Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBruno Coudoin <bcoudoin@src.gnome.org>2006-03-01 00:34:43 (GMT)
committer Bruno Coudoin <bcoudoin@src.gnome.org>2006-03-01 00:34:43 (GMT)
commit0efd36e66326eb6a04180d87c19dea62032f690a (patch)
tree5910f1fe2ce63fb6871b96af21d6b104950c1ad0
parent2a8c07d1ca5c4da91fac5e517bcb74b64ef7fe23 (diff)
MERGE gcompris_7-4 UNTESTED
MERGE gcompris_7-4 UNTESTED
-rw-r--r--ChangeLog1247
-rw-r--r--boards/Makefile.am20
-rw-r--r--boards/boardicons/README1
-rw-r--r--boards/boardicons/magic_hat_minus.pngbin0 -> 6594 bytes
-rw-r--r--boards/boardicons/magic_hat_plus.pngbin0 -> 6976 bytes
-rw-r--r--boards/boardicons/wordprocessor.pngbin0 -> 8742 bytes
-rw-r--r--boards/geography.xml.in1
-rw-r--r--boards/geography/Makefile.am3
-rw-r--r--boards/geography/board6_0.xml.in23
-rw-r--r--boards/geography/germany_region/back.pngbin0 -> 17285 bytes
-rw-r--r--boards/geography/germany_region/baden-wuerttemberg.pngbin0 -> 5452 bytes
-rw-r--r--boards/geography/germany_region/bayern.pngbin0 -> 7173 bytes
-rw-r--r--boards/geography/germany_region/berlin.pngbin0 -> 871 bytes
-rw-r--r--boards/geography/germany_region/brandenburg.pngbin0 -> 5458 bytes
-rw-r--r--boards/geography/germany_region/bremen.pngbin0 -> 1028 bytes
-rw-r--r--boards/geography/germany_region/hamburg.pngbin0 -> 1159 bytes
-rw-r--r--boards/geography/germany_region/hessen.pngbin0 -> 3989 bytes
-rw-r--r--boards/geography/germany_region/mecklenburg-vorpommern.pngbin0 -> 7179 bytes
-rw-r--r--boards/geography/germany_region/niedersachsen.pngbin0 -> 7213 bytes
-rw-r--r--boards/geography/germany_region/nordrhein-westfalen.pngbin0 -> 6784 bytes
-rw-r--r--boards/geography/germany_region/rheinland-pfalz.pngbin0 -> 4850 bytes
-rw-r--r--boards/geography/germany_region/saarland.pngbin0 -> 2020 bytes
-rw-r--r--boards/geography/germany_region/sachsen-anhalt.pngbin0 -> 4881 bytes
-rw-r--r--boards/geography/germany_region/sachsen.pngbin0 -> 4070 bytes
-rw-r--r--boards/geography/germany_region/schleswig_holstein.pngbin0 -> 5813 bytes
-rw-r--r--boards/geography/germany_region/target_baden-wuerttemberg.pngbin0 -> 157 bytes
-rw-r--r--boards/geography/germany_region/target_bayern.pngbin0 -> 162 bytes
-rw-r--r--boards/geography/germany_region/target_berlin.pngbin0 -> 129 bytes
-rw-r--r--boards/geography/germany_region/target_brandenburg.pngbin0 -> 156 bytes
-rw-r--r--boards/geography/germany_region/target_bremen.pngbin0 -> 131 bytes
-rw-r--r--boards/geography/germany_region/target_hamburg.pngbin0 -> 131 bytes
-rw-r--r--boards/geography/germany_region/target_hessen.pngbin0 -> 153 bytes
-rw-r--r--boards/geography/germany_region/target_mecklenburg-vorpommern.pngbin0 -> 153 bytes
-rw-r--r--boards/geography/germany_region/target_niedersachsen.pngbin0 -> 161 bytes
-rw-r--r--boards/geography/germany_region/target_nordrhein-westfalen.pngbin0 -> 158 bytes
-rw-r--r--boards/geography/germany_region/target_rheinland-pfalz.pngbin0 -> 148 bytes
-rw-r--r--boards/geography/germany_region/target_saarland.pngbin0 -> 129 bytes
-rw-r--r--boards/geography/germany_region/target_sachsen-anhalt.pngbin0 -> 149 bytes
-rw-r--r--boards/geography/germany_region/target_sachsen.pngbin0 -> 147 bytes
-rw-r--r--boards/geography/germany_region/target_schleswig_holstein.pngbin0 -> 150 bytes
-rw-r--r--boards/geography/germany_region/target_thueringen.pngbin0 -> 145 bytes
-rw-r--r--boards/geography/germany_region/thueringen.pngbin0 -> 3661 bytes
-rw-r--r--boards/magic_hat/hat-point.pngbin0 -> 20896 bytes
-rw-r--r--boards/magic_hat/hat.pngbin0 -> 21187 bytes
-rw-r--r--boards/magic_hat/magic_hat_minus.pngbin0 -> 6594 bytes
-rw-r--r--boards/magic_hat/magic_hat_minus_bg.pngbin0 -> 15631 bytes
-rw-r--r--boards/magic_hat/magic_hat_plus.pngbin0 -> 6976 bytes
-rw-r--r--boards/magic_hat/magic_hat_plus_bg.pngbin0 -> 15652 bytes
-rw-r--r--boards/magic_hat/star-clear.pngbin0 -> 23543 bytes
-rw-r--r--boards/magic_hat/star1.pngbin0 -> 11869 bytes
-rw-r--r--boards/magic_hat/star2.pngbin0 -> 23027 bytes
-rw-r--r--boards/magic_hat/star3.pngbin0 -> 25059 bytes
-rw-r--r--boards/magic_hat_minus.xml.in19
-rw-r--r--boards/magic_hat_plus.xml.in19
-rw-r--r--boards/memory_add.xml.in19
-rw-r--r--boards/memory_add_minus.xml.in19
-rw-r--r--boards/memory_add_minus_mult_div.xml.in19
-rw-r--r--boards/memory_add_minus_mult_div_tux.xml.in19
-rw-r--r--boards/memory_add_minus_tux.xml.in19
-rw-r--r--boards/memory_add_tux.xml.in19
-rw-r--r--boards/memory_div.xml.in19
-rw-r--r--boards/memory_div_tux.xml.in19
-rw-r--r--boards/memory_minus.xml.in19
-rw-r--r--boards/memory_minus_tux.xml.in19
-rw-r--r--boards/memory_mult.xml.in19
-rw-r--r--boards/memory_mult_div.xml.in19
-rw-r--r--boards/memory_mult_div_tux.xml.in19
-rw-r--r--boards/memory_mult_tux.xml.in19
-rw-r--r--boards/memory_op_group.xml.in12
-rw-r--r--boards/memory_op_group_tux.xml.in12
-rw-r--r--boards/menu2.xml.in28
-rw-r--r--boards/skins/gartoon/gcompris-menu2bg.pngbin0 -> 105351 bytes
-rw-r--r--boards/wordprocessor.xml.in19
-rw-r--r--configure.in2
-rw-r--r--po/TRANSLATORS.README2
-rw-r--r--src/boards/Makefile.am13
-rw-r--r--src/boards/awele.c545
-rw-r--r--src/boards/awele.h5
-rw-r--r--src/boards/awele_alphaBeta.c356
-rw-r--r--src/boards/awele_utils.c325
-rw-r--r--src/boards/awele_utils.h31
-rw-r--r--src/boards/click_on_letter.c50
-rw-r--r--src/boards/colors.c42
-rw-r--r--src/boards/gletters.c38
-rw-r--r--src/boards/imageid.c32
-rw-r--r--src/boards/magic_hat.c730
-rw-r--r--src/boards/memory.c442
-rw-r--r--src/boards/menu2.c1047
-rw-r--r--src/boards/missingletter.c27
-rw-r--r--src/boards/py-gcompris-profile.c3
-rw-r--r--src/boards/py-mod-anim.c4
-rw-r--r--src/boards/py-mod-gcompris.c5
-rw-r--r--src/boards/python/gnumch.py4
-rw-r--r--src/boards/python/pythontest.py9
-rw-r--r--src/boards/reading.c31
-rw-r--r--src/boards/shapegame.c34
-rw-r--r--src/boards/smallnumbers.c64
-rw-r--r--src/boards/wordprocessor.c605
-rw-r--r--src/gcompris/Makefile.am3
-rw-r--r--src/gcompris/anim.c7
-rw-r--r--src/gcompris/bar.c22
-rw-r--r--src/gcompris/board_config.c132
-rw-r--r--src/gcompris/gameutil.c8
-rw-r--r--src/gcompris/gcompris.c1
-rw-r--r--src/gcompris/gcompris.h13
-rw-r--r--src/gcompris/gcompris_alphabeta.c131
-rw-r--r--src/gcompris/gcompris_alphabeta.h62
-rw-r--r--src/gcompris/gcompris_confirm.c491
-rw-r--r--src/gcompris/properties.c3
-rw-r--r--src/gcompris/properties.h3
-rwxr-xr-xtools/list_missing_sounds.sh45
-rw-r--r--tools/shapegame/HOWTO114
-rw-r--r--tools/shapegame/Makefile2
-rw-r--r--tools/shapegame/dt/.cvsignore1
-rw-r--r--tools/shapegame/dt/Makefile23
-rw-r--r--tools/shapegame/dt/README34
-rw-r--r--tools/shapegame/dt/dt.cpp58
-rw-r--r--tools/shapegame/dt/dt.h115
-rw-r--r--tools/shapegame/dt/image.h101
-rw-r--r--tools/shapegame/dt/imconv.h177
-rw-r--r--tools/shapegame/dt/imutil.h66
-rw-r--r--tools/shapegame/dt/input.pbmbin0 -> 5014 bytes
-rw-r--r--tools/shapegame/dt/misc.h65
-rw-r--r--tools/shapegame/dt/pnmfile.h211
-rw-r--r--tools/shapegame/nice_target_spot.cpp126
-rw-r--r--tools/shapegame/test.pbmbin0 -> 120 bytes
126 files changed, 7229 insertions, 901 deletions
diff --git a/ChangeLog b/ChangeLog
index 43e44d4..5f3c234 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,709 @@
2006-03-01 Bruno coudoin <bruno.coudoin@free.fr>
+ *** MERGE OF BRANCH gcompris_7_4 ***
+
+ * boards/Makefile.am:
+ * boards/boardicons/README:
+ * boards/boardicons/magic_hat_minus.png:
+ * boards/boardicons/magic_hat_plus.png:
+ * boards/boardicons/wordprocessor.png:
+ * boards/geography.xml.in:
+ * boards/geography/Makefile.am:
+ * boards/geography/board6_0.xml.in:
+ * boards/geography/germany_region/back.png:
+ * boards/geography/germany_region/baden-wuerttemberg.png:
+ * boards/geography/germany_region/bayern.png:
+ * boards/geography/germany_region/berlin.png:
+ * boards/geography/germany_region/brandenburg.png:
+ * boards/geography/germany_region/bremen.png:
+ * boards/geography/germany_region/hamburg.png:
+ * boards/geography/germany_region/hessen.png:
+ * boards/geography/germany_region/mecklenburg-vorpommern.png:
+ * boards/geography/germany_region/niedersachsen.png:
+ * boards/geography/germany_region/nordrhein-westfalen.png:
+ * boards/geography/germany_region/rheinland-pfalz.png:
+ * boards/geography/germany_region/saarland.png:
+ * boards/geography/germany_region/sachsen-anhalt.png:
+ * boards/geography/germany_region/sachsen.png:
+ * boards/geography/germany_region/schleswig_holstein.png:
+ * boards/geography/germany_region/target_baden-wuerttemberg.png:
+ * boards/geography/germany_region/target_bayern.png:
+ * boards/geography/germany_region/target_berlin.png:
+ * boards/geography/germany_region/target_brandenburg.png:
+ * boards/geography/germany_region/target_bremen.png:
+ * boards/geography/germany_region/target_hamburg.png:
+ * boards/geography/germany_region/target_hessen.png:
+ * boards/geography/germany_region/target_mecklenburg-vorpommern.png
+ :
+ * boards/geography/germany_region/target_niedersachsen.png:
+ * boards/geography/germany_region/target_nordrhein-westfalen.png:
+ * boards/geography/germany_region/target_rheinland-pfalz.png:
+ * boards/geography/germany_region/target_saarland.png:
+ * boards/geography/germany_region/target_sachsen-anhalt.png:
+ * boards/geography/germany_region/target_sachsen.png:
+ * boards/geography/germany_region/target_schleswig_holstein.png:
+ * boards/geography/germany_region/target_thueringen.png:
+ * boards/geography/germany_region/thueringen.png:
+ * boards/magic_hat/hat-point.png:
+ * boards/magic_hat/hat.png:
+ * boards/magic_hat/magic_hat_minus.png:
+ * boards/magic_hat/magic_hat_minus_bg.png:
+ * boards/magic_hat/magic_hat_plus.png:
+ * boards/magic_hat/magic_hat_plus_bg.png:
+ * boards/magic_hat/star-clear.png:
+ * boards/magic_hat/star1.png:
+ * boards/magic_hat/star2.png:
+ * boards/magic_hat/star3.png:
+ * boards/magic_hat_minus.xml.in:
+ * boards/magic_hat_plus.xml.in:
+ * boards/memory_add.xml.in:
+ * boards/memory_add_minus.xml.in:
+ * boards/memory_add_minus_mult_div.xml.in:
+ * boards/memory_add_minus_mult_div_tux.xml.in:
+ * boards/memory_add_minus_tux.xml.in:
+ * boards/memory_add_tux.xml.in:
+ * boards/memory_mult.xml.in:
+ * boards/memory_mult_div.xml.in:
+ * boards/memory_mult_div_tux.xml.in:
+ * boards/memory_mult_tux.xml.in:
+ * boards/memory_op_group.xml.in:
+ * boards/memory_op_group_tux.xml.in:
+ * boards/menu2.xml.in:
+ * boards/skins/gartoon/gcompris-menu2bg.png:
+ * boards/wordprocessor.xml.in:
+ * configure.in:
+ * po/ChangeLog:
+ * po/TRANSLATORS.README:
+ * src/boards/Makefile.am:
+ * src/boards/awele.c: (pause_board), (start_board), (end_board),
+ (repeat), (set_level), (awele_next_level), (awele_create_item),
+ (game_won), (to_computer), (buttonClick):
+ * src/boards/awele.h:
+ * src/boards/awele_alphaBeta.c: (eval), (eval_to_null),
+ (eval_to_best_capture), (firstChild), (nextSibling), (free_awale),
+ (think):
+ * src/boards/awele_utils.c: (isOpponentHungry), (moveAwale),
+ (randplay), (diedOfHunger):
+ * src/boards/awele_utils.h:
+ * src/boards/click_on_letter.c: (start_board), (sounds_are_fine),
+ (conf_ok), (config_start):
+ * src/boards/colors.c: (conf_ok), (colors_config_start),
+ (start_board):
+ * src/boards/gletters.c: (level_set_score), (conf_ok),
+ (gletter_config_start):
+ * src/boards/imageid.c: (start_board), (conf_ok), (config_start):
+ * src/boards/magic_hat.c: (pause_board), (start_board),
+ (end_board), (process_ok), (set_level), (is_our_board),
+ (magic_hat_next_level), (magic_hat_destroy_all_items),
+ (magic_hat_create_item), (finished), (game_won), (draw_frame),
+ (draw_table), (draw_hat), (place_item), (item_event), (hat_event),
+ (nb_list), (move_stars), (close_hat), (smooth_move):
+ * src/boards/memory.c: (get_random_token), (start_board),
+ (memory_destroy_all_items), (get_image), (create_item),
+ (compare_card):
+ * src/boards/menu2.c: (menu_pause), (menu_start), (create_panel),
+ (display_section), (menu_end), (menu_is_our_board), (menu_config),
+ (display_board_icon), (next_spot), (menu_create_item),
+ (item_event), (set_content), (create_info_area), (free_stuff),
+ (get_ratio), (create_top), (display_welcome), (menu_config_start),
+ (menu_config_stop):
+ * src/boards/missingletter.c: (start_board), (conf_ok),
+ (config_start):
+ * src/boards/py-gcompris-profile.c:
+ (gcompris_new_pyGcomprisProfileObject):
+ * src/boards/py-mod-anim.c: (Animation_free), (AnimCanvas_free):
+ * src/boards/py-mod-gcompris.c: (pyGcomprisConfCallback):
+ * src/boards/python/gnumch.py:
+ * src/boards/python/pythontest.py:
+ * src/boards/reading.c: (start_board), (conf_ok),
+ (reading_config_start):
+ * src/boards/shapegame.c: (start_board), (conf_ok), (config_start):
+ * src/boards/smallnumbers.c: (start_board),
+ (smallnumbers_create_item), (conf_ok), (smallnumber_config_start):
+ * src/boards/wordprocessor.c: (pause_board), (start_board),
+ (end_board), (set_level), (is_our_board),
+ (wordprocessor_destroy_all_items), (wordprocessor_create),
+ (display_style_buttons), (item_event), (create_tags),
+ (set_default_style), (display_style_selector),
+ (item_event_style_selection), (key_press_event):
+ * src/gcompris/Makefile.am:
+ * src/gcompris/anim.c: (gcompris_deactivate_animation),
+ (anim_tick):
+ * src/gcompris/bar.c: (item_event_bar), (confirm_quit):
+ * src/gcompris/board_config.c: (gcompris_close_board_conf),
+ (gcompris_response_board_conf), (gcompris_configuration_window),
+ (gcompris_change_locale):
+ * src/gcompris/gameutil.c: (gcompris_get_menulist):
+ * src/gcompris/gcompris.c: (gcompris_init):
+ * src/gcompris/gcompris.h:
+ * src/gcompris/gcompris_alphabeta.c: (gcompris_alphabeta):
+ * src/gcompris/gcompris_alphabeta.h:
+ * src/gcompris/gcompris_confirm.c: (gcompris_confirm),
+ (gcompris_confirm_stop), (display_confirm), (free_stuff),
+ (set_content), (button_event):
+ * src/gcompris/properties.c: (gcompris_properties_new):
+ * src/gcompris/properties.h:
+ * tools/list_missing_sounds.sh:
+ * tools/shapegame/HOWTO:
+ * tools/shapegame/Makefile:
+ * tools/shapegame/dt/.cvsignore:
+ * tools/shapegame/dt/Makefile:
+ * tools/shapegame/dt/README:
+ * tools/shapegame/dt/dt.cpp:
+ * tools/shapegame/dt/dt.h:
+ * tools/shapegame/dt/image.h:
+ * tools/shapegame/dt/imconv.h:
+ * tools/shapegame/dt/imutil.h:
+ * tools/shapegame/dt/input.pbm:
+ * tools/shapegame/dt/misc.h:
+ * tools/shapegame/dt/pnmfile.h:
+ * tools/shapegame/nice_target_spot.cpp:
+ * tools/shapegame/test.pbm:
+
+2006-02-13 Yves Combe <yves@ycombe.net>
+
+ fix bug in gcompris_sound_controller signal definition. Apparently causes crash in dapper Ubuntu.
+
+ * po/Makefile.in.in:
+ * src/gcompris/soundutil.c: (default_sound_played_signal_handler),
+ (gcompris_sound_class_init):
+
+2006-02-11 Yves Combe <yves@ycombe.net>
+
+ test on size of db file, to create tables if it's 0
+ (correction of null-sized db due to USE_SQLITE bug).
+
+ * src/gcompris/gcompris_db.c: (gcompris_db_init):
+
+2006-02-09 Yves Combe <yves@ycombe.net>
+
+ minor fix (hat double click and highlight focus).
+
+ * src/boards/magic_hat.c: (draw_hat), (hat_event):
+
+2006-02-09 Yves Combe <yves@ycombe.net>
+
+ new versions of magic hat by Marc Brun: addition and substraction.
+
+ * boards/Makefile.am:
+ * boards/boardicons/magic_hat.png:
+ * boards/boardicons/magic_hat_minus.png:
+ * boards/boardicons/magic_hat_plus.png:
+ * boards/magic_hat.xml.in:
+ * boards/magic_hat/magic_hat_minus.png:
+ * boards/magic_hat/magic_hat_minus_bg.png:
+ * boards/magic_hat/magic_hat_plus.png:
+ * boards/magic_hat/magic_hat_plus_bg.png:
+ * boards/magic_hat/star.png:
+ * boards/magic_hat_minus.xml.in:
+ * boards/magic_hat_plus.xml.in:
+ * configure.in:
+ * src/boards/magic_hat.c: (start_board), (process_ok),
+ (magic_hat_create_item), (draw_frame), (draw_hat), (place_item),
+ (item_event), (hat_event), (move_stars), (close_hat),
+ (smooth_move):
+
+2006-02-09 Yves Combe <yves@ycombe.net>
+
+ fix bug in memory_div and emory_mult_div.
+ fix font size and font color.
+
+ * src/boards/memory.c: (get_image), (create_item):
+
+2006-02-09 Yves Combe <yves@ycombe.net>
+
+ fix bug, change font size following level for memory operations activities.
+
+ * src/boards/memory.c: (get_random_token), (start_board),
+ (create_item), (compare_card):
+
+2006-02-09 Yves Combe <yves@ycombe.net>
+
+ fix animation was launched after winning.
+ add memory based mathematicals operations boards.
+
+ * boards/Makefile.am:
+ * boards/memory_add.xml.in:
+ * boards/memory_add_minus.xml.in:
+ * boards/memory_add_minus_mult_div.xml.in:
+ * boards/memory_add_minus_mult_div_tux.xml.in:
+ * boards/memory_add_minus_tux.xml.in:
+ * boards/memory_add_tux.xml.in:
+ * boards/memory_mult.xml.in:
+ * boards/memory_mult_div.xml.in:
+ * boards/memory_mult_div_tux.xml.in:
+ * boards/memory_mult_tux.xml.in:
+ * boards/memory_op_group.xml.in:
+ * boards/memory_op_group_tux.xml.in:
+ * src/boards/awele.c: (buttonClick):
+ * src/boards/memory.c: (get_random_token), (start_board),
+ (memory_destroy_all_items), (get_image), (create_item),
+ (compare_card):
+
+2006-02-08 Yves Combe <yves@ycombe.net>
+
+ fix depth search. Must not to be odd in best difference evaluation!
+
+ * src/boards/awele_alphaBeta.c: (think):
+
+2006-02-08 Yves Combe <yves@ycombe.net>
+
+ add a reset of item->canvas after destroy.
+
+ * src/gcompris/anim.c: (gcompris_deactivate_animation):
+
+2006-02-08 Yves Combe <yves@ycombe.net>
+
+ Some fix in animation api/usage.
+
+ * src/boards/awele_alphaBeta.c: (think):
+ * src/boards/py-mod-anim.c: (Animation_free), (AnimCanvas_free):
+ * src/boards/python/gnumch.py:
+ * src/gcompris/anim.c: (anim_tick):
+
+2006-02-07 Bruno coudoin <bruno.coudoin@free.fr>
+
+ * src/boards/advanced_colors.c: (add_xml_data): fixed to check properly for long locale (e.g. pt_BR)
+ * src/boards/read_colors.c: (add_xml_data), (parse_doc): -
+ * src/boards/python/melody.py: added a dialog if run without sound fx activated
+ changed to use the reload icon instead of mouth sign for the repeat.
+
+2006-02-07 Yves Combe <yves@ycombe.net>
+
+ fix anim api to destroy the item canvas on deactivate.
+ fix gnumch to not crash with that (del anim before quit)
+ fix anim in awele.
+
+ * src/boards/awele.c: (pause_board), (repeat), (set_level),
+ (to_computer), (buttonClick):
+ * src/boards/awele_utils.c: (diedOfHunger):
+ * src/boards/python/gnumch.py:
+ * src/gcompris/anim.c: (gcompris_deactivate_animation):
+
+2006-02-07 Yves Combe,,, <yves@ycombe.net>
+
+ add Grand slam rule for capture (no capture
+ if that let opponent hungry).
+ add correct rule for hunger end of games (untested).
+
+ * src/boards/awele.c: (to_computer):
+ * src/boards/awele_utils.c: (moveAwale), (diedOfHunger):
+ * src/boards/awele_utils.h:
+
+2006-02-07 Yves Combe <yves@ycombe.net>
+
+ fix crash with animation on next_level and repeat.
+ fix strings i18n. Needs review of strings.
+
+ * src/boards/awele.c: (pause_board), (repeat), (set_level),
+ (awele_create_item), (to_computer), (buttonClick):
+
+2006-02-07 Yves Combe <yves@ycombe.net>
+
+ add animation like in connect4 when computer think.
+
+ * src/boards/awele.c: (pause_board), (start_board), (end_board),
+ (awele_next_level), (to_computer), (buttonClick):
+
+2006-02-06 Yves Combe <yves@ycombe.net>
+
+ clean code from unused fucntion
+
+ * src/boards/awele.c:
+ * src/boards/awele.h:
+
+2006-02-06 Yves Combe <yves@ycombe.net>
+
+ change evaluation fonction usage in awele,
+ to make it easier in level 1-4.
+ difficulty:
+ - level 1-2 -> random
+ - level 3-4 -> best computer capture, depth 1.
+ - level 5-6 -> best difference in capture, depth 1.
+ - level 7-8 -> best difference in capture, depth 2.
+ - level 9 -> best difference in capture, depth 3.
+ clean from g_warning.
+ change first player: computer begins at level 2-4-6-8.
+
+ * src/boards/awele.c: (start_board), (repeat), (set_level),
+ (awele_next_level), (game_won), (to_computer),
+ (updateCapturedBeans):
+ * src/boards/awele_alphaBeta.c: (eval_to_null),
+ (eval_to_best_capture), (think):
+ * src/boards/awele_utils.c: (moveAwale):
+ * src/gcompris/gcompris_alphabeta.c: (gcompris_alphabeta):
+
+2006-02-06 Yves Combe <yves@ycombe.net>
+
+ awele manily fixed.
+ TODO: change first player.
+ TODO: add correct rule in case of end by hungry player.
+
+ * src/boards/awele.c: (pause_board), (start_board),
+ (awele_next_level), (awele_create_item), (to_computer),
+ (buttonClick), (updateNbBeans), (updateCapturedBeans),
+ (buttonNewGameClick):
+ * src/boards/awele.h:
+ * src/boards/awele_alphaBeta.c: (firstChild), (think):
+ * src/boards/awele_utils.c: (moveAwale):
+ * src/gcompris/gcompris_alphabeta.c: (gcompris_alphabeta):
+
+2006-02-06 Yves Combe <yves@ycombe.net>
+
+ add generic minmax(alphabeta) function.
+ use it in awale.
+ Need more tests.
+
+ * src/boards/awele.c: (start_board), (awele_create_item),
+ (to_computer), (buttonClick), (updateCapturedBeans):
+ * src/boards/awele_alphaBeta.c: (eval), (firstChild),
+ (nextSibling), (free_awale), (think):
+ * src/boards/awele_utils.c: (isOpponentHungry), (moveAwale),
+ (randplay):
+ * src/boards/awele_utils.h:
+ * src/gcompris/Makefile.am:
+ * src/gcompris/gcompris.h:
+ * src/gcompris/gcompris_alphabeta.c: (gcompris_alphabeta):
+ * src/gcompris/gcompris_alphabeta.h:
+
+2006-02-05 Bruno coudoin <bruno.coudoin@free.fr>
+
+ Changed background entry color to white. The blue background color
+ was no more working for me for no reason.
+
+ Improved wordprocessor. Now handle a single fixed theme coherently.
+
+ * po/ChangeLog:
+ * src/boards/python/guessnumber.py:
+ * src/boards/wordprocessor.c: (display_style_buttons),
+ (item_event), (create_tags), (set_default_style),
+ (key_press_event):
+
+2006-02-03 Bruno coudoin <bruno.coudoin@free.fr>
+
+ - merged awele with HEAD.
+
+ * boards/awele/awele_frame.jpg:
+ * boards/awele/awele_frame.png:
+ * boards/awele/awele_frame_avec_messages.png:
+ * boards/awele/nv_partie.png:
+ * boards/awele/nv_partie_clic.png:
+ * boards/awele/nv_partie_notify.png:
+ * po/TRANSLATORS.README:
+ * src/boards/awele.c: (start_board), (repeat), (awele_create_item),
+ (buttonNewGameClick):
+ * src/boards/awele.h:
+ * src/boards/python/guessnumber.py: fix title alignement from HEAD.
+ * src/boards/smallnumbers.c: (smallnumbers_create_item): from HEAD, use bar dice.
+ * src/boards/wordprocessor.c: (wordprocessor_create),
+ (display_style_buttons), (item_event), (create_tags),
+ (key_press_event):
+
+2006-02-03 Yves Combe,,, <yves@ycombe.net>
+
+ fix level display and usage in awele.
+ add winning detection at 25 beans-> display bonus and new game.
+
+ * src/boards/awele.c: (start_board), (set_level),
+ (awele_create_item):
+
+2006-02-02 Yves Combe <yves@ycombe.net>
+
+ Display bonus and end of game when 25 beans are captured.
+
+ * src/boards/awele.c: (updateCapturedBeans):
+
+2006-02-02 Bruno coudoin <bruno.coudoin@free.fr>
+
+
+ * tools/list_missing_sounds.sh: By Jose Jorge. A nice utility to compare the locale
+ translations status of voices to English.
+
+2006-01-31 Yves Combe,,, <yves@ycombe.net>
+
+ fix configurables boards in c to configure from bar.
+
+ * src/boards/colors.c: (conf_ok), (colors_config_start),
+ (start_board):
+ * src/boards/gletters.c: (level_set_score), (conf_ok),
+ (gletter_config_start):
+ * src/boards/imageid.c: (config_start):
+ * src/boards/missingletter.c: (config_start):
+ * src/boards/reading.c: (reading_config_start):
+ * src/boards/smallnumbers.c: (start_board),
+ (smallnumbers_create_item), (conf_ok), (smallnumber_config_start):
+
+2006-01-31 Yves Combe <yves@ycombe.net>
+
+ fix /reading boards to configure from bar.
+
+ * src/boards/click_on_letter.c: (conf_ok):
+ * src/boards/imageid.c: (start_board), (conf_ok), (config_start):
+ * src/boards/missingletter.c: (start_board), (conf_ok):
+ * src/boards/python/pythontest.py:
+ * src/boards/reading.c: (start_board), (conf_ok),
+ (reading_config_start):
+ * src/boards/shapegame.c: (conf_ok):
+
+2006-01-30 Bruno coudoin <bruno.coudoin@free.fr>
+
+ - Added copyright header following formal argeement of
+ the author Pedro Felzenszwalb <pff@cs.uchicago.edu>
+
+ * tools/shapegame/.cvsignore:
+ * tools/shapegame/dt/.cvsignore:
+ * tools/shapegame/dt/README:
+ * tools/shapegame/dt/dt.cpp:
+ * tools/shapegame/dt/dt.h:
+ * tools/shapegame/dt/image.h:
+ * tools/shapegame/dt/imconv.h:
+ * tools/shapegame/dt/imutil.h:
+ * tools/shapegame/dt/misc.h:
+ * tools/shapegame/dt/pnmfile.h:
+ * tools/shapegame/nice_target_spot.cpp:
+
+2006-01-30 Yves Combe <yves@ycombe.net>
+
+ fix configuration window was not visible in fullscreen mode, using gtk_dialog.
+
+ * src/gcompris/board_config.c: (gcompris_close_board_conf),
+ (gcompris_response_board_conf), (gcompris_configuration_window):
+
+2006-01-30 Bruno coudoin <bruno.coudoin@free.fr>
+
+ - Added the German map by Olaf Ronneberger.
+ - Added in tools/shapegame/ a utility to create shapegame activity
+
+ * boards/geography.xml.in:
+ * boards/geography/Makefile.am:
+ * boards/geography/board6_0.xml.in:
+ * boards/geography/germany_region/back.png:
+ * boards/geography/germany_region/baden-wuerttemberg.png:
+ * boards/geography/germany_region/bayern.png:
+ * boards/geography/germany_region/berlin.png:
+ * boards/geography/germany_region/brandenburg.png:
+ * boards/geography/germany_region/bremen.png:
+ * boards/geography/germany_region/hamburg.png:
+ * boards/geography/germany_region/hessen.png:
+ * boards/geography/germany_region/mecklenburg-vorpommern.png:
+ * boards/geography/germany_region/niedersachsen.png:
+ * boards/geography/germany_region/nordrhein-westfalen.png:
+ * boards/geography/germany_region/rheinland-pfalz.png:
+ * boards/geography/germany_region/saarland.png:
+ * boards/geography/germany_region/sachsen-anhalt.png:
+ * boards/geography/germany_region/sachsen.png:
+ * boards/geography/germany_region/schleswig_holstein.png:
+ * boards/geography/germany_region/target_baden-wuerttemberg.png:
+ * boards/geography/germany_region/target_bayern.png:
+ * boards/geography/germany_region/target_berlin.png:
+ * boards/geography/germany_region/target_brandenburg.png:
+ * boards/geography/germany_region/target_bremen.png:
+ * boards/geography/germany_region/target_hamburg.png:
+ * boards/geography/germany_region/target_hessen.png:
+ * boards/geography/germany_region/target_mecklenburg-vorpommern.png
+ :
+ * boards/geography/germany_region/target_niedersachsen.png:
+ * boards/geography/germany_region/target_nordrhein-westfalen.png:
+ * boards/geography/germany_region/target_rheinland-pfalz.png:
+ * boards/geography/germany_region/target_saarland.png:
+ * boards/geography/germany_region/target_sachsen-anhalt.png:
+ * boards/geography/germany_region/target_sachsen.png:
+ * boards/geography/germany_region/target_schleswig_holstein.png:
+ * boards/geography/germany_region/target_thueringen.png:
+ * boards/geography/germany_region/thueringen.png:
+ * src/boards/wordprocessor.c: (wordprocessor_create),
+ (display_style_buttons), (item_event), (create_tags):
+ * src/gcompris/gcompris_confirm.c:
+ * tools/shapegame/HOWTO:
+ * tools/shapegame/Makefile:
+ * tools/shapegame/dt/Makefile:
+ * tools/shapegame/dt/README:
+ * tools/shapegame/dt/dt.cpp:
+ * tools/shapegame/dt/dt.h:
+ * tools/shapegame/dt/image.h:
+ * tools/shapegame/dt/imconv.h:
+ * tools/shapegame/dt/imutil.h:
+ * tools/shapegame/dt/input.pbm:
+ * tools/shapegame/dt/misc.h:
+ * tools/shapegame/dt/pnmfile.h:
+ * tools/shapegame/nice_target_spot.cpp:
+ * tools/shapegame/test.pbm:
+
+2006-01-29 Yves Combe <yves@ycombe.net>
+
+ fix click_on_letter and shapegame (imagename) to configure from bar.
+
+ * src/boards/click_on_letter.c: (sounds_are_fine), (conf_ok),
+ (config_start):
+ * src/boards/py-gcompris-profile.c:
+ (gcompris_new_pyGcomprisProfileObject):
+ * src/boards/py-mod-gcompris.c: (pyGcomprisConfCallback):
+ * src/boards/shapegame.c: (start_board), (conf_ok), (config_start):
+ * src/gcompris/board_config.c: (gcompris_close_board_conf),
+ (gcompris_apply_board_conf), (gcompris_configuration_window),
+ (gcompris_change_locale):
+
+2006-01-29 Yves Combe <yves@ycombe.net>
+
+ Add board config_start call by the bar.
+ Click on letter fixed to use that. Menu2 too.
+ Others boards needs fix too.
+
+ * src/boards/click_on_letter.c: (start_board), (conf_ok),
+ (config_start):
+ * src/boards/menu2.c: (menu_config_start), (menu_config_stop):
+ * src/gcompris/bar.c: (item_event_bar):
+
+2006-01-29 Yves Combe,,, <yves@ycombe.net>
+
+ menu2 is now default menu.
+ menu2 works now with -l option
+
+ * src/boards/Makefile.am:
+ * src/boards/menu2.c: (create_panel), (menu_is_our_board),
+ (create_top):
+ * src/gcompris/gcompris.c: (gcompris_init):
+
+2006-01-29 Yves Combe <yves@ycombe.net>
+
+ Suppress event connection on text.
+ Segfault seems to be fixed.
+
+ * src/gcompris/gcompris_confirm.c: (gcompris_confirm_stop),
+ (display_confirm):
+
+2006-01-27 Yves Combe <yves@ycombe.net>
+
+ fix unpause bug in confirm.
+
+ * src/gcompris/gcompris_confirm.c: (display_confirm):
+
+2006-01-26 Yves Combe <yves@ycombe.net>
+
+ small memory fix: pixbuf not freed after use.
+
+ * src/gcompris/gcompris_confirm.c: (display_confirm):
+
+2006-01-25 Yves Combe <yves@ycombe.net>
+
+ fix colors in confirmation window.
+
+ * src/gcompris/gcompris_confirm.c: (display_confirm):
+
+2006-01-25 Yves Combe <yves@ycombe.net>
+
+ add a confirmation popup on quit. Yet colors problem because of shadow.
+
+ * src/boards/menu2.c: (menu_create_item):
+ * src/gcompris/Makefile.am:
+ * src/gcompris/bar.c: (item_event_bar), (confirm_quit):
+ * src/gcompris/gcompris.h:
+ * src/gcompris/gcompris_confirm.c: (gcompris_confirm),
+ (gcompris_confirm_stop), (display_confirm), (free_stuff),
+ (set_content), (button_event):
+
+2006-01-25 Bruno coudoin <bruno.coudoin@free.fr>
+
+ First release of a new activity, the wordprocessor.
+ Uncomplete yet.
+
+ * boards/Makefile.am:
+ * boards/boardicons/README:
+ * boards/boardicons/wordprocessor.png:
+ * boards/wordprocessor.xml.in:
+ * src/boards/Makefile.am:
+ * src/boards/wordprocessor.c: (pause_board), (start_board),
+ (end_board), (set_level), (is_our_board),
+ (wordprocessor_destroy_all_items), (wordprocessor_create),
+ (item_event):
+
+2006-01-23 Yves Combe <yves@ycombe.net>
+
+ constraint resize icon.
+
+ * src/boards/menu2.c: (menu_create_item):
+
+2006-01-23 Yves Combe <yves@ycombe.net>
+
+ add background for menu2, with the differents zones.
+
+ * boards/skins/gartoon/gcompris-menu2bg.png:
+ * src/boards/menu2.c: (menu_start):
+
+2006-01-23 Yves Combe <yves@ycombe.net>
+
+ fix segfault i had in level 4 5 6 of magic hat.
+
+ * src/boards/magic_hat.c: (place_item):
+
+2006-01-23 Yves Combe <yves@ycombe.net>
+
+ fix bug in menu2.
+ minor update in magic_hat (MB)
+
+ * src/boards/magic_hat.c: (hat_event):
+ * src/boards/menu2.c: (menu_start), (display_section),
+ (item_event), (create_top):
+
+2006-01-22 Yves Combe <yves@ycombe.net>
+
+ new activity magic_hat by Marc Brun.
+
+ * boards/Makefile.am:
+ * boards/boardicons/magic_hat.png:
+ * boards/magic_hat.xml.in:
+ * boards/magic_hat/hat-point.png:
+ * boards/magic_hat/hat.png:
+ * boards/magic_hat/magic_hat-bg.png:
+ * boards/magic_hat/star-clear.png:
+ * boards/magic_hat/star.png:
+ * boards/magic_hat/star1.png:
+ * boards/magic_hat/star2.png:
+ * boards/magic_hat/star3.png:
+ * src/boards/Makefile.am:
+ * src/boards/magic_hat.c: (pause_board), (start_board),
+ (end_board), (process_ok), (set_level), (is_our_board),
+ (magic_hat_next_level), (magic_hat_destroy_all_items),
+ (magic_hat_create_item), (finished), (game_won), (draw_frame),
+ (draw_table), (draw_hat), (place_item), (item_event), (hat_event),
+ (nb_list), (smooth_move):
+ * src/boards/menu2.c: (display_welcome):
+
+2006-01-21 Yves Combe <yves@ycombe.net>
+
+ suppress highlight on start
+
+ * src/boards/menu2.c: (display_welcome):
+
+2006-01-21 Yves Combe <yves@ycombe.net>
+
+ return to last menu position after playing a board
+ add GCompris Logo at start.
+
+ * src/boards/menu2.c: (menu_start), (display_section),
+ (create_top), (display_welcome):
+ * src/gcompris/properties.c: (gcompris_properties_new):
+ * src/gcompris/properties.h:
+
+2006-01-21 Yves Combe <yves@ycombe.net>
+
+ gcompris -l nowhere/menu2 to test this new menu.
+
+ * boards/Makefile.am:
+ * boards/menu2.xml.in:
+ * src/boards/Makefile.am:
+ * src/boards/menu2.c: (menu_pause), (menu_start), (create_panel),
+ (display_section), (menu_end), (menu_is_our_board), (menu_config),
+ (display_board_icon), (next_spot), (menu_create_item),
+ (item_event), (set_content), (create_info_area), (free_stuff),
+ (get_ratio), (create_top):
+ * src/gcompris/gameutil.c: (gcompris_get_menulist):
+
+
+ *** BRANCH gcompris_7_4 ***
+
+2006-03-01 Bruno coudoin <bruno.coudoin@free.fr>
+
* src/boards/python/sudoku.py: Added protections to try to avoid a crash hapenning
after or during the bonus. It has been observed after level 4.
@@ -465,6 +1169,548 @@
* src/gcompris/gcompris.c: (gcompris_init):
* src/gcompris/gcompris_db.c: (gcompris_db_init):
+2006-02-13 Yves Combe <yves@ycombe.net>
+
+ fix bug in gcompris_sound_controller signal definition. Apparently causes crash in dapper Ubuntu.
+
+ * po/Makefile.in.in:
+ * src/gcompris/soundutil.c: (default_sound_played_signal_handler),
+ (gcompris_sound_class_init):
+
+2006-02-11 Yves Combe <yves@ycombe.net>
+
+ test on size of db file, to create tables if it's 0
+ (correction of null-sized db due to USE_SQLITE bug).
+
+ * src/gcompris/gcompris_db.c: (gcompris_db_init):
+
+2006-02-09 Yves Combe <yves@ycombe.net>
+
+ minor fix (hat double click and highlight focus).
+
+ * src/boards/magic_hat.c: (draw_hat), (hat_event):
+
+2006-02-09 Yves Combe <yves@ycombe.net>
+
+ new versions of magic hat by Marc Brun: addition and substraction.
+
+ * boards/Makefile.am:
+ * boards/boardicons/magic_hat.png:
+ * boards/boardicons/magic_hat_minus.png:
+ * boards/boardicons/magic_hat_plus.png:
+ * boards/magic_hat.xml.in:
+ * boards/magic_hat/magic_hat_minus.png:
+ * boards/magic_hat/magic_hat_minus_bg.png:
+ * boards/magic_hat/magic_hat_plus.png:
+ * boards/magic_hat/magic_hat_plus_bg.png:
+ * boards/magic_hat/star.png:
+ * boards/magic_hat_minus.xml.in:
+ * boards/magic_hat_plus.xml.in:
+ * configure.in:
+ * src/boards/magic_hat.c: (start_board), (process_ok),
+ (magic_hat_create_item), (draw_frame), (draw_hat), (place_item),
+ (item_event), (hat_event), (move_stars), (close_hat),
+ (smooth_move):
+
+2006-02-09 Yves Combe <yves@ycombe.net>
+
+ fix bug in memory_div and emory_mult_div.
+ fix font size and font color.
+
+ * src/boards/memory.c: (get_image), (create_item):
+
+2006-02-09 Yves Combe <yves@ycombe.net>
+
+ fix bug, change font size following level for memory operations activities.
+
+ * src/boards/memory.c: (get_random_token), (start_board),
+ (create_item), (compare_card):
+
+2006-02-09 Yves Combe <yves@ycombe.net>
+
+ fix animation was launched after winning.
+ add memory based mathematicals operations boards.
+
+ * boards/Makefile.am:
+ * boards/memory_add.xml.in:
+ * boards/memory_add_minus.xml.in:
+ * boards/memory_add_minus_mult_div.xml.in:
+ * boards/memory_add_minus_mult_div_tux.xml.in:
+ * boards/memory_add_minus_tux.xml.in:
+ * boards/memory_add_tux.xml.in:
+ * boards/memory_mult.xml.in:
+ * boards/memory_mult_div.xml.in:
+ * boards/memory_mult_div_tux.xml.in:
+ * boards/memory_mult_tux.xml.in:
+ * boards/memory_op_group.xml.in:
+ * boards/memory_op_group_tux.xml.in:
+ * src/boards/awele.c: (buttonClick):
+ * src/boards/memory.c: (get_random_token), (start_board),
+ (memory_destroy_all_items), (get_image), (create_item),
+ (compare_card):
+
+2006-02-08 Yves Combe <yves@ycombe.net>
+
+ fix depth search. Must not to be odd in best difference evaluation!
+
+ * src/boards/awele_alphaBeta.c: (think):
+
+2006-02-08 Yves Combe <yves@ycombe.net>
+
+ add a reset of item->canvas after destroy.
+
+ * src/gcompris/anim.c: (gcompris_deactivate_animation):
+
+2006-02-08 Yves Combe <yves@ycombe.net>
+
+ Some fix in animation api/usage.
+
+ * src/boards/awele_alphaBeta.c: (think):
+ * src/boards/py-mod-anim.c: (Animation_free), (AnimCanvas_free):
+ * src/boards/python/gnumch.py:
+ * src/gcompris/anim.c: (anim_tick):
+
+2006-02-07 Bruno coudoin <bruno.coudoin@free.fr>
+
+ * src/boards/advanced_colors.c: (add_xml_data): fixed to check properly for long locale (e.g. pt_BR)
+ * src/boards/read_colors.c: (add_xml_data), (parse_doc): -
+ * src/boards/python/melody.py: added a dialog if run without sound fx activated
+ changed to use the reload icon instead of mouth sign for the repeat.
+
+2006-02-07 Yves Combe <yves@ycombe.net>
+
+ fix anim api to destroy the item canvas on deactivate.
+ fix gnumch to not crash with that (del anim before quit)
+ fix anim in awele.
+
+ * src/boards/awele.c: (pause_board), (repeat), (set_level),
+ (to_computer), (buttonClick):
+ * src/boards/awele_utils.c: (diedOfHunger):
+ * src/boards/python/gnumch.py:
+ * src/gcompris/anim.c: (gcompris_deactivate_animation):
+
+2006-02-07 Yves Combe,,, <yves@ycombe.net>
+
+ add Grand slam rule for capture (no capture
+ if that let opponent hungry).
+ add correct rule for hunger end of games (untested).
+
+ * src/boards/awele.c: (to_computer):
+ * src/boards/awele_utils.c: (moveAwale), (diedOfHunger):
+ * src/boards/awele_utils.h:
+
+2006-02-07 Yves Combe <yves@ycombe.net>
+
+ fix crash with animation on next_level and repeat.
+ fix strings i18n. Needs review of strings.
+
+ * src/boards/awele.c: (pause_board), (repeat), (set_level),
+ (awele_create_item), (to_computer), (buttonClick):
+
+2006-02-07 Yves Combe <yves@ycombe.net>
+
+ add animation like in connect4 when computer think.
+
+ * src/boards/awele.c: (pause_board), (start_board), (end_board),
+ (awele_next_level), (to_computer), (buttonClick):
+
+2006-02-06 Yves Combe <yves@ycombe.net>
+
+ clean code from unused fucntion
+
+ * src/boards/awele.c:
+ * src/boards/awele.h:
+
+2006-02-06 Yves Combe <yves@ycombe.net>
+
+ change evaluation fonction usage in awele,
+ to make it easier in level 1-4.
+ difficulty:
+ - level 1-2 -> random
+ - level 3-4 -> best computer capture, depth 1.
+ - level 5-6 -> best difference in capture, depth 1.
+ - level 7-8 -> best difference in capture, depth 2.
+ - level 9 -> best difference in capture, depth 3.
+ clean from g_warning.
+ change first player: computer begins at level 2-4-6-8.
+
+ * src/boards/awele.c: (start_board), (repeat), (set_level),
+ (awele_next_level), (game_won), (to_computer),
+ (updateCapturedBeans):
+ * src/boards/awele_alphaBeta.c: (eval_to_null),
+ (eval_to_best_capture), (think):
+ * src/boards/awele_utils.c: (moveAwale):
+ * src/gcompris/gcompris_alphabeta.c: (gcompris_alphabeta):
+
+2006-02-06 Yves Combe <yves@ycombe.net>
+
+ awele manily fixed.
+ TODO: change first player.
+ TODO: add correct rule in case of end by hungry player.
+
+ * src/boards/awele.c: (pause_board), (start_board),
+ (awele_next_level), (awele_create_item), (to_computer),
+ (buttonClick), (updateNbBeans), (updateCapturedBeans),
+ (buttonNewGameClick):
+ * src/boards/awele.h:
+ * src/boards/awele_alphaBeta.c: (firstChild), (think):
+ * src/boards/awele_utils.c: (moveAwale):
+ * src/gcompris/gcompris_alphabeta.c: (gcompris_alphabeta):
+
+2006-02-06 Yves Combe <yves@ycombe.net>
+
+ add generic minmax(alphabeta) function.
+ use it in awale.
+ Need more tests.
+
+ * src/boards/awele.c: (start_board), (awele_create_item),
+ (to_computer), (buttonClick), (updateCapturedBeans):
+ * src/boards/awele_alphaBeta.c: (eval), (firstChild),
+ (nextSibling), (free_awale), (think):
+ * src/boards/awele_utils.c: (isOpponentHungry), (moveAwale),
+ (randplay):
+ * src/boards/awele_utils.h:
+ * src/gcompris/Makefile.am:
+ * src/gcompris/gcompris.h:
+ * src/gcompris/gcompris_alphabeta.c: (gcompris_alphabeta):
+ * src/gcompris/gcompris_alphabeta.h:
+
+2006-02-05 Bruno coudoin <bruno.coudoin@free.fr>
+
+ Changed background entry color to white. The blue background color
+ was no more working for me for no reason.
+
+ Improved wordprocessor. Now handle a single fixed theme coherently.
+
+ * po/ChangeLog:
+ * src/boards/python/guessnumber.py:
+ * src/boards/wordprocessor.c: (display_style_buttons),
+ (item_event), (create_tags), (set_default_style),
+ (key_press_event):
+
+2006-02-03 Bruno coudoin <bruno.coudoin@free.fr>
+
+ - merged awele with HEAD.
+
+ * boards/awele/awele_frame.jpg:
+ * boards/awele/awele_frame.png:
+ * boards/awele/awele_frame_avec_messages.png:
+ * boards/awele/nv_partie.png:
+ * boards/awele/nv_partie_clic.png:
+ * boards/awele/nv_partie_notify.png:
+ * po/TRANSLATORS.README:
+ * src/boards/awele.c: (start_board), (repeat), (awele_create_item),
+ (buttonNewGameClick):
+ * src/boards/awele.h:
+ * src/boards/python/guessnumber.py: fix title alignement from HEAD.
+ * src/boards/smallnumbers.c: (smallnumbers_create_item): from HEAD, use bar dice.
+ * src/boards/wordprocessor.c: (wordprocessor_create),
+ (display_style_buttons), (item_event), (create_tags),
+ (key_press_event):
+
+2006-02-03 Yves Combe,,, <yves@ycombe.net>
+
+ fix level display and usage in awele.
+ add winning detection at 25 beans-> display bonus and new game.
+
+ * src/boards/awele.c: (start_board), (set_level),
+ (awele_create_item):
+
+2006-02-02 Yves Combe <yves@ycombe.net>
+
+ Display bonus and end of game when 25 beans are captured.
+
+ * src/boards/awele.c: (updateCapturedBeans):
+
+2006-02-02 Bruno coudoin <bruno.coudoin@free.fr>
+
+
+ * tools/list_missing_sounds.sh: By Jose Jorge. A nice utility to compare the locale
+ translations status of voices to English.
+
+2006-01-31 Yves Combe,,, <yves@ycombe.net>
+
+ fix configurables boards in c to configure from bar.
+
+ * src/boards/colors.c: (conf_ok), (colors_config_start),
+ (start_board):
+ * src/boards/gletters.c: (level_set_score), (conf_ok),
+ (gletter_config_start):
+ * src/boards/imageid.c: (config_start):
+ * src/boards/missingletter.c: (config_start):
+ * src/boards/reading.c: (reading_config_start):
+ * src/boards/smallnumbers.c: (start_board),
+ (smallnumbers_create_item), (conf_ok), (smallnumber_config_start):
+
+2006-01-31 Yves Combe <yves@ycombe.net>
+
+ fix /reading boards to configure from bar.
+
+ * src/boards/click_on_letter.c: (conf_ok):
+ * src/boards/imageid.c: (start_board), (conf_ok), (config_start):
+ * src/boards/missingletter.c: (start_board), (conf_ok):
+ * src/boards/python/pythontest.py:
+ * src/boards/reading.c: (start_board), (conf_ok),
+ (reading_config_start):
+ * src/boards/shapegame.c: (conf_ok):
+
+2006-01-30 Bruno coudoin <bruno.coudoin@free.fr>
+
+ - Added copyright header following formal argeement of
+ the author Pedro Felzenszwalb <pff@cs.uchicago.edu>
+
+ * tools/shapegame/.cvsignore:
+ * tools/shapegame/dt/.cvsignore:
+ * tools/shapegame/dt/README:
+ * tools/shapegame/dt/dt.cpp:
+ * tools/shapegame/dt/dt.h:
+ * tools/shapegame/dt/image.h:
+ * tools/shapegame/dt/imconv.h:
+ * tools/shapegame/dt/imutil.h:
+ * tools/shapegame/dt/misc.h:
+ * tools/shapegame/dt/pnmfile.h:
+ * tools/shapegame/nice_target_spot.cpp:
+
+2006-01-30 Yves Combe <yves@ycombe.net>
+
+ fix configuration window was not visible in fullscreen mode, using gtk_dialog.
+
+ * src/gcompris/board_config.c: (gcompris_close_board_conf),
+ (gcompris_response_board_conf), (gcompris_configuration_window):
+
+2006-01-30 Bruno coudoin <bruno.coudoin@free.fr>
+
+ - Added the German map by Olaf Ronneberger.
+ - Added in tools/shapegame/ a utility to create shapegame activity
+
+ * boards/geography.xml.in:
+ * boards/geography/Makefile.am:
+ * boards/geography/board6_0.xml.in:
+ * boards/geography/germany_region/back.png:
+ * boards/geography/germany_region/baden-wuerttemberg.png:
+ * boards/geography/germany_region/bayern.png:
+ * boards/geography/germany_region/berlin.png:
+ * boards/geography/germany_region/brandenburg.png:
+ * boards/geography/germany_region/bremen.png:
+ * boards/geography/germany_region/hamburg.png:
+ * boards/geography/germany_region/hessen.png:
+ * boards/geography/germany_region/mecklenburg-vorpommern.png:
+ * boards/geography/germany_region/niedersachsen.png:
+ * boards/geography/germany_region/nordrhein-westfalen.png:
+ * boards/geography/germany_region/rheinland-pfalz.png:
+ * boards/geography/germany_region/saarland.png:
+ * boards/geography/germany_region/sachsen-anhalt.png:
+ * boards/geography/germany_region/sachsen.png:
+ * boards/geography/germany_region/schleswig_holstein.png:
+ * boards/geography/germany_region/target_baden-wuerttemberg.png:
+ * boards/geography/germany_region/target_bayern.png:
+ * boards/geography/germany_region/target_berlin.png:
+ * boards/geography/germany_region/target_brandenburg.png:
+ * boards/geography/germany_region/target_bremen.png:
+ * boards/geography/germany_region/target_hamburg.png:
+ * boards/geography/germany_region/target_hessen.png:
+ * boards/geography/germany_region/target_mecklenburg-vorpommern.png
+ :
+ * boards/geography/germany_region/target_niedersachsen.png:
+ * boards/geography/germany_region/target_nordrhein-westfalen.png:
+ * boards/geography/germany_region/target_rheinland-pfalz.png:
+ * boards/geography/germany_region/target_saarland.png:
+ * boards/geography/germany_region/target_sachsen-anhalt.png:
+ * boards/geography/germany_region/target_sachsen.png:
+ * boards/geography/germany_region/target_schleswig_holstein.png:
+ * boards/geography/germany_region/target_thueringen.png:
+ * boards/geography/germany_region/thueringen.png:
+ * src/boards/wordprocessor.c: (wordprocessor_create),
+ (display_style_buttons), (item_event), (create_tags):
+ * src/gcompris/gcompris_confirm.c:
+ * tools/shapegame/HOWTO:
+ * tools/shapegame/Makefile:
+ * tools/shapegame/dt/Makefile:
+ * tools/shapegame/dt/README:
+ * tools/shapegame/dt/dt.cpp:
+ * tools/shapegame/dt/dt.h:
+ * tools/shapegame/dt/image.h:
+ * tools/shapegame/dt/imconv.h:
+ * tools/shapegame/dt/imutil.h:
+ * tools/shapegame/dt/input.pbm:
+ * tools/shapegame/dt/misc.h:
+ * tools/shapegame/dt/pnmfile.h:
+ * tools/shapegame/nice_target_spot.cpp:
+ * tools/shapegame/test.pbm:
+
+2006-01-29 Yves Combe <yves@ycombe.net>
+
+ fix click_on_letter and shapegame (imagename) to configure from bar.
+
+ * src/boards/click_on_letter.c: (sounds_are_fine), (conf_ok),
+ (config_start):
+ * src/boards/py-gcompris-profile.c:
+ (gcompris_new_pyGcomprisProfileObject):
+ * src/boards/py-mod-gcompris.c: (pyGcomprisConfCallback):
+ * src/boards/shapegame.c: (start_board), (conf_ok), (config_start):
+ * src/gcompris/board_config.c: (gcompris_close_board_conf),
+ (gcompris_apply_board_conf), (gcompris_configuration_window),
+ (gcompris_change_locale):
+
+2006-01-29 Yves Combe <yves@ycombe.net>
+
+ Add board config_start call by the bar.
+ Click on letter fixed to use that. Menu2 too.
+ Others boards needs fix too.
+
+ * src/boards/click_on_letter.c: (start_board), (conf_ok),
+ (config_start):
+ * src/boards/menu2.c: (menu_config_start), (menu_config_stop):
+ * src/gcompris/bar.c: (item_event_bar):
+
+2006-01-29 Yves Combe,,, <yves@ycombe.net>
+
+ menu2 is now default menu.
+ menu2 works now with -l option
+
+ * src/boards/Makefile.am:
+ * src/boards/menu2.c: (create_panel), (menu_is_our_board),
+ (create_top):
+ * src/gcompris/gcompris.c: (gcompris_init):
+
+2006-01-29 Yves Combe <yves@ycombe.net>
+
+ Suppress event connection on text.
+ Segfault seems to be fixed.
+
+ * src/gcompris/gcompris_confirm.c: (gcompris_confirm_stop),
+ (display_confirm):
+
+2006-01-27 Yves Combe <yves@ycombe.net>
+
+ fix unpause bug in confirm.
+
+ * src/gcompris/gcompris_confirm.c: (display_confirm):
+
+2006-01-26 Yves Combe <yves@ycombe.net>
+
+ small memory fix: pixbuf not freed after use.
+
+ * src/gcompris/gcompris_confirm.c: (display_confirm):
+
+2006-01-25 Yves Combe <yves@ycombe.net>
+
+ fix colors in confirmation window.
+
+ * src/gcompris/gcompris_confirm.c: (display_confirm):
+
+2006-01-25 Yves Combe <yves@ycombe.net>
+
+ add a confirmation popup on quit. Yet colors problem because of shadow.
+
+ * src/boards/menu2.c: (menu_create_item):
+ * src/gcompris/Makefile.am:
+ * src/gcompris/bar.c: (item_event_bar), (confirm_quit):
+ * src/gcompris/gcompris.h:
+ * src/gcompris/gcompris_confirm.c: (gcompris_confirm),
+ (gcompris_confirm_stop), (display_confirm), (free_stuff),
+ (set_content), (button_event):
+
+2006-01-25 Bruno coudoin <bruno.coudoin@free.fr>
+
+ First release of a new activity, the wordprocessor.
+ Uncomplete yet.
+
+ * boards/Makefile.am:
+ * boards/boardicons/README:
+ * boards/boardicons/wordprocessor.png:
+ * boards/wordprocessor.xml.in:
+ * src/boards/Makefile.am:
+ * src/boards/wordprocessor.c: (pause_board), (start_board),
+ (end_board), (set_level), (is_our_board),
+ (wordprocessor_destroy_all_items), (wordprocessor_create),
+ (item_event):
+
+2006-01-23 Yves Combe <yves@ycombe.net>
+
+ constraint resize icon.
+
+ * src/boards/menu2.c: (menu_create_item):
+
+2006-01-23 Yves Combe <yves@ycombe.net>
+
+ add background for menu2, with the differents zones.
+
+ * boards/skins/gartoon/gcompris-menu2bg.png:
+ * src/boards/menu2.c: (menu_start):
+
+2006-01-23 Yves Combe <yves@ycombe.net>
+
+ fix segfault i had in level 4 5 6 of magic hat.
+
+ * src/boards/magic_hat.c: (place_item):
+
+2006-01-23 Yves Combe <yves@ycombe.net>
+
+ fix bug in menu2.
+ minor update in magic_hat (MB)
+
+ * src/boards/magic_hat.c: (hat_event):
+ * src/boards/menu2.c: (menu_start), (display_section),
+ (item_event), (create_top):
+
+2006-01-22 Yves Combe <yves@ycombe.net>
+
+ new activity magic_hat by Marc Brun.
+
+ * boards/Makefile.am:
+ * boards/boardicons/magic_hat.png:
+ * boards/magic_hat.xml.in:
+ * boards/magic_hat/hat-point.png:
+ * boards/magic_hat/hat.png:
+ * boards/magic_hat/magic_hat-bg.png:
+ * boards/magic_hat/star-clear.png:
+ * boards/magic_hat/star.png:
+ * boards/magic_hat/star1.png:
+ * boards/magic_hat/star2.png:
+ * boards/magic_hat/star3.png:
+ * src/boards/Makefile.am:
+ * src/boards/magic_hat.c: (pause_board), (start_board),
+ (end_board), (process_ok), (set_level), (is_our_board),
+ (magic_hat_next_level), (magic_hat_destroy_all_items),
+ (magic_hat_create_item), (finished), (game_won), (draw_frame),
+ (draw_table), (draw_hat), (place_item), (item_event), (hat_event),
+ (nb_list), (smooth_move):
+ * src/boards/menu2.c: (display_welcome):
+
+2006-01-21 Yves Combe <yves@ycombe.net>
+
+ suppress highlight on start
+
+ * src/boards/menu2.c: (display_welcome):
+
+2006-01-21 Yves Combe <yves@ycombe.net>
+
+ return to last menu position after playing a board
+ add GCompris Logo at start.
+
+ * src/boards/menu2.c: (menu_start), (display_section),
+ (create_top), (display_welcome):
+ * src/gcompris/properties.c: (gcompris_properties_new):
+ * src/gcompris/properties.h:
+
+2006-01-21 Yves Combe <yves@ycombe.net>
+
+ gcompris -l nowhere/menu2 to test this new menu.
+
+ * boards/Makefile.am:
+ * boards/menu2.xml.in:
+ * src/boards/Makefile.am:
+ * src/boards/menu2.c: (menu_pause), (menu_start), (create_panel),
+ (display_section), (menu_end), (menu_is_our_board), (menu_config),
+ (display_board_icon), (next_spot), (menu_create_item),
+ (item_event), (set_content), (create_info_area), (free_stuff),
+ (get_ratio), (create_top):
+ * src/gcompris/gameutil.c: (gcompris_get_menulist):
+
+
+ *** BRANCH gcompris_7_4 ***
+
2006-01-19 Bruno coudoin <bruno.coudoin@free.fr>
Improved board english description.
@@ -5590,7 +6836,6 @@
* src/gcompris/board_config.h:
* src/gcompris/plugin.h:
->>>>>>> 1.526
2005-07-22 Yves Combe <yves@ycombe.net>
Connect treeview signal to allow usage of pref button
diff --git a/boards/Makefile.am b/boards/Makefile.am
index a5b2337..03ea18a 100644
--- a/boards/Makefile.am
+++ b/boards/Makefile.am
@@ -64,6 +64,8 @@ xml_in_files = \
keyboard.xml.in \
leftright.xml.in \
login.xml.in \
+ magic_hat_plus.xml.in \
+ magic_hat_minus.xml.in \
math.xml.in \
maze2DRelative.xml.in \
maze3D.xml.in \
@@ -74,9 +76,26 @@ xml_in_files = \
memory_group.xml.in \
memory_sound_tux.xml.in \
memory_sound.xml.in \
+ memory_op_group.xml.in \
+ memory_op_group_tux.xml.in \
+ memory_add.xml.in \
+ memory_add_tux.xml.in \
+ memory_minus.xml.in \
+ memory_minus_tux.xml.in \
+ memory_mult.xml.in \
+ memory_mult_tux.xml.in \
+ memory_div.xml.in \
+ memory_div_tux.xml.in \
+ memory_add_minus.xml.in \
+ memory_add_minus_tux.xml.in \
+ memory_mult_div.xml.in \
+ memory_mult_div_tux.xml.in \
+ memory_add_minus_mult_div.xml.in \
+ memory_add_minus_mult_div_tux.xml.in \
memory_tux.xml.in \
memory.xml.in \
menu.xml.in \
+ menu2.xml.in \
miscelaneous.xml.in \
missing_letter.xml.in \
money_cents.xml.in \
@@ -112,6 +131,7 @@ xml_in_files = \
traffic.xml.in \
tuxpaint.xml.in \
watercycle.xml.in \
+ wordprocessor.xml.in \
wordsgame.xml.in
xml_DATA = $(xml_in_files:.xml.in=.xml)
diff --git a/boards/boardicons/README b/boards/boardicons/README
index fd65ac3..558009b 100644
--- a/boards/boardicons/README
+++ b/boards/boardicons/README
@@ -6,3 +6,4 @@ Images comming from http://www.openclipart.org and is public domain:
- computer.png
- searace.png and searace1player.png
- smallnumber.png smallnumber2.png
+- wordprocessor.png (Author: Juliane Krug)
diff --git a/boards/boardicons/magic_hat_minus.png b/boards/boardicons/magic_hat_minus.png
new file mode 100644
index 0000000..77d71c3
--- /dev/null
+++ b/boards/boardicons/magic_hat_minus.png
Binary files differ
diff --git a/boards/boardicons/magic_hat_plus.png b/boards/boardicons/magic_hat_plus.png
new file mode 100644
index 0000000..8a10fb2
--- /dev/null
+++ b/boards/boardicons/magic_hat_plus.png
Binary files differ
diff --git a/boards/boardicons/wordprocessor.png b/boards/boardicons/wordprocessor.png
new file mode 100644
index 0000000..ea6e663
--- /dev/null
+++ b/boards/boardicons/wordprocessor.png
Binary files differ
diff --git a/boards/geography.xml.in b/boards/geography.xml.in
index ab1e003..2e93e36 100644
--- a/boards/geography.xml.in
+++ b/boards/geography.xml.in
@@ -13,5 +13,6 @@
<_title>Locate the countries</_title>
<_description>Drag and Drop the items to redraw the whole map</_description>
<_prerequisite>Mouse manipulation: movement, drag and drop</_prerequisite>
+ <_credit>The Germany map comes from Wikipedia and is released under the GNU Free Documentation License. Olaf Ronneberger and his children Lina and Julia Ronneberger created the German level.</_credit>
</Board>
</GCompris>
diff --git a/boards/geography/Makefile.am b/boards/geography/Makefile.am
index 04631c8..2158bb7 100644
--- a/boards/geography/Makefile.am
+++ b/boards/geography/Makefile.am
@@ -10,7 +10,8 @@ xml_in_files = \
board4_0.xml.in \
board4_1.xml.in \
board4_2.xml.in \
- board5_0.xml.in
+ board5_0.xml.in \
+ board6_0.xml.in
xml_DATA = $(xml_in_files:.xml.in=.xml)
diff --git a/boards/geography/board6_0.xml.in b/boards/geography/board6_0.xml.in
new file mode 100644
index 0000000..e883a9a
--- /dev/null
+++ b/boards/geography/board6_0.xml.in
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ShapeGame>
+ <Title x="600" y="495" justification="GTK_JUSTIFY_CENTER">
+ <_name>Deutschland Bundesländer</_name>
+ </Title>
+ <Shape name="A1" pixmapfile="geography/germany_region/baden-wuerttemberg.png" targetfile="geography/germany_region/target_baden-wuerttemberg.png" x="240.5" y="422.5" zoomx="1" zoomy="1" position="0"><_tooltip>Baden-Württemberg</_tooltip></Shape>
+ <Shape name="A2" pixmapfile="geography/germany_region/bayern.png" targetfile="geography/germany_region/target_bayern.png" x="342" y="406.5" zoomx="1" zoomy="1" position="0"><_tooltip>Bayern</_tooltip></Shape>
+ <Shape name="A3" pixmapfile="geography/germany_region/berlin.png" targetfile="geography/germany_region/target_berlin.png" x="429" y="175.5" zoomx="1" zoomy="1" position="0"><_tooltip>Berlin</_tooltip></Shape>
+ <Shape name="A4" pixmapfile="geography/germany_region/brandenburg.png" targetfile="geography/germany_region/target_brandenburg.png" x="403" y="178" zoomx="1" zoomy="1" position="0"><_tooltip>Brandenburg</_tooltip></Shape>
+ <Shape name="A5" pixmapfile="geography/germany_region/bremen.png" targetfile="geography/germany_region/target_bremen.png" x="215.5" y="130.5" zoomx="1" zoomy="1" position="0"><_tooltip>Bremen</_tooltip></Shape>
+ <Shape name="A6" pixmapfile="geography/germany_region/hamburg.png" targetfile="geography/germany_region/target_hamburg.png" x="285" y="121.5" zoomx="1" zoomy="1" position="0"><_tooltip>Hamburg</_tooltip></Shape>
+ <Shape name="A7" pixmapfile="geography/germany_region/hessen.png" targetfile="geography/germany_region/target_hessen.png" x="242.5" y="303.5" zoomx="1" zoomy="1" position="0"><_tooltip>Hessen</_tooltip></Shape>
+ <Shape name="A8" pixmapfile="geography/germany_region/mecklenburg-vorpommern.png" targetfile="geography/germany_region/target_mecklenburg-vorpommern.png" x="379.5" y="91" zoomx="1" zoomy="1" position="0"><_tooltip>Mecklenburg-Vorpommern</_tooltip></Shape>
+ <Shape name="A9" pixmapfile="geography/germany_region/niedersachsen.png" targetfile="geography/germany_region/target_niedersachsen.png" x="248.5" y="151" zoomx="1" zoomy="1" position="0"><_tooltip>Niedersachsen</_tooltip></Shape>
+ <Shape name="A10" pixmapfile="geography/germany_region/nordrhein-westfalen.png" targetfile="geography/germany_region/target_nordrhein-westfalen.png" x="188.5" y="244.5" zoomx="1" zoomy="1" position="0"><_tooltip>Nordrhein-Westfalen</_tooltip></Shape>
+ <Shape name="A11" pixmapfile="geography/germany_region/rheinland-pfalz.png" targetfile="geography/germany_region/target_rheinland-pfalz.png" x="171" y="339" zoomx="1" zoomy="1" position="0"><_tooltip>Rheinland-Pfalz</_tooltip></Shape>
+ <Shape name="A12" pixmapfile="geography/germany_region/saarland.png" targetfile="geography/germany_region/target_saarland.png" x="152" y="377" zoomx="1" zoomy="1" position="0"><_tooltip>Saarland</_tooltip></Shape>
+ <Shape name="A13" pixmapfile="geography/germany_region/sachsen-anhalt.png" targetfile="geography/germany_region/target_sachsen-anhalt.png" x="358" y="211.5" zoomx="1" zoomy="1" position="0"><_tooltip>Sachsen-Anhalt</_tooltip></Shape>
+ <Shape name="A14" pixmapfile="geography/germany_region/sachsen.png" targetfile="geography/germany_region/target_sachsen.png" x="422" y="277" zoomx="1" zoomy="1" position="0"><_tooltip>Sachsen</_tooltip></Shape>
+ <Shape name="A15" pixmapfile="geography/germany_region/schleswig_holstein.png" targetfile="geography/germany_region/target_schleswig_holstein.png" x="274.5" y="72.5" zoomx="1" zoomy="1" position="0"><_tooltip>Schleswig-Holstein</_tooltip></Shape>
+ <Shape name="A16" pixmapfile="geography/germany_region/thueringen.png" targetfile="geography/germany_region/target_thueringen.png" x="333.5" y="277" zoomx="1" zoomy="1" position="0"><_tooltip>Thüringen</_tooltip></Shape>
+ <Shape name="1" pixmapfile="geography/germany_region/back.png" type="SHAPE_BACKGROUND" x="300" y="258.5" zoomx="1" zoomy="1" position="0"/>
+</ShapeGame>
diff --git a/boards/geography/germany_region/back.png b/boards/geography/germany_region/back.png
new file mode 100644
index 0000000..0f04112
--- /dev/null
+++ b/boards/geography/germany_region/back.png
Binary files differ
diff --git a/boards/geography/germany_region/baden-wuerttemberg.png b/boards/geography/germany_region/baden-wuerttemberg.png
new file mode 100644
index 0000000..b7e3655
--- /dev/null
+++ b/boards/geography/germany_region/baden-wuerttemberg.png
Binary files differ
diff --git a/boards/geography/germany_region/bayern.png b/boards/geography/germany_region/bayern.png
new file mode 100644
index 0000000..3d8ac57
--- /dev/null
+++ b/boards/geography/germany_region/bayern.png
Binary files differ
diff --git a/boards/geography/germany_region/berlin.png b/boards/geography/germany_region/berlin.png
new file mode 100644
index 0000000..3d6e583
--- /dev/null
+++ b/boards/geography/germany_region/berlin.png
Binary files differ
diff --git a/boards/geography/germany_region/brandenburg.png b/boards/geography/germany_region/brandenburg.png
new file mode 100644
index 0000000..5ca64f4
--- /dev/null
+++ b/boards/geography/germany_region/brandenburg.png
Binary files differ
diff --git a/boards/geography/germany_region/bremen.png b/boards/geography/germany_region/bremen.png
new file mode 100644
index 0000000..a5b5538
--- /dev/null
+++ b/boards/geography/germany_region/bremen.png
Binary files differ
diff --git a/boards/geography/germany_region/hamburg.png b/boards/geography/germany_region/hamburg.png
new file mode 100644
index 0000000..786b692
--- /dev/null
+++ b/boards/geography/germany_region/hamburg.png
Binary files differ
diff --git a/boards/geography/germany_region/hessen.png b/boards/geography/germany_region/hessen.png
new file mode 100644
index 0000000..5b65cff
--- /dev/null
+++ b/boards/geography/germany_region/hessen.png
Binary files differ
diff --git a/boards/geography/germany_region/mecklenburg-vorpommern.png b/boards/geography/germany_region/mecklenburg-vorpommern.png
new file mode 100644
index 0000000..9715939
--- /dev/null
+++ b/boards/geography/germany_region/mecklenburg-vorpommern.png
Binary files differ
diff --git a/boards/geography/germany_region/niedersachsen.png b/boards/geography/germany_region/niedersachsen.png
new file mode 100644
index 0000000..f2d9291
--- /dev/null
+++ b/boards/geography/germany_region/niedersachsen.png
Binary files differ
diff --git a/boards/geography/germany_region/nordrhein-westfalen.png b/boards/geography/germany_region/nordrhein-westfalen.png
new file mode 100644
index 0000000..bf7cb1f
--- /dev/null
+++ b/boards/geography/germany_region/nordrhein-westfalen.png
Binary files differ
diff --git a/boards/geography/germany_region/rheinland-pfalz.png b/boards/geography/germany_region/rheinland-pfalz.png
new file mode 100644
index 0000000..28b5c70
--- /dev/null
+++ b/boards/geography/germany_region/rheinland-pfalz.png
Binary files differ
diff --git a/boards/geography/germany_region/saarland.png b/boards/geography/germany_region/saarland.png
new file mode 100644
index 0000000..9b8ba42
--- /dev/null
+++ b/boards/geography/germany_region/saarland.png
Binary files differ
diff --git a/boards/geography/germany_region/sachsen-anhalt.png b/boards/geography/germany_region/sachsen-anhalt.png
new file mode 100644
index 0000000..ee18f2e
--- /dev/null
+++ b/boards/geography/germany_region/sachsen-anhalt.png
Binary files differ
diff --git a/boards/geography/germany_region/sachsen.png b/boards/geography/germany_region/sachsen.png
new file mode 100644
index 0000000..7b63f3d
--- /dev/null
+++ b/boards/geography/germany_region/sachsen.png
Binary files differ
diff --git a/boards/geography/germany_region/schleswig_holstein.png b/boards/geography/germany_region/schleswig_holstein.png
new file mode 100644
index 0000000..9e1ee61
--- /dev/null
+++ b/boards/geography/germany_region/schleswig_holstein.png
Binary files differ
diff --git a/boards/geography/germany_region/target_baden-wuerttemberg.png b/boards/geography/germany_region/target_baden-wuerttemberg.png
new file mode 100644
index 0000000..3b44695
--- /dev/null
+++ b/boards/geography/germany_region/target_baden-wuerttemberg.png
Binary files differ
diff --git a/boards/geography/germany_region/target_bayern.png b/boards/geography/germany_region/target_bayern.png
new file mode 100644
index 0000000..92da698
--- /dev/null
+++ b/boards/geography/germany_region/target_bayern.png
Binary files differ
diff --git a/boards/geography/germany_region/target_berlin.png b/boards/geography/germany_region/target_berlin.png
new file mode 100644
index 0000000..bbcbc1f
--- /dev/null
+++ b/boards/geography/germany_region/target_berlin.png
Binary files differ
diff --git a/boards/geography/germany_region/target_brandenburg.png b/boards/geography/germany_region/target_brandenburg.png
new file mode 100644
index 0000000..bce5bff
--- /dev/null
+++ b/boards/geography/germany_region/target_brandenburg.png
Binary files differ
diff --git a/boards/geography/germany_region/target_bremen.png b/boards/geography/germany_region/target_bremen.png
new file mode 100644
index 0000000..e15957a
--- /dev/null
+++ b/boards/geography/germany_region/target_bremen.png
Binary files differ
diff --git a/boards/geography/germany_region/target_hamburg.png b/boards/geography/germany_region/target_hamburg.png
new file mode 100644
index 0000000..6759e88
--- /dev/null
+++ b/boards/geography/germany_region/target_hamburg.png
Binary files differ
diff --git a/boards/geography/germany_region/target_hessen.png b/boards/geography/germany_region/target_hessen.png
new file mode 100644
index 0000000..dbddb77
--- /dev/null
+++ b/boards/geography/germany_region/target_hessen.png
Binary files differ
diff --git a/boards/geography/germany_region/target_mecklenburg-vorpommern.png b/boards/geography/germany_region/target_mecklenburg-vorpommern.png
new file mode 100644
index 0000000..766550d
--- /dev/null
+++ b/boards/geography/germany_region/target_mecklenburg-vorpommern.png
Binary files differ
diff --git a/boards/geography/germany_region/target_niedersachsen.png b/boards/geography/germany_region/target_niedersachsen.png
new file mode 100644
index 0000000..c865066
--- /dev/null
+++ b/boards/geography/germany_region/target_niedersachsen.png
Binary files differ
diff --git a/boards/geography/germany_region/target_nordrhein-westfalen.png b/boards/geography/germany_region/target_nordrhein-westfalen.png
new file mode 100644
index 0000000..5f1cec0
--- /dev/null
+++ b/boards/geography/germany_region/target_nordrhein-westfalen.png
Binary files differ
diff --git a/boards/geography/germany_region/target_rheinland-pfalz.png b/boards/geography/germany_region/target_rheinland-pfalz.png
new file mode 100644
index 0000000..248002f
--- /dev/null
+++ b/boards/geography/germany_region/target_rheinland-pfalz.png
Binary files differ
diff --git a/boards/geography/germany_region/target_saarland.png b/boards/geography/germany_region/target_saarland.png
new file mode 100644
index 0000000..ad46e5d
--- /dev/null
+++ b/boards/geography/germany_region/target_saarland.png
Binary files differ
diff --git a/boards/geography/germany_region/target_sachsen-anhalt.png b/boards/geography/germany_region/target_sachsen-anhalt.png
new file mode 100644
index 0000000..0b76de1
--- /dev/null
+++ b/boards/geography/germany_region/target_sachsen-anhalt.png
Binary files differ
diff --git a/boards/geography/germany_region/target_sachsen.png b/boards/geography/germany_region/target_sachsen.png
new file mode 100644
index 0000000..678d1d1
--- /dev/null
+++ b/boards/geography/germany_region/target_sachsen.png
Binary files differ
diff --git a/boards/geography/germany_region/target_schleswig_holstein.png b/boards/geography/germany_region/target_schleswig_holstein.png
new file mode 100644
index 0000000..2b8222d
--- /dev/null
+++ b/boards/geography/germany_region/target_schleswig_holstein.png
Binary files differ
diff --git a/boards/geography/germany_region/target_thueringen.png b/boards/geography/germany_region/target_thueringen.png
new file mode 100644
index 0000000..3b0795c
--- /dev/null
+++ b/boards/geography/germany_region/target_thueringen.png
Binary files differ
diff --git a/boards/geography/germany_region/thueringen.png b/boards/geography/germany_region/thueringen.png
new file mode 100644
index 0000000..d361bbf
--- /dev/null
+++ b/boards/geography/germany_region/thueringen.png
Binary files differ
diff --git a/boards/magic_hat/hat-point.png b/boards/magic_hat/hat-point.png
new file mode 100644
index 0000000..b35e598
--- /dev/null
+++ b/boards/magic_hat/hat-point.png
Binary files differ
diff --git a/boards/magic_hat/hat.png b/boards/magic_hat/hat.png
new file mode 100644
index 0000000..813a2f3
--- /dev/null
+++ b/boards/magic_hat/hat.png
Binary files differ
diff --git a/boards/magic_hat/magic_hat_minus.png b/boards/magic_hat/magic_hat_minus.png
new file mode 100644
index 0000000..77d71c3
--- /dev/null
+++ b/boards/magic_hat/magic_hat_minus.png
Binary files differ
diff --git a/boards/magic_hat/magic_hat_minus_bg.png b/boards/magic_hat/magic_hat_minus_bg.png
new file mode 100644
index 0000000..2350d04
--- /dev/null
+++ b/boards/magic_hat/magic_hat_minus_bg.png
Binary files differ
diff --git a/boards/magic_hat/magic_hat_plus.png b/boards/magic_hat/magic_hat_plus.png
new file mode 100644
index 0000000..8a10fb2
--- /dev/null
+++ b/boards/magic_hat/magic_hat_plus.png
Binary files differ
diff --git a/boards/magic_hat/magic_hat_plus_bg.png b/boards/magic_hat/magic_hat_plus_bg.png
new file mode 100644
index 0000000..6a0fdb3
--- /dev/null
+++ b/boards/magic_hat/magic_hat_plus_bg.png
Binary files differ
diff --git a/boards/magic_hat/star-clear.png b/boards/magic_hat/star-clear.png
new file mode 100644
index 0000000..dba511a
--- /dev/null
+++ b/boards/magic_hat/star-clear.png
Binary files differ
diff --git a/boards/magic_hat/star1.png b/boards/magic_hat/star1.png
new file mode 100644
index 0000000..df6755d
--- /dev/null
+++ b/boards/magic_hat/star1.png
Binary files differ
diff --git a/boards/magic_hat/star2.png b/boards/magic_hat/star2.png
new file mode 100644
index 0000000..854d1d3
--- /dev/null
+++ b/boards/magic_hat/star2.png
Binary files differ
diff --git a/boards/magic_hat/star3.png b/boards/magic_hat/star3.png
new file mode 100644
index 0000000..740eabf
--- /dev/null
+++ b/boards/magic_hat/star3.png
Binary files differ
diff --git a/boards/magic_hat_minus.xml.in b/boards/magic_hat_minus.xml.in
new file mode 100644
index 0000000..4fc6736
--- /dev/null
+++ b/boards/magic_hat_minus.xml.in
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<GCompris>
+ <Board
+ name="magic_hat_minus"
+ type="magic_hat"
+ section="/experimental"
+ icon="boardicons/magic_hat_minus.png"
+ difficulty="2"
+ mode="minus"
+ author="Marc BRUN"
+ boarddir="">
+ <_title>The magician hat</_title>
+ <_description>Compute how many items are under the magic hat after some escaped</_description>
+ <_prerequisite>Substraction</_prerequisite>
+ <_goal>Learn substraction</_goal>
+ <_manual>Look at the magician, he tells you how much stars are under his magic hat. Then, click on the hat to open it. A few stars now escape. Click again on the hat to close it. You have to compute how much are still under the hat. Click on the bottom right frame to give your answer.</_manual>
+ <_credit></_credit>
+ </Board>
+</GCompris>
diff --git a/boards/magic_hat_plus.xml.in b/boards/magic_hat_plus.xml.in
new file mode 100644
index 0000000..81afe9b
--- /dev/null
+++ b/boards/magic_hat_plus.xml.in
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<GCompris>
+ <Board
+ name="magic_hat_plus"
+ type="magic_hat"
+ section="/experimental"
+ icon="boardicons/magic_hat_plus.png"
+ difficulty="2"
+ mode="plus"
+ author="Marc BRUN"
+ boarddir="">
+ <_title>The magician hat</_title>
+ <_description>Compute how many items are under the magic hat</_description>
+ <_prerequisite>Addition</_prerequisite>
+ <_goal>Learn addition</_goal>
+ <_manual>Click on the hat to open it. A few stars now comes under the hat. Click again on the hat to close it. You have to compute how much are under the hat. Click on the bottom right frame to give your answer.</_manual>
+ <_credit></_credit>
+ </Board>
+</GCompris>
diff --git a/boards/memory_add.xml.in b/boards/memory_add.xml.in
new file mode 100644
index 0000000..34b68f5
--- /dev/null
+++ b/boards/memory_add.xml.in
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<GCompris>
+ <Board
+ name="memory_add"
+ type="memory"
+ section="/experimental/memory_op_group"
+ mode="add"
+ difficulty="1"
+ icon="boardicons/memory.png"
+ author="Bruno Coudoin (bruno.coudoin@free.fr)"
+ boarddir="">
+ <_title>Memory Game for additions</_title>
+ <_description>Flip the cards to find the matching pairs</_description>
+ <_prerequisite>Additions</_prerequisite>
+ <_goal>Train your memory in addition domain and remove all the cards</_goal>
+ <_manual>A set of blank cards is shown. Each card has a picture on the other side, and each picture card has a twin exactly the same. Click on a card to see its hidden picture, and try to match the twins. You can only turn over two cards at once, so you need to remember where a picture is, while you look for its twin. When you turn over the twins, they both disappear.</_manual>
+ </Board>
+ <Data directory=""/>
+</GCompris>
diff --git a/boards/memory_add_minus.xml.in b/boards/memory_add_minus.xml.in
new file mode 100644
index 0000000..7a046cc
--- /dev/null
+++ b/boards/memory_add_minus.xml.in
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<GCompris>
+ <Board
+ name="memory_add_minus"
+ type="memory"
+ section="/experimental/memory_op_group"
+ mode="add_minus"
+ difficulty="1"
+ icon="boardicons/memory.png"
+ author="Bruno Coudoin (bruno.coudoin@free.fr)"
+ boarddir="">
+ <_title>Memory Game for additions and substractions</_title>
+ <_description>Flip the cards to find the matching pairs</_description>
+ <_prerequisite>Additions</_prerequisite>
+ <_goal>Train your memory in addition domain and remove all the cards</_goal>
+ <_manual>A set of blank cards is shown. Each card has a picture on the other side, and each picture card has a twin exactly the same. Click on a card to see its hidden picture, and try to match the twins. You can only turn over two cards at once, so you need to remember where a picture is, while you look for its twin. When you turn over the twins, they both disappear.</_manual>
+ </Board>
+ <Data directory=""/>
+</GCompris>
diff --git a/boards/memory_add_minus_mult_div.xml.in b/boards/memory_add_minus_mult_div.xml.in
new file mode 100644
index 0000000..f553f5f
--- /dev/null
+++ b/boards/memory_add_minus_mult_div.xml.in
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<GCompris>
+ <Board
+ name="memory_add_minus_mult_div"
+ type="memory"
+ section="/experimental/memory_op_group"
+ mode="add_minus_mult_div"
+ difficulty="1"
+ icon="boardicons/memory.png"
+ author="Bruno Coudoin (bruno.coudoin@free.fr)"
+ boarddir="">
+ <_title>Memory Game for the operations</_title>
+ <_description>Flip the cards to find the matching pairs</_description>
+ <_prerequisite>Additions</_prerequisite>
+ <_goal>Train your memory in addition domain and remove all the cards</_goal>
+ <_manual>A set of blank cards is shown. Each card has a picture on the other side, and each picture card has a twin exactly the same. Click on a card to see its hidden picture, and try to match the twins. You can only turn over two cards at once, so you need to remember where a picture is, while you look for its twin. When you turn over the twins, they both disappear.</_manual>
+ </Board>
+ <Data directory=""/>
+</GCompris>
diff --git a/boards/memory_add_minus_mult_div_tux.xml.in b/boards/memory_add_minus_mult_div_tux.xml.in
new file mode 100644
index 0000000..017e4ac
--- /dev/null
+++ b/boards/memory_add_minus_mult_div_tux.xml.in
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<GCompris>
+ <Board
+ name="memory_add_minus_mult_div_tux"
+ type="memory"
+ section="/experimental/memory_op_group_tux"
+ mode="add_minus_mult_div_tux"
+ difficulty="1"
+ icon="boardicons/memory_tux.png"
+ author="Bruno Coudoin (bruno.coudoin@free.fr)"
+ boarddir="">
+ <_title>Memory Game for the 4 operations against Tux</_title>
+ <_description>Flip the cards to find the matching pairs</_description>
+ <_prerequisite>Additions</_prerequisite>
+ <_goal>Train your memory in addition domain and remove all the cards</_goal>
+ <_manual>A set of blank cards is shown. Each card has a picture on the other side, and each picture card has a twin exactly the same. Click on a card to see its hidden picture, and try to match the twins. You can only turn over two cards at once, so you need to remember where a picture is, while you look for its twin. When you turn over the twins, they both disappear.</_manual>
+ </Board>
+ <Data directory=""/>
+</GCompris>
diff --git a/boards/memory_add_minus_tux.xml.in b/boards/memory_add_minus_tux.xml.in
new file mode 100644
index 0000000..1473680
--- /dev/null
+++ b/boards/memory_add_minus_tux.xml.in
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<GCompris>
+ <Board
+ name="memory_add_minus_tux"
+ type="memory"
+ section="/experimental/memory_op_group_tux"
+ mode="add_minus_tux"
+ difficulty="1"
+ icon="boardicons/memory_tux.png"
+ author="Bruno Coudoin (bruno.coudoin@free.fr)"
+ boarddir="">
+ <_title>Memory Game for additions and substractions against Tux</_title>
+ <_description>Flip the cards to find the matching pairs</_description>
+ <_prerequisite>Additions</_prerequisite>
+ <_goal>Train your memory in addition domain and remove all the cards</_goal>
+ <_manual>A set of blank cards is shown. Each card has a picture on the other side, and each picture card has a twin exactly the same. Click on a card to see its hidden picture, and try to match the twins. You can only turn over two cards at once, so you need to remember where a picture is, while you look for its twin. When you turn over the twins, they both disappear.</_manual>
+ </Board>
+ <Data directory=""/>
+</GCompris>
diff --git a/boards/memory_add_tux.xml.in b/boards/memory_add_tux.xml.in
new file mode 100644
index 0000000..a6d9086
--- /dev/null
+++ b/boards/memory_add_tux.xml.in
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<GCompris>
+ <Board
+ name="memory_add_tux"
+ type="memory"
+ section="/experimental/memory_op_group_tux"
+ mode="add_tux"
+ difficulty="1"
+ icon="boardicons/memory_tux.png"
+ author="Bruno Coudoin (bruno.coudoin@free.fr)"
+ boarddir="">
+ <_title>Memory Game for additions against Tux</_title>
+ <_description>Flip the cards to find the matching pairs</_description>
+ <_prerequisite>Additions</_prerequisite>
+ <_goal>Train your memory in addition domain and remove all the cards</_goal>
+ <_manual>A set of blank cards is shown. Each card has a picture on the other side, and each picture card has a twin exactly the same. Click on a card to see its hidden picture, and try to match the twins. You can only turn over two cards at once, so you need to remember where a picture is, while you look for its twin. When you turn over the twins, they both disappear.</_manual>
+ </Board>
+ <Data directory=""/>
+</GCompris>
diff --git a/boards/memory_div.xml.in b/boards/memory_div.xml.in
new file mode 100644
index 0000000..b92127b
--- /dev/null
+++ b/boards/memory_div.xml.in
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<GCompris>
+ <Board
+ name="memory_div"
+ type="memory"
+ section="/experimental/memory_op_group"
+ mode="div"
+ difficulty="1"
+ icon="boardicons/memory.png"
+ author="Bruno Coudoin (bruno.coudoin@free.fr)"
+ boarddir="">
+ <_title>Memory Game for divisions</_title>
+ <_description>Flip the cards to find the matching pairs</_description>
+ <_prerequisite>Additions</_prerequisite>
+ <_goal>Train your memory in addition domain and remove all the cards</_goal>
+ <_manual>A set of blank cards is shown. Each card has a picture on the other side, and each picture card has a twin exactly the same. Click on a card to see its hidden picture, and try to match the twins. You can only turn over two cards at once, so you need to remember where a picture is, while you look for its twin. When you turn over the twins, they both disappear.</_manual>
+ </Board>
+ <Data directory=""/>
+</GCompris>
diff --git a/boards/memory_div_tux.xml.in b/boards/memory_div_tux.xml.in
new file mode 100644
index 0000000..dcd88c0
--- /dev/null
+++ b/boards/memory_div_tux.xml.in
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<GCompris>
+ <Board
+ name="memory_div_tux"
+ type="memory"
+ section="/experimental/memory_op_group_tux"
+ mode="div_tux"
+ difficulty="1"
+ icon="boardicons/memory_tux.png"
+ author="Bruno Coudoin (bruno.coudoin@free.fr)"
+ boarddir="">
+ <_title>Memory Game for divisions against Tux</_title>
+ <_description>Flip the cards to find the matching pairs</_description>
+ <_prerequisite>Additions</_prerequisite>
+ <_goal>Train your memory in addition domain and remove all the cards</_goal>
+ <_manual>A set of blank cards is shown. Each card has a picture on the other side, and each picture card has a twin exactly the same. Click on a card to see its hidden picture, and try to match the twins. You can only turn over two cards at once, so you need to remember where a picture is, while you look for its twin. When you turn over the twins, they both disappear.</_manual>
+ </Board>
+ <Data directory=""/>
+</GCompris>
diff --git a/boards/memory_minus.xml.in b/boards/memory_minus.xml.in
new file mode 100644
index 0000000..17d81d7
--- /dev/null
+++ b/boards/memory_minus.xml.in
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<GCompris>
+ <Board
+ name="memory_minus"
+ type="memory"
+ section="/experimental/memory_op_group"
+ mode="minus"
+ difficulty="1"
+ icon="boardicons/memory.png"
+ author="Bruno Coudoin (bruno.coudoin@free.fr)"
+ boarddir="">
+ <_title>Memory Game for substractions</_title>
+ <_description>Flip the cards to find the matching pairs</_description>
+ <_prerequisite>Additions</_prerequisite>
+ <_goal>Train your memory in addition domain and remove all the cards</_goal>
+ <_manual>A set of blank cards is shown. Each card has a picture on the other side, and each picture card has a twin exactly the same. Click on a card to see its hidden picture, and try to match the twins. You can only turn over two cards at once, so you need to remember where a picture is, while you look for its twin. When you turn over the twins, they both disappear.</_manual>
+ </Board>
+ <Data directory=""/>
+</GCompris>
diff --git a/boards/memory_minus_tux.xml.in b/boards/memory_minus_tux.xml.in
new file mode 100644
index 0000000..d129bd3
--- /dev/null
+++ b/boards/memory_minus_tux.xml.in
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<GCompris>
+ <Board
+ name="memory_minus_tux"
+ type="memory"
+ section="/experimental/memory_op_group_tux"
+ mode="minus_tux"
+ difficulty="1"
+ icon="boardicons/memory_tux.png"
+ author="Bruno Coudoin (bruno.coudoin@free.fr)"
+ boarddir="">
+ <_title>Memory Game for substractions against Tux</_title>
+ <_description>Flip the cards to find the matching pairs</_description>
+ <_prerequisite>Additions</_prerequisite>
+ <_goal>Train your memory in addition domain and remove all the cards</_goal>
+ <_manual>A set of blank cards is shown. Each card has a picture on the other side, and each picture card has a twin exactly the same. Click on a card to see its hidden picture, and try to match the twins. You can only turn over two cards at once, so you need to remember where a picture is, while you look for its twin. When you turn over the twins, they both disappear.</_manual>
+ </Board>
+ <Data directory=""/>
+</GCompris>
diff --git a/boards/memory_mult.xml.in b/boards/memory_mult.xml.in
new file mode 100644
index 0000000..1c50b6d
--- /dev/null
+++ b/boards/memory_mult.xml.in
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<GCompris>
+ <Board
+ name="memory_mult"
+ type="memory"
+ section="/experimental/memory_op_group"
+ mode="mult"
+ difficulty="1"
+ icon="boardicons/memory.png"
+ author="Bruno Coudoin (bruno.coudoin@free.fr)"
+ boarddir="">
+ <_title>Memory Game for multiplications</_title>
+ <_description>Flip the cards to find the matching pairs</_description>
+ <_prerequisite>Additions</_prerequisite>
+ <_goal>Train your memory in addition domain and remove all the cards</_goal>
+ <_manual>A set of blank cards is shown. Each card has a picture on the other side, and each picture card has a twin exactly the same. Click on a card to see its hidden picture, and try to match the twins. You can only turn over two cards at once, so you need to remember where a picture is, while you look for its twin. When you turn over the twins, they both disappear.</_manual>
+ </Board>
+ <Data directory=""/>
+</GCompris>
diff --git a/boards/memory_mult_div.xml.in b/boards/memory_mult_div.xml.in
new file mode 100644
index 0000000..1b07e3e
--- /dev/null
+++ b/boards/memory_mult_div.xml.in
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<GCompris>
+ <Board
+ name="memory_mult_div"
+ type="memory"
+ section="/experimental/memory_op_group"
+ mode="mult_div"
+ difficulty="1"
+ icon="boardicons/memory.png"
+ author="Bruno Coudoin (bruno.coudoin@free.fr)"
+ boarddir="">
+ <_title>Memory Game for multiplications and divisions</_title>
+ <_description>Flip the cards to find the matching pairs</_description>
+ <_prerequisite>Additions</_prerequisite>
+ <_goal>Train your memory in addition domain and remove all the cards</_goal>
+ <_manual>A set of blank cards is shown. Each card has a picture on the other side, and each picture card has a twin exactly the same. Click on a card to see its hidden picture, and try to match the twins. You can only turn over two cards at once, so you need to remember where a picture is, while you look for its twin. When you turn over the twins, they both disappear.</_manual>
+ </Board>
+ <Data directory=""/>
+</GCompris>
diff --git a/boards/memory_mult_div_tux.xml.in b/boards/memory_mult_div_tux.xml.in
new file mode 100644
index 0000000..d6f3f48
--- /dev/null
+++ b/boards/memory_mult_div_tux.xml.in
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<GCompris>
+ <Board
+ name="memory_mult_div_tux"
+ type="memory"
+ section="/experimental/memory_op_group_tux"
+ mode="mult_div_tux"
+ difficulty="1"
+ icon="boardicons/memory_tux.png"
+ author="Bruno Coudoin (bruno.coudoin@free.fr)"
+ boarddir="">
+ <_title>Memory Game for multiplications and divisions against Tux</_title>
+ <_description>Flip the cards to find the matching pairs</_description>
+ <_prerequisite>Additions</_prerequisite>
+ <_goal>Train your memory in addition domain and remove all the cards</_goal>
+ <_manual>A set of blank cards is shown. Each card has a picture on the other side, and each picture card has a twin exactly the same. Click on a card to see its hidden picture, and try to match the twins. You can only turn over two cards at once, so you need to remember where a picture is, while you look for its twin. When you turn over the twins, they both disappear.</_manual>
+ </Board>
+ <Data directory=""/>
+</GCompris>
diff --git a/boards/memory_mult_tux.xml.in b/boards/memory_mult_tux.xml.in
new file mode 100644
index 0000000..96b4593
--- /dev/null
+++ b/boards/memory_mult_tux.xml.in
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<GCompris>
+ <Board
+ name="memory_mult_tux"
+ type="memory"
+ section="/experimental/memory_op_group_tux"
+ mode="mult_tux"
+ difficulty="1"
+ icon="boardicons/memory_tux.png"
+ author="Bruno Coudoin (bruno.coudoin@free.fr)"
+ boarddir="">
+ <_title>Memory Game for multiplications against Tux</_title>
+ <_description>Flip the cards to find the matching pairs</_description>
+ <_prerequisite>Additions</_prerequisite>
+ <_goal>Train your memory in addition domain and remove all the cards</_goal>
+ <_manual>A set of blank cards is shown. Each card has a picture on the other side, and each picture card has a twin exactly the same. Click on a card to see its hidden picture, and try to match the twins. You can only turn over two cards at once, so you need to remember where a picture is, while you look for its twin. When you turn over the twins, they both disappear.</_manual>
+ </Board>
+ <Data directory=""/>
+</GCompris>
diff --git a/boards/memory_op_group.xml.in b/boards/memory_op_group.xml.in
new file mode 100644
index 0000000..73540a6
--- /dev/null
+++ b/boards/memory_op_group.xml.in
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<GCompris>
+ <Board
+ name="memory_op_group"
+ type="menu"
+ section="/experimental"
+ icon="boardicons/memory_elephant.png"
+ author="">
+ <_title>Go to Memory Operations activities</_title>
+ <_description>Various memory activities (images, letters, sounds).</_description>
+ </Board>
+</GCompris>
diff --git a/boards/memory_op_group_tux.xml.in b/boards/memory_op_group_tux.xml.in
new file mode 100644
index 0000000..cdd1f18
--- /dev/null
+++ b/boards/memory_op_group_tux.xml.in
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<GCompris>
+ <Board
+ name="memory_op_group_tux"
+ type="menu"
+ section="/experimental"
+ icon="boardicons/memory_elephant.png"
+ author="">
+ <_title>Go to Memory Operations activities against Tux</_title>
+ <_description>Various memory activities (images, letters, sounds).</_description>
+ </Board>
+</GCompris>
diff --git a/boards/menu2.xml.in b/boards/menu2.xml.in
new file mode 100644
index 0000000..58b8cba
--- /dev/null
+++ b/boards/menu2.xml.in
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<GCompris>
+ <Board
+ name="menu2"
+ type="menu2"
+ section="nowhere"
+ icon=""
+ author="">
+ <_title>GCompris Main Menu</_title>
+ <_description>Left-click the mouse on an activity to select it.</_description>
+ <_prerequisite>GCompris is a collection of educational games that provides for children from 2 years old with different activities.</_prerequisite>
+ <_goal>The goal of gcompris is to provide a free alternative to popular proprietary edutainment software</_goal>
+ <_manual xml:space="preserve">A simple click on an icon brings you to an activity or a menu of activities.
+At the bottom of the screen is the gcompris control bar.
+The following icons are displayed from right to left.
+(note that each icon is displayed only if available in the current activity)
+ Home - Back to previous menu or exit gcompris if at the top
+ Thumb - OK. Confirm your answer
+ Dice - Display the current level. Click to select another level
+ Music note - Repeat the question
+ Question Mark - Help
+ Tool - The configuration menu
+ Tux Plane - About game
+The stars, show suitable age groups for each game:
+ 1, 2 or 3 simple stars - 2 to 6 years old
+ 1, 2 or 3 complex stars - From 7 years old</_manual>
+ </Board>
+</GCompris>
diff --git a/boards/skins/gartoon/gcompris-menu2bg.png b/boards/skins/gartoon/gcompris-menu2bg.png
new file mode 100644
index 0000000..2dd3a14
--- /dev/null
+++ b/boards/skins/gartoon/gcompris-menu2bg.png
Binary files differ
diff --git a/boards/wordprocessor.xml.in b/boards/wordprocessor.xml.in
new file mode 100644
index 0000000..7d303c5
--- /dev/null
+++ b/boards/wordprocessor.xml.in
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<GCompris>
+ <Board
+ name="wordprocessor"
+ type="wordprocessor"
+ section="/experimental"
+ icon="boardicons/wordprocessor.png"
+ difficulty="2"
+ mode="normal"
+ author="Bruno coudoin"
+ boarddir="">
+ <_title>Your word processor</_title>
+ <_description>A simple word processor to enter and save any text</_description>
+ <_prerequisite></_prerequisite>
+ <_goal></_goal>
+ <_manual></_manual>
+ <_credit></_credit>
+ </Board>
+</GCompris>
diff --git a/configure.in b/configure.in
index b6abb39..6581217 100644
--- a/configure.in
+++ b/configure.in
@@ -2,7 +2,7 @@ dnl Process this file with autoconf to produce a configure script.
AC_INIT(src/gcompris/gcompris.c)
AC_CANONICAL_TARGET
-AM_INIT_AUTOMAKE(gcompris, 7.3.2)
+AM_INIT_AUTOMAKE(gcompris, 7.4.0BETA1)
AM_CONFIG_HEADER(config.h)
AM_MAINTAINER_MODE
diff --git a/po/TRANSLATORS.README b/po/TRANSLATORS.README
index 5176beb..f03a581 100644
--- a/po/TRANSLATORS.README
+++ b/po/TRANSLATORS.README
@@ -4,6 +4,8 @@
WARNING: After a .po update and install, run GCompris with --reread-menu option
in order to see your changes. (GCompris caches strings in a database).
+To update only you po file, run: intltool-update lang (lang is fr for French).
+
GCompris is a little bit special in terms of translation needs. The best is
done to bring back everything to .po files but it is not exhaustive.
diff --git a/src/boards/Makefile.am b/src/boards/Makefile.am
index 38bb29a..52192b6 100644
--- a/src/boards/Makefile.am
+++ b/src/boards/Makefile.am
@@ -48,6 +48,7 @@ lib_LTLIBRARIES = \
libleftright.la \
libsuperbrain.la \
libmachpuzzle.la \
+ libmagic_hat.la \
libmaze.la \
libmemory.la \
libmenu.la \
@@ -67,6 +68,7 @@ lib_LTLIBRARIES = \
libadvanced_colors.la \
libread_colors.la \
libdraw.la \
+ libwordprocessor.la \
$(python_plugin)
libdir = $(plugindir)
@@ -94,8 +96,7 @@ libcrane_la_SOURCES = crane.c
libmenu_la_LDFLAGS = -module -avoid-version
libmenu_la_LIBADD = $(top_builddir)/src/gcompris/libgcompris-1.la
-libmenu_la_SOURCES = menu.c
-
+libmenu_la_SOURCES = menu2.c
libclickgame_la_LDFLAGS = -module -avoid-version
libclickgame_la_LIBADD = $(top_builddir)/src/gcompris/libgcompris-1.la
@@ -192,6 +193,10 @@ libtarget_la_LDFLAGS = -module -avoid-version
libtarget_la_LIBADD = $(top_builddir)/src/gcompris/libgcompris-1.la
libtarget_la_SOURCES = target.c
+libmagic_hat_la_LDFLAGS = -module -avoid-version
+libmagic_hat_la_LIBADD = $(top_builddir)/src/gcompris/libgcompris-1.la
+libmagic_hat_la_SOURCES = magic_hat.c
+
libmaze_la_LDFLAGS = -module -avoid-version
libmaze_la_LIBADD = $(top_builddir)/src/gcompris/libgcompris-1.la
libmaze_la_SOURCES = maze.c
@@ -253,6 +258,10 @@ libfifteen_la_LDFLAGS = -module -avoid-version
libfifteen_la_LIBADD = $(top_builddir)/src/gcompris/libgcompris-1.la
libfifteen_la_SOURCES = fifteen.c
+libwordprocessor_la_LDFLAGS = -module -avoid-version
+libwordprocessor_la_LIBADD = $(top_builddir)/src/gcompris/libgcompris-1.la
+libwordprocessor_la_SOURCES = wordprocessor.c
+
libpython_la_LDFLAGS = -export-dynamic -module -avoid-version $(PYTHON_LIBS)
libpython_la_LIBADD = $(top_builddir)/src/gcompris/libgcompris-1.la
diff --git a/src/boards/awele.c b/src/boards/awele.c
index 6ed6eb2..30816bd 100644
--- a/src/boards/awele.c
+++ b/src/boards/awele.c
@@ -26,8 +26,7 @@ char errorMsg[30];
AWALE *staticAwale;
int caseCoord[12] =
{ 102, 206, 309, 413, 522, 628, 626, 520, 411, 307, 201, 100 };
-GRAPHICS_ELT *graphsElt = NULL;
-CALLBACK_ARGS *buttonClickArgs[6];
+static GRAPHICS_ELT *graphsElt = NULL;
static void start_board (GcomprisBoard * agcomprisBoard);
static void pause_board (gboolean pause);
@@ -43,7 +42,14 @@ static gboolean is_our_board (GcomprisBoard * gcomprisBoard);
static GnomeCanvasItem *awele_create_item (GnomeCanvasGroup * parent);
static void awele_destroy_all_items (void);
static void awele_next_level (void);
+static gboolean to_computer(gpointer data);
+static gint timeout = 0;
+static gboolean computer_turn = FALSE;
+static gboolean sublevel_finished = FALSE;
+/*=============================================*/
+static GcomprisAnimation *animation;
+static GcomprisAnimCanvasItem *anim_item;
/*
* Description of this plugin
@@ -87,14 +93,33 @@ GET_BPLUGIN_INFO (awele)
static void pause_board (gboolean pause)
{
if (gcomprisBoard == NULL)
- return;
-
- if (gamewon == TRUE && pause == FALSE)
- { /* the game is won */
- game_won ();
- }
+ return;
board_paused = pause;
+
+ if (pause == FALSE) {
+ if (gamewon == TRUE)
+ game_won ();
+ else
+ if (computer_turn){
+ timeout = g_timeout_add (2000,
+ (GSourceFunc) to_computer,
+ NULL);
+ anim_item = (GnomeCanvasItem*)
+ gcompris_activate_animation( boardRootItem,
+ animation );
+ gnome_canvas_item_show(anim_item->canvas);
+ }
+ }
+ else{
+ if (computer_turn){
+ gcompris_deactivate_animation(anim_item);
+ if (timeout){
+ g_source_remove(timeout);
+ timeout = 0;
+ }
+ }
+ }
}
/*
@@ -110,7 +135,7 @@ start_board (GcomprisBoard * agcomprisBoard)
gcomprisBoard = agcomprisBoard;
gcomprisBoard->level = 1;
- gcomprisBoard->maxlevel = 4;
+ gcomprisBoard->maxlevel = 9;
gcomprisBoard->sublevel = 1;
gcomprisBoard->number_of_sublevel = 1; /* Go to next level after
* this number of 'play' */
@@ -121,11 +146,13 @@ start_board (GcomprisBoard * agcomprisBoard)
if(pixmap) {
gcompris_bar_set_repeat_icon(pixmap);
gdk_pixbuf_unref(pixmap);
- gcompris_bar_set(GCOMPRIS_BAR_REPEAT_ICON);
+ gcompris_bar_set(GCOMPRIS_BAR_LEVEL|GCOMPRIS_BAR_REPEAT_ICON);
} else {
- gcompris_bar_set(GCOMPRIS_BAR_REPEAT);
+ gcompris_bar_set(GCOMPRIS_BAR_LEVEL|GCOMPRIS_BAR_REPEAT);
}
-
+
+ animation = gcompris_load_animation( "connect4/sablier.txt" );
+
awele_next_level ();
gamewon = FALSE;
@@ -142,6 +169,7 @@ end_board ()
if (gcomprisBoard != NULL)
{
pause_board (TRUE);
+ gcompris_free_animation(animation);
awele_destroy_all_items ();
}
gcomprisBoard = NULL;
@@ -170,8 +198,14 @@ is_our_board (GcomprisBoard * gcomprisBoard)
*
*/
static void repeat (){
-
- buttonNewGameClick(graphsElt);
+ if (computer_turn){
+ gcompris_deactivate_animation(anim_item);
+ if (timeout){
+ g_source_remove(timeout);
+ timeout = 0;
+ }
+ }
+ awele_next_level();
}
@@ -183,7 +217,16 @@ set_level (guint level)
{
gcomprisBoard->level=level;
gcomprisBoard->sublevel = 1;
+
+ if (computer_turn){
+ gcompris_deactivate_animation(anim_item);
+ if (timeout){
+ g_source_remove(timeout);
+ timeout = 0;
+ }
+ }
awele_next_level();
+
}
}
@@ -204,13 +247,27 @@ awele_next_level ()
awele_destroy_all_items ();
gamewon = FALSE;
+ computer_turn = FALSE;
/*
* Create the level
*/
awele_create_item (gnome_canvas_root (gcomprisBoard->canvas));
-
-
+
+ if ((gcomprisBoard->level % 2) ==0){
+ computer_turn = TRUE;
+ staticAwale->player = HUMAN;
+ timeout = g_timeout_add (2000,
+ (GSourceFunc) to_computer,
+ NULL);
+ anim_item = (GnomeCanvasItem*)
+ gcompris_activate_animation( boardRootItem,
+ animation );
+ gnome_canvas_item_show(anim_item->canvas);
+
+ } else {
+ computer_turn = FALSE;
+ }
}
/*
@@ -317,7 +374,7 @@ awele_create_item (GnomeCanvasGroup * parent)
}
- staticAwale = (AWALE *) malloc (sizeof (AWALE));
+ staticAwale = (AWALE *) g_malloc (sizeof (AWALE));
if (!staticAwale)
exit (1);
@@ -327,7 +384,9 @@ awele_create_item (GnomeCanvasGroup * parent)
staticAwale->board[i] = NBBEANSPERHOLE;
}
- staticAwale->player = HUMAN;
+ /* ->player is last player */
+ /* next is human */
+ staticAwale->player = COMPUTER;
for (i = 0; i < NBPLAYER; i++)
{
@@ -336,14 +395,6 @@ awele_create_item (GnomeCanvasGroup * parent)
graphsElt = (GRAPHICS_ELT *) malloc (sizeof (GRAPHICS_ELT));
- for (i = 0; i < 6; i++)
- {
- buttonClickArgs[i] =
- (CALLBACK_ARGS *) malloc (sizeof (CALLBACK_ARGS));
- buttonClickArgs[i]->graphsElt = graphsElt;
- buttonClickArgs[i]->numeroCase = i;
- }
-
/*
* Boucle pour creer et positionner les boutons qui serviront
* a selectionner la case a jouer
@@ -407,7 +458,7 @@ awele_create_item (GnomeCanvasGroup * parent)
gtk_signal_connect (GTK_OBJECT (graphsElt->button[i]),
"event", GTK_SIGNAL_FUNC (buttonClick),
- (gpointer) buttonClickArgs[i]);
+ GINT_TO_POINTER(i));
}
@@ -482,7 +533,7 @@ awele_create_item (GnomeCanvasGroup * parent)
graphsElt->msg = gnome_canvas_item_new (boardRootItem,
gnome_canvas_text_get_type (),
- "text", "Selectionne une case a jouer",
+ "text", _("Choose an house"),
"font", "12x24",
"size", 20000,
"x", (double) 400,
@@ -501,29 +552,32 @@ awele_create_item (GnomeCanvasGroup * parent)
static void
game_won ()
{
- gcomprisBoard->sublevel++;
-
- if (gcomprisBoard->sublevel > gcomprisBoard->number_of_sublevel)
- {
- /*
- * Try the next level
- */
- gcomprisBoard->sublevel = 1;
- gcomprisBoard->level++;
- if (gcomprisBoard->level > gcomprisBoard->maxlevel)
- { // the
+ if (sublevel_finished){
+ gcomprisBoard->sublevel++;
+
+ if (gcomprisBoard->sublevel > gcomprisBoard->number_of_sublevel)
+ {
+ /*
+ * Try the next level
+ */
+ gcomprisBoard->sublevel = 1;
+ gcomprisBoard->level++;
+ if (gcomprisBoard->level > gcomprisBoard->maxlevel)
+ { // the
// current
// board
// is
// finished
// : bail
// out
- board_finished (BOARD_FINISHED_RANDOM);
- return;
- }
-
- }
- awele_next_level ();
+ board_finished (BOARD_FINISHED_RANDOM);
+ return;
+ }
+
+ }
+ }
+ sublevel_finished = FALSE;
+ awele_next_level ();
}
/**
@@ -574,6 +628,61 @@ initBoardGraphics (GRAPHICS_ELT * graphsElt)
}
}
+
+static gboolean to_computer(gpointer data)
+{
+ short int coup;
+
+ if (!computer_turn){
+ g_warning ("to_computer called but not compter_turn");
+ return FALSE;
+ }
+
+ if (board_paused){
+ g_warning ("to_computer called but board paused");
+ timeout = 0;
+ return TRUE;
+ }
+
+ coup = think (staticAwale, gcomprisBoard->level);
+
+ gcompris_deactivate_animation(anim_item);
+ computer_turn = FALSE;
+
+ if (coup >= 0){
+ AWALE *tmpAw = staticAwale;
+ staticAwale = moveAwale (coup, tmpAw);
+ if (!staticAwale){
+ g_error("le coup devrait être bon !");
+ }
+ gboolean IAmHungry = diedOfHunger(staticAwale);
+ if (!IAmHungry){
+ g_free(tmpAw);
+ updateNbBeans (0);
+ updateCapturedBeans ();
+ g_object_set (graphsElt->msg, "text",
+ _("Your turn to play ..."), NULL);
+ } else {
+ /* computer hungry but human can't give it beans */
+ /* Human player win by catching all the beans left. */
+ gamewon = TRUE;
+ sublevel_finished = TRUE;
+ gcompris_display_bonus(TRUE, BONUS_FLOWER);
+ }
+ } else {
+ /* computer can't play. Why? human is hungry and i cannot give it
+ to eat */
+ /* if human has 24 beans, it's draw (human win in gcompris) */
+ /* if not, all staying are captured by computer and computer win */
+ gamewon = TRUE;
+ sublevel_finished = (staticAwale->CapturedBeans[HUMAN] == 24);
+ gcompris_display_bonus(sublevel_finished, BONUS_FLOWER);
+ }
+
+ timeout = 0;
+ return FALSE;
+}
+
/**
* Fonction effectuant la procedure associe a un clic sur pixmap
* Cette fonction est appelee quand un clic sur un bouton est effectue.\n
@@ -588,93 +697,67 @@ initBoardGraphics (GRAPHICS_ELT * graphsElt)
static gint
buttonClick (GtkWidget * item, GdkEvent * event, gpointer data)
{
-
- CALLBACK_ARGS *args;
- short int retourMove;
- short int returnMove;
- short int coup;
-
- args = (CALLBACK_ARGS *) data;
+ gint numeroCase = GPOINTER_TO_INT(data);
switch (event->type)
{
case GDK_ENTER_NOTIFY:
g_object_set (GTK_OBJECT
- (args->graphsElt->button[args->numeroCase]),
+ (graphsElt->button[numeroCase]),
"pixbuf",
- args->graphsElt->pixbufButtonNotify[args->
- numeroCase],
+ graphsElt->pixbufButtonNotify[numeroCase],
"y", (double) Y_BOUTONS, NULL);
break;
case GDK_LEAVE_NOTIFY:
g_object_set (GTK_OBJECT
- (args->graphsElt->button[args->numeroCase]),
+ (graphsElt->button[numeroCase]),
"pixbuf",
- args->graphsElt->pixbufButton[args->numeroCase],
+ graphsElt->pixbufButton[numeroCase],
"y", (double) Y_BOUTONS, NULL);
break;
case GDK_BUTTON_PRESS:
-
- g_object_set (GTK_OBJECT
- (args->graphsElt->button[args->numeroCase]),
- "pixbuf",
- args->graphsElt->pixbufButtonClicked[args->
- numeroCase],
- "y", (double) Y_BOUTONS + 3, NULL);
-
- g_object_set (args->graphsElt->msg, "text", "", NULL);
-
- if (isValidMove (args->numeroCase, staticAwale) != TRUE)
- {
- g_object_set (args->graphsElt->msg, "text", errorMsg,
- NULL);
- }
- else
- {
- retourMove = move (args->numeroCase, staticAwale);
- if (retourMove == TRUE || retourMove == GAMEOVER)
- {
- updateNbBeans (args->graphsElt->nbBeansHole,
- boardRootItem,
- args->graphsElt->
- ptBeansHoleLink, 0);
- updateCapturedBeans (args->graphsElt->
- Captures);
- staticAwale->player = COMPUTER;
- }
- if (retourMove == GAMEOVER)
- g_object_set (args->graphsElt->msg, "text",
- "FIN DE LA PARTIE !!!", NULL);
- }
-
- break;
+ if (computer_turn)
+ return TRUE;
+
+ g_object_set (GTK_OBJECT
+ (graphsElt->button[numeroCase]),
+ "pixbuf",
+ graphsElt->pixbufButtonClicked[numeroCase],
+ "y", (double) Y_BOUTONS + 3, NULL);
+
+ g_object_set (graphsElt->msg, "text", "", NULL);
+
+ AWALE *tmpaw = moveAwale (numeroCase, staticAwale);
+ if (!tmpaw)
+ {
+ g_object_set (graphsElt->msg, "text", _("Not allowed! Try again !"),
+ NULL);
+ }
+ else
+ {
+ g_free(staticAwale);
+ staticAwale = tmpaw;
+ updateNbBeans (0);
+ updateCapturedBeans ();
+ if (!gamewon){
+ computer_turn = TRUE;
+ timeout = g_timeout_add (2000,
+ (GSourceFunc) to_computer,
+ NULL);
+ anim_item = (GnomeCanvasItem*)
+ gcompris_activate_animation( boardRootItem,
+ animation );
+ }
+ }
+
+ break;
case GDK_BUTTON_RELEASE:
- g_object_set (GTK_OBJECT
- (args->graphsElt->button[args->numeroCase]),
- "pixbuf",
- args->graphsElt->pixbufButtonNotify[args->
- numeroCase],
- "y", (double) Y_BOUTONS, NULL);
-
-
- if (staticAwale->player == COMPUTER)
- {
- sleep (1);
- coup = think (staticAwale, gcomprisBoard->level);
- returnMove = move (coup, staticAwale);
- updateNbBeans (args->graphsElt->nbBeansHole,
- boardRootItem,
- args->graphsElt->ptBeansHoleLink, 0);
- updateCapturedBeans (args->graphsElt->Captures);
- staticAwale->player = HUMAN;
- if (returnMove == GAMEOVER)
- g_object_set (args->graphsElt->msg, "text",
- "FIN DE LA PARTIE !!!", NULL);
- else g_object_set (args->graphsElt->msg, "text",
- "A toi de jouer ...", NULL);
-
- }
- break;
+ g_object_set (GTK_OBJECT
+ (graphsElt->button[numeroCase]),
+ "pixbuf",
+ graphsElt->pixbufButtonNotify[numeroCase],
+ "y", (double) Y_BOUTONS, NULL);
+ break;
default:
break;
}
@@ -695,91 +778,91 @@ buttonClick (GtkWidget * item, GdkEvent * event, gpointer data)
* @return Renvoi du pointeur sur la zone memoire apres redimension (n'a probablement pas changé d'adresse).
*/
static BEANHOLE_LINK *
-updateNbBeans (GnomeCanvasItem * nbBeansHole[NBHOLE],
- GnomeCanvasGroup * rootGroup,
- BEANHOLE_LINK * ptLink, int alpha)
+updateNbBeans (int alpha)
{
- char buffer[3]; //Manipulation chaines de caracteres
- int i, j, k, idxTabBeans = 0; //Compteur Boucle Manipulation Elements graphiques
- static short int nbActiveBean = NBTOTALBEAN; //nbre graine restant sur plateau
- static short int nbOldActiveBean; //nbre graine restant sur plateau au tour precedent
- BEANHOLE_LINK *ptBeansHoleLink = NULL; //pointeur sur structures stockant les item graines et la case dans laquelle elles se trouvent.
-
- /**
- * Sauvegarde du nombre de graines restantes sur le plateau de jeu
- * pour le prochain appel a la fonction.
- * Mise a jour de nbActiveBean avec nouvelle configuration du plateau de jeu.
- */
- if (alpha)
- {
- nbOldActiveBean = 48;
- }
- else
- {
- nbOldActiveBean = nbActiveBean;
- }
-
- nbActiveBean =
- NBTOTALBEAN - (staticAwale->CapturedBeans[HUMAN] +
- staticAwale->CapturedBeans[COMPUTER]);
-
- /**
- * Destruction d'autant d'elements graphiques graines
- * qu'il y a eu de captures pdt ce tour de jeu
- */
- for (ptBeansHoleLink = &ptLink[nbActiveBean], i = 0;
- i < nbOldActiveBean - nbActiveBean; i++, ptBeansHoleLink++)
+ char buffer[3]; //Manipulation chaines de caracteres
+ int i, j, k, idxTabBeans = 0; //Compteur Boucle Manipulation Elements graphiques
+ static short int nbActiveBean = NBTOTALBEAN; //nbre graine restant sur plateau
+ static short int nbOldActiveBean; //nbre graine restant sur plateau au tour precedent
+ BEANHOLE_LINK *ptBeansHoleLink = NULL; //pointeur sur structures stockant les item graines et la case dans laquelle elles se trouvent.
+
+ /**
+ * Sauvegarde du nombre de graines restantes sur le plateau de jeu
+ * pour le prochain appel a la fonction.
+ * Mise a jour de nbActiveBean avec nouvelle configuration du plateau de jeu.
+ */
+ if (alpha)
+ {
+ nbOldActiveBean = 48;
+ }
+ else
+ {
+ nbOldActiveBean = nbActiveBean;
+ }
+
+ nbActiveBean =
+ NBTOTALBEAN - (staticAwale->CapturedBeans[HUMAN] +
+ staticAwale->CapturedBeans[COMPUTER]);
+
+ /**
+ * Destruction d'autant d'elements graphiques graines
+ * qu'il y a eu de captures pdt ce tour de jeu
+ */
+ for (ptBeansHoleLink = &(graphsElt->ptBeansHoleLink)[nbActiveBean], i = 0;
+ i < nbOldActiveBean - nbActiveBean; i++, ptBeansHoleLink++)
+ {
+ gtk_object_destroy (GTK_OBJECT (ptBeansHoleLink->beanPixbuf));
+ }
+
+
+ /**
+ * Allocation d'un nouvel espace memoire stockant les item graines
+ * et la case dans laquelle elles se trouvent. Puis liberation de la fin de
+ * l'ancien espace memoire.
+ */
+
+ ptBeansHoleLink =
+ (BEANHOLE_LINK *) realloc (graphsElt->ptBeansHoleLink,
+ nbActiveBean *
+ sizeof (BEANHOLE_LINK));
+
+ /**
+ * Pour chaque case du plateau, mise a jour du nbre de graines qu'elle contient.
+ * Et pour chaque graine de cette case, deplacement d'un element graphique type graine
+ * dans cette case. Et mise a jour de l'information hole dans la structure BEANHOLE_LINK.
+ */
+ for (i = NBHOLE - 1; i >= 0; i--)
+ {
+ sprintf (buffer, "%d", staticAwale->board[i]);
+ gnome_canvas_item_set (graphsElt->nbBeansHole[i], "text", buffer, NULL);
+
+ for (j = 0;
+ j < staticAwale->board[i] && idxTabBeans < nbActiveBean;
+ j++, idxTabBeans++)
{
- gtk_object_destroy (GTK_OBJECT (ptBeansHoleLink->beanPixbuf));
+
+ k = 0 + rand () % 4;
+
+ gnome_canvas_item_set (ptBeansHoleLink[idxTabBeans].
+ beanPixbuf, "x",
+ (double) caseCoord[i] +
+ rand () % 50, "y",
+ (double) (((i <
+ 6) ? 260 : 130) +
+ rand () % 60), NULL);
+
+ ptBeansHoleLink[idxTabBeans].hole = i;
}
-
-
- /**
- * Allocation d'un nouvel espace memoire stockant les item graines
- * et la case dans laquelle elles se trouvent. Puis liberation de la fin de
- * l'ancien espace memoire.
- */
-
- ptBeansHoleLink =
- (BEANHOLE_LINK *) realloc (ptLink,
- nbActiveBean *
- sizeof (BEANHOLE_LINK));
-
- /**
- * Pour chaque case du plateau, mise a jour du nbre de graines qu'elle contient.
- * Et pour chaque graine de cette case, deplacement d'un element graphique type graine
- * dans cette case. Et mise a jour de l'information hole dans la structure BEANHOLE_LINK.
- */
- for (i = NBHOLE - 1; i >= 0; i--)
- {
- sprintf (buffer, "%d", staticAwale->board[i]);
- gnome_canvas_item_set (nbBeansHole[i], "text", buffer, NULL);
-
- for (j = 0;
- j < staticAwale->board[i] && idxTabBeans < nbActiveBean;
- j++, idxTabBeans++)
- {
-
- k = 0 + rand () % 4;
-
- gnome_canvas_item_set (ptBeansHoleLink[idxTabBeans].
- beanPixbuf, "x",
- (double) caseCoord[i] +
- rand () % 50, "y",
- (double) (((i <
- 6) ? 260 : 130) +
- rand () % 60), NULL);
-
- ptBeansHoleLink[idxTabBeans].hole = i;
- }
-
- }
-
- /**
- * Renvoi du pointeur sur la zone memoire retaillee (n'a probablement pas change d'adresse).
- */
- return ptBeansHoleLink;
+
+ }
+
+ /**
+ * Renvoi du pointeur sur la zone memoire retaillee (n'a probablement pas change d'adresse).
+ */
+
+ graphsElt->ptBeansHoleLink = ptBeansHoleLink;
+ return ptBeansHoleLink;
}
@@ -790,7 +873,7 @@ updateNbBeans (GnomeCanvasItem * nbBeansHole[NBHOLE],
* @param Captures[2] pointeur sur les gnomeCanvasItem d'affichage des scores
*/
static void
-updateCapturedBeans (GnomeCanvasItem * Captures[2])
+updateCapturedBeans ()
{
short int i;
@@ -799,63 +882,13 @@ updateCapturedBeans (GnomeCanvasItem * Captures[2])
for (i = 0; i < 2; i++)
{
sprintf (buffer, "%d", staticAwale->CapturedBeans[i]);
- g_object_set (Captures[i], "text", buffer, NULL);
- if (staticAwale->CapturedBeans[i] > 24)
- {
- gamewon = TRUE;
- gcompris_display_bonus(i==0, BONUS_FLOWER);
- }
+ g_object_set (graphsElt->Captures[i], "text", buffer, NULL);
+ if (staticAwale->CapturedBeans[i] > 24)
+ {
+ gamewon = TRUE;
+ sublevel_finished = (i==0);
+ gcompris_display_bonus(sublevel_finished, BONUS_FLOWER);
+ }
}
}
-
-/**
-* Fonction effectuant la procedure associe a un clic sur le bouton nouvelle Partie
-* Cette fonction est appelee quand un clic sur le bouton nouvelle Partie est effectue.\n
-* Selon l'event->Type declenchement de procedure differentes, modification de l'aspect des boutons\n
-* et declenchement de la reinitialisation du plateau de jeu.
-* @param widget pointeur sur le widget ayant declenche l'evenement eventDelete
-* @param event pointeur sur le type d'evenement
-* @param data un pointeur de type void, pour passer en argument a la fonction\n
-* les elements graphiques a modifier.
-* @return un entier
-*/
-static gint
-buttonNewGameClick (GRAPHICS_ELT *graphsElt)
-{
- short int nbCapturedBean = 0;
- BEANHOLE_LINK *ptLink;
- int i;
-
- nbCapturedBean =
- staticAwale->CapturedBeans[HUMAN] +
- staticAwale->CapturedBeans[COMPUTER];
-
- /**
- * Destruction de toute les graines et remise a zero compteur de capture
- * et indicateur nbre de graine par case
- */
- for (ptLink = graphsElt->ptBeansHoleLink, i = 0;
- i < NBTOTALBEAN - nbCapturedBean; i++, ptLink++)
- {
- gtk_object_destroy (GTK_OBJECT (ptLink->beanPixbuf));
- }
-
- for (i = 0; i < NBHOLE; i++)
- {
- staticAwale->board[i] = NBBEANSPERHOLE;
- g_object_set (GTK_OBJECT
- (graphsElt->nbBeansHole[i]),
- "text", "4", NULL);
- }
-
- staticAwale->player = HUMAN;
-
- for (i = 0; i < NBPLAYER; i++)
- {
- staticAwale->CapturedBeans[i] = 0;
- }
-
- updateCapturedBeans (graphsElt->Captures);
- initBoardGraphics (graphsElt);
-}
diff --git a/src/boards/awele.h b/src/boards/awele.h
index 2d883f4..3c75929 100644
--- a/src/boards/awele.h
+++ b/src/boards/awele.h
@@ -54,11 +54,10 @@ typedef struct {
static gint eventDelete (GtkWidget * widget, GdkEvent *event, gpointer data);
static gint eventDestroy (GtkWidget * widget, GdkEvent *event, gpointer data);
static gint buttonClick (GtkWidget *item, GdkEvent *event, gpointer data);
-static gint buttonNewGameClick (GRAPHICS_ELT *graphsElt);
/**
* Fonctions Mise a jour de l'affichage
*/
-static BEANHOLE_LINK * updateNbBeans (GnomeCanvasItem *nbBeansHole[NBHOLE], GnomeCanvasGroup *rootGroup, BEANHOLE_LINK *ptLink, int alpha);
-static void updateCapturedBeans (GnomeCanvasItem *Captures[2]);
+static BEANHOLE_LINK * updateNbBeans (int alpha);
+static void updateCapturedBeans (void);
static void initBoardGraphics (GRAPHICS_ELT *graphsElt);
diff --git a/src/boards/awele_alphaBeta.c b/src/boards/awele_alphaBeta.c
index 1fc7e81..e97d9ea 100644
--- a/src/boards/awele_alphaBeta.c
+++ b/src/boards/awele_alphaBeta.c
@@ -15,11 +15,10 @@
#include "awele_utils.h"
#include <string.h>
#include <stdlib.h>
+#include "gcompris/gcompris.h"
-
-int maxprof;
-static void alphabeta( TREE * t , short int alpha , short int beta );
+static gint maxprof;
/**
* Fonction d'evaluation d'un plateau
@@ -29,27 +28,75 @@ static void alphabeta( TREE * t , short int alpha , short int beta );
* @param AWALE *aw Pointeur sur la structure AWALE a evaluer
* @return Une note d'evaluation du plateau.
*/
-int eval (AWALE *aw){
-
- int score;//, attacDelta, mobilityDelta;
-
- score = aw->CapturedBeans[COMPUTER] - aw->CapturedBeans[HUMAN];
- //attacDelta = threatenDelta(aw)*33;
-
- /*if ((aw->CapturedBeans[COMPUTER] + aw->CapturedBeans[HUMAN]) > 30)
- mobilityDelta = 0;
- else
- mobilityDelta = moveDelta(aw)*22;*/
-
- if (aw->player == HUMAN){
- score = -score;
- //attacDelta = -attacDelta;
- //mobilityDelta = -mobilityDelta;
- }
-
- //score = score*100 + mobilityDelta + attacDelta;
-
- return score;
+gint eval (GNode *node){
+ AWALE *aw = node->data;
+
+ if (aw->CapturedBeans[COMPUTER] > 24)
+ return 25;
+
+ if (aw->CapturedBeans[HUMAN] > 24)
+ return -25;
+
+ return (aw->CapturedBeans[COMPUTER] - aw->CapturedBeans[HUMAN]);
+}
+
+/*
+ * Evaluation function for level 1-2
+ * this function returns always 0. The play is random,
+ * because tree building is randomised.
+ *
+ */
+gint eval_to_null (GNode *node){
+ return 0;
+}
+
+
+gint eval_to_best_capture (GNode *node){
+ AWALE *aw = node->data;
+
+ return (aw->CapturedBeans[COMPUTER]);
+}
+
+/*
+ * firstChild. create all the childs and return first one
+ */
+GNode *firstChild(GNode *node)
+{
+ AWALE *aw = node->data;
+ AWALE *tmpaw;
+ GNode *tmpnode;
+ gint eval_node = eval(node);
+ gint rand_play;
+
+ /* Case node is winning one */
+ if ((eval_node == 25) || (eval_node == -25))
+ return NULL;
+
+ gint i;
+ rand_play = 1 + random()%6;
+
+ for (i = 0 ; i < 6; i++)
+ {
+ tmpaw = moveAwale((rand_play + i)%6 + ((aw->player == HUMAN )? 6 : 0), aw);
+ if (tmpaw){
+ tmpnode = g_node_new(tmpaw);
+ g_node_insert (node, -1, tmpnode);
+ }
+ }
+
+ return g_node_first_child(node);
+}
+
+/* next sibling */
+GNode *nextSibling(GNode *node)
+{
+ return g_node_next_sibling(node);
+}
+
+
+gboolean free_awale(GNode *node,
+ gpointer data){
+ g_free(data);
}
@@ -60,180 +107,95 @@ int eval (AWALE *aw){
* La profondeur augmente au fur et mesure de la partie quand le nombre de graines diminue.\n
* @param aw Un pointeur sur le plateau a partir duquel reflechir
* @return Le meilleur coup calcule par la machine
+* le player est celui qui a joué le dernier coup.
*/
-short int think( AWALE *a, short int level){
- TREE * t ;
- int npris ;
- short int best;
-
- maxprof = level ;
-
- /*augmente la profondeur quand le nombre de pieces diminue */
- npris = a->CapturedBeans[HUMAN] + a->CapturedBeans[COMPUTER] ;
- if ( npris > 20 ) maxprof ++ ;
- if ( npris > 25 ) maxprof ++ ;
- if ( npris > 30 ) maxprof ++ ;
- if ( npris > 35 ) maxprof ++ ;
- if ( npris > 40 ) maxprof ++ ;
-
- /* initialisation de l'arbre */
- t = create_tree( 0 , a->player , a ) ;
-
- /* recherche meilleur coup */
- alphabeta( t , -INFINI , INFINI ) ;
-
- best = t->best;
-
- destroy_tree( &t ) ;
-
- return (best);
-}
-/**
-* Algorithme MiniMax (amelioration AlphaBeta)
-* Cette fonction va etudier les meilleurs coups possibles a jouer \n
-* de facon recursive pour tous les coups possibles\n
-* @param t La racine de l'arbre
-* @param alpha optimisation alphaBeta coupure de type Max
-* @param beta optimisation alphaBeta coupure de type Min
-*/
-static void alphabeta( TREE * t , short int alpha , short int beta ){
-
- short int i,j, n,is,ie,isOtherPlayer,ieOtherPlayer;
- short int m,note;
- char prune=FALSE ;
- char FinPartie = TRUE;
-
- is = (t->aw->player == HUMAN)?START_HUMAN:START_COMPUTER;
- ie = (t->aw->player == HUMAN)?END_HUMAN:END_COMPUTER;
- isOtherPlayer = (t->aw->player == HUMAN)?START_COMPUTER:START_HUMAN;
- ieOtherPlayer = (t->aw->player == HUMAN)?END_COMPUTER:END_HUMAN;
-
- /**
- * Test si fin de partie par famine
- */
- for (n =0, i=is; i<=ie; i++)
- n += t->aw->board[i];
-
- if (!n)
- for (j=isOtherPlayer; j<=ieOtherPlayer; j++){
- if (t->aw->board[j] <= ieOtherPlayer -j)
- FinPartie = FinPartie & TRUE;
- else {
- FinPartie = FinPartie & FALSE;
- break;
- }
- }
-
- /* si noeud terminal calcul note */
- if ( t->prof == DEF_DEPTH || t->aw->CapturedBeans[HUMAN]+t->aw->CapturedBeans[COMPUTER] >= NBTOTALBEAN -2 || FinPartie != TRUE) {
- t->note = eval (t->aw);
- return ;
- }
-
-
- /* remontee note des fils */
- m = alpha ;
-
- for ( n=0,i=is ; i<=ie && !prune ; n++,i++ )
-
- if (testMove(i, t->aw)) {
-
- if (t->prof >0)
- t->son[n] = create_tree( t->prof+1, switch_player(t->aw->player), t->aw ) ;
- else
- t->son[n] = create_tree( t->prof+1, t->aw->player, t->aw ) ;
-
- if (testMove(i, t->son[n]->aw)){
- move ( i , t->son[n]->aw);
- t->son[n]->aw->player = switch_player (t->son[n]->aw->player);
- alphabeta( t->son[n] , -beta , -m ) ;
- note = -t->son[n]->note ;
- if ( note > m ) {
- m = note ;
- t->best = i ;
- }
-
- if ( m >= beta ) prune=TRUE ;
- }
-
- destroy_tree( &(t->son[n]) ) ;
- }
-
- t->note = m ;
-}
-/**
-* Fonction de calcul de la difference du nombre de cases menacantes
-* Cette fonction va calculer le nombre de cases menacantes pour les deux joueurs\n
-* puis faire la diffrence des deux.
-* @param aw Un pointeur sur le plateau a evaluer
-* @return un entier egal a la difference des cases menacantes
-*/
-short int threatenDelta (AWALE *aw){
-
- short int i, tempo;
- short int threatenHuman = 0, threatenComputer = 0;
- AWALE tmpAw[13];
-
-
- memcpy(&tmpAw[12], aw, sizeof(AWALE));
-
- for (i=START_HUMAN; i<=END_COMPUTER; i++){
- if (i<=END_HUMAN){
- if (testMove (i, &tmpAw[12])){
- memcpy(&tmpAw[i], aw, sizeof(AWALE));
- tempo = tmpAw[i].CapturedBeans[HUMAN];
- move(i, tmpAw);
- if (tmpAw[i].CapturedBeans[HUMAN] > tempo)
- threatenHuman++;
- }
- }
- else {
- tmpAw[i].player = switch_player(aw->player);
- tmpAw[12].player = COMPUTER;
- if (testMove (i, &tmpAw[12])){
- memcpy(&tmpAw[i], aw, sizeof(AWALE));
- tempo = tmpAw[i].CapturedBeans[COMPUTER];
- move(i, tmpAw);
- if (tmpAw[i].CapturedBeans[COMPUTER] > tempo)
- threatenComputer++;
- }
- }
-
-
- }
-
- return (threatenComputer - threatenHuman);
+short int think( AWALE *static_awale, short int level){
+
+ AWALE *aw = g_malloc(sizeof(AWALE));
+ memcpy (aw, static_awale, sizeof(AWALE));
+
+ GNode *t = g_node_new(aw) ;
+
+ int npris ;
+ int best = -1;
+ int value = 0;
+ EvalFunction use_eval = NULL;
+
+ switch (level) {
+ case 1:
+ maxprof = 1;
+ use_eval = &eval_to_null;
+ g_warning("search depth 1, evaluation null");
+ break;
+ case 2:
+ maxprof = 1;
+ use_eval = &eval_to_best_capture;
+ g_warning("search depth 1, evaluation best capture");
+ break;
+ case 3:
+ case 4:
+ maxprof = 2;
+ use_eval = &eval;
+ g_warning("search depth %d, evaluation best difference", maxprof);
+ break;
+ case 5:
+ case 6:
+ maxprof = 4;
+ use_eval = &eval;
+ g_warning("search depth %d, evaluation best difference", maxprof);
+ break;
+ case 7:
+ case 8:
+ maxprof = 6;
+ use_eval = &eval;
+ g_warning("search depth %d, evaluation best difference", maxprof);
+ break;
+ case 9:
+ maxprof = 8;
+ use_eval = &eval;
+ g_warning("search depth %d, evaluation best difference", maxprof);
+ break;
+ default:
+ maxprof = 8;
+ use_eval = &eval;
+ g_warning("search depth %d, evaluation best difference", maxprof);
+ break;
+ }
+
+ value = gcompris_alphabeta( TRUE,
+ t,
+ use_eval,
+ &best,
+ (FirstChildGameFunction) firstChild,
+ (NextSiblingGameFunction) nextSibling,
+ -INFINI ,
+ INFINI,
+ maxprof) ;
+
+ if (best < 0){
+ g_warning("Leaf node, game is over");
+ return -1;
+ }
+ GNode *tmpNode = g_node_nth_child (t, best);
+
+ AWALE *tmpaw = tmpNode->data;
+
+ g_warning("THINK best : %d, play: %d", value, tmpaw->last_play);
+
+ best = tmpaw->last_play;
+
+ /* free awales*/
+ g_node_traverse (t,
+ G_IN_ORDER,
+ G_TRAVERSE_ALL,
+ -1,
+ (GNodeTraverseFunc) free_awale,
+ NULL);
+
+ /* free tree */
+ g_node_destroy(t);
+
+ return (best);
}
-
-/**
-* Fonction de calcul de la difference de la mobilite des deux joueurs
-* Cette fonction va calculer le nombre de cases non vides pour les deux joueurs\n
-* puis faire la diffrence des deux.
-* @param aw Un pointeur sur le plateau a evaluer
-* @return un entier egal a la difference des cases non vides des deux joueurs
-*/
-short int moveDelta (AWALE *aw){
-
- short int i;
- short int moveHuman = 0, moveComputer = 0;
- AWALE tmpAw;
-
- memcpy (&tmpAw, aw, sizeof (AWALE));
-
- for (i=START_HUMAN; i<=END_COMPUTER; i++)
-
- if (i == START_COMPUTER)
- tmpAw.player = COMPUTER;
-
- if (testMove (i, &tmpAw)){
- if (i<=END_HUMAN)
- moveHuman++;
- else
- moveComputer++;
-
- }
-
- return (moveComputer - moveHuman);
-}
diff --git a/src/boards/awele_utils.c b/src/boards/awele_utils.c
index 7899461..368503c 100644
--- a/src/boards/awele_utils.c
+++ b/src/boards/awele_utils.c
@@ -12,9 +12,8 @@
* 330, Boston, MA 02111-1307 USA
*/
-#include <stdlib.h>
+#include "awele_utils.h"
#include <string.h>
-#include <awele_utils.h>
/**
* Fonction test si famine
@@ -25,21 +24,22 @@
* @param start un entier donnant la premiere case de l'opposant
* @param end un entier donnant la derniere case de l'opposant
* @return TRUE si ce mouvement ne declenche pas une famine, FALSE sinon
+* player est le dernier à avoir joué. C'est son coté qui peut être vide.
*/
-short int isOpponentHungry(AWALE * aw, short int start, short int end)
+short int isOpponentHungry(short int player, AWALE * aw)
{
+ short int i, total, start, end;
- short int i, total;
- extern char errorMsg[30];
+ start = (player == HUMAN)? START_HUMAN : START_COMPUTER;
+ end = (player == HUMAN)? END_HUMAN : END_COMPUTER;
for (total = 0, i = start; i <= end; i++) {
total += aw->board[i];
}
- if (total)
+ if (!total)
return TRUE;
- strcpy(errorMsg, MSG_FAMINE);
return FALSE;
}
@@ -49,83 +49,73 @@ short int isOpponentHungry(AWALE * aw, short int start, short int end)
* @param hole entier designant la case du plateau choisie
* @param aw pointeur sur la structure AWALE courante.
*/
-short int isValidMove(short int hole, AWALE * aw)
+AWALE *moveAwale(short int hole, AWALE * aw)
{
-
- extern char errorMsg[30];
- if (aw->board[hole])
- return TRUE;
-
- strcpy(errorMsg, MSG_EMPTYHOLE);
- return FALSE;
-}
-
-
-/**
-* Fonction deplacement des graines
-* Cette fonction est appele a chaque deplacement de graines
-* @param hole la case a partir de laquelle commencer le deplacement
-* @param un pointeur sur la structure AWALE courante, pour laquelle efetuer le deplacement
-* @return TRUE si mouvement valide, le test de famine ne peut etre fait qu'apres deplacement\n
-* FALSE sinon.
-*/
-short int move(short int hole, AWALE * aw)
-{
-
- AWALE tempAw;
- short int i, j, nbBeans, start, end;
-
-
- /**
- * Sauvegarde de l'awale courant dans un awale temporaire
- * pour effectuer le mouvement et tester s'il est valide.
- */
- memcpy(&tempAw, aw, sizeof(AWALE));
-
-
- start = (tempAw.player == HUMAN) ? START_COMPUTER : START_HUMAN;
- end = (tempAw.player == HUMAN) ? END_COMPUTER : END_HUMAN;
-
- nbBeans = tempAw.board[hole];
- tempAw.board[hole] = 0;
-
- // Déplacement des graines
- for (i = nbBeans, j = hole + 1; i > 0; i--, j++) {
- if (j == NBHOLE)
- j = 0;
- if (j != hole)
- tempAw.board[j] += 1;
- else
- i++;
+ AWALE *tempAw, *tempAwGs;
+ gboolean has_capture = FALSE;
+
+ if (!aw->board[hole]){
+ return NULL;
+ }
+
+ short int nbBeans, j, last;
+
+ tempAw = g_malloc(sizeof(AWALE));
+
+ memcpy(tempAw, aw, sizeof(AWALE));
+
+ tempAw->last_play = hole;
+
+ nbBeans = tempAw->board[hole];
+ tempAw->board[hole] = 0;
+
+ // Déplacement des graines
+ for (j = 1, last = (hole+1)%12 ; j <= nbBeans; j++) {
+ tempAw->board[last] += 1;
+ last = (last + 1) % 12;
+ if (last == hole)
+ last = (last +1)% 12;
+ }
+
+ last = (last +11) %12;
+
+ /* Grand Slam (play and no capture because this let other player hungry */
+ tempAwGs = g_malloc(sizeof(AWALE));
+ memcpy(tempAwGs, tempAw, sizeof(AWALE));
+
+ // capture
+ while ((last >= ((tempAw->player == HUMAN)? 0 : 6))
+ && (last < ((tempAw->player == HUMAN)? 6 : 12))){
+ if ((tempAw->board[last] == 2) || (tempAw->board[last] == 3)){
+ has_capture = TRUE;
+ tempAw->CapturedBeans[switch_player(tempAw->player)] += tempAw->board[last];
+ tempAw->board[last] = 0;
+ last = (last+11)%12;
+ continue;
}
-
- j--;
- // Comptage des points et mise a zero ou il y a capture
- if ((j >= start && j <= end)
- && (tempAw.board[j] == 2 || tempAw.board[j] == 3)) {
- for (i = j; i >= start; i--) {
- if (tempAw.board[i] == 2 || tempAw.board[i] == 3) {
- tempAw.CapturedBeans[tempAw.player] += tempAw.board[i];
- tempAw.board[i] = 0;
- } else
- break;
- }
+ break;
+ }
+
+ if (isOpponentHungry(tempAw->player, tempAw)){
+ if (has_capture){
+ /* Grand Slam case */
+ //g_warning("Grand Slam: no capture");
+ g_free(tempAw);
+ return tempAwGs;
+ } else{
+ /* No capture and opponent hungry -> forbidden */
+ //g_warning("isOpponentHungry %s TRUE",(tempAw->player == HUMAN)? "HUMAN" : "COMPUTER" );
+ g_free(tempAw);
+ g_free(tempAwGs);
+ return NULL;
}
-
-
-
- if (isOpponentHungry(&tempAw, start, end) != TRUE)
- return FALSE;
- else
- memcpy(aw, &tempAw, sizeof(AWALE));
-
- if (isEndOfGame(aw) == GAMEOVER)
- return GAMEOVER;
-
- return TRUE;
+ }
+ else {
+ tempAw->player = switch_player(tempAw->player);
+ return tempAw;
+ }
}
-
/**
* Fonction de chgt de joueur
* Cette fonction permet de renvoyer la valeur de l'opposant
@@ -146,178 +136,31 @@ short int switch_player(short int player)
short int randplay(AWALE * a)
{
short int i;
+ AWALE *tmp = NULL;
do {
i = 6 + rand() % 6;
- } while (a->board[i] == 0 && !testMove(i, a));
+ } while (a->board[i] == 0 && !(tmp = moveAwale(i, a)));
+ g_free(tmp);
return (i);
}
-/**
-* Fonction de test si Fin de partie
-* Cette fonction est appelee apres chaque mvt\
-* pour tester si c'est la fin de la partie.
-* @param aw pointeur sur la structure AWALE a evaluer
-* @return GAMEOVER si c'est la fin de la partie, NOT_GAMEOVER sinon
-*/
-short int isEndOfGame(AWALE * aw)
-{
-
- short int start, end, i, iCpt, otherPlayer, oppICpt;
-
- start = (aw->player == HUMAN) ? START_HUMAN : START_COMPUTER;
- end = (aw->player == HUMAN) ? END_HUMAN : END_COMPUTER;
- otherPlayer = (aw->player == HUMAN) ? COMPUTER : HUMAN;
-
- // Comptage du nbre de graine dans le camp du joueur courant.
- iCpt = 0;
- for (i = start; i <= end; i++) {
- iCpt += aw->board[i];
- }
-
- start = (aw->player == HUMAN) ? START_COMPUTER : START_HUMAN;
- end = (aw->player == HUMAN) ? END_COMPUTER : END_HUMAN;
-
- switch (iCpt) {
- case 0: //si le joueur courant n'a plus de graine dans son camp
- for (i = start; i <= end; i++)
- if (aw->board[i] > (end - i))
- // si l'adversaire peut rengrainer :
- return NOT_GAMEOVER;
- /* Sinon, l'adversaire ne peut pas rengrainer :
- comptage des points, mise a zéro des cases */
- aw->CapturedBeans[otherPlayer] +=
- NBTOTALBEAN - (aw->CapturedBeans[HUMAN] +
- aw->CapturedBeans[COMPUTER]);
- for (i = START_HUMAN; i < NBHOLE; i++)
- aw->board[i] = 0;
- return GAMEOVER;
-
- case 1: // S'il ne reste plus q'une graine dans chaque camp alors fin de partie.
- oppICpt = 0;
- for (i = start; i <= end; i++) {
- oppICpt += aw->board[i];
- }
- if (oppICpt == 1 || oppICpt == 0)
- return GAMEOVER;
- }
-
- return NOT_GAMEOVER;
-}
-
-/**
-* Fonction de test mouvement pour les coups de la machine
-* Cette fonction est appelee avt chaque mouvement de la machine pour connaitre\n
-* tous les coups possibles.
-* @param coup un entier representant le coup a tester
-* @param aw Un pointeur su la structure AWALE courante
-* @return TRUE si le mouvement est possible, FALSE sinon
-*/
-short int testMove(short int coup, AWALE * aw)
+/* last player is hungry and cannot be served ? */
+gboolean diedOfHunger(AWALE *aw)
{
+ gint begin = (aw->player == HUMAN) ? 6 : 0;
+ gint k;
- AWALE tempAw;
- short int returnMove = FALSE;
-
- memcpy(&tempAw, aw, sizeof(AWALE));
-
- if (isValidMove(coup, &tempAw))
- returnMove = move(coup, &tempAw);
-
- if (returnMove == TRUE || returnMove == GAMEOVER)
- return TRUE;
- else
+ if (isOpponentHungry(switch_player(aw->player), aw)){
+ for (k=0; k <6; k++){
+ if ( aw->board[begin+k] > 6 - k)
return FALSE;
-
-}
-
-/**
-* Fonction de creation d'un awale
-* Cette fonction reserve en memoire l'espace d'un awale\n
-* et renvoi un pointeur sur la zone reservee
-* @param void
-* @return un pointeur sur la zone nouvellement creee contenant la structure awale
-*/
-AWALE *create_awale()
-{
- AWALE *a;
-
- a = (AWALE *) malloc(sizeof(AWALE));
- if (a == NULL) {
- exit(0);
- }
-
-
- return a;
-
-}
-
-//ATTENTION : cette fonction n'est plus utilisée
-void awale_equal(AWALE * inp, AWALE * out)
-{
- memcpy(out, inp, sizeof(AWALE));
-}
-
-/**
-* Fonction de creation d'un noeud de l'arbre
-* Cette fonction est appelee a chaque creation d'un noeud de l'arbre\n
-* Elle initialise une structure de type TREE, contenant un plateau de jeu,\n
-* et les six fils possibles de ce plateau de jeu (representant les coups directement derives)
-* @param prof entier representant la profondeur du noeud a cree
-* @param player representant le joueur pour lequel le noeud est cree
-* @param aw pointeur sur la structure AWALE mère inseree dans le noeud
-* @return un pointeur sur la structure TREE fraichement cree.
-*/
-TREE *create_tree(short int prof, short int player, AWALE * aw)
-{
- TREE *t;
- short int i;
-
- t = (TREE *) malloc(sizeof(TREE));
- if (t == NULL) {
- exit(0);
}
- t->aw = create_awale();
- memcpy(t->aw, aw, sizeof(AWALE));
- t->prof = prof;
- t->aw->player = player;
- t->note = t->best = 0;
- for (i = 0; i < HALF_SIZE; i++)
- t->son[i] = NULL;
- return t;
-}
-
-/**
-* Fonction de destruction d'un noeud de l'arbre
-* Cette fonction est appelee pour detruire un noeud de l'arbre, et donc libere l'espace memoire
-* @param t un pointeur de pointeur de structure TREE
-* @return void
-*/
-void destroy_tree(TREE ** t)
-{
- short int i;
-
- for (i = 0; i < HALF_SIZE; i++) {
- if ((*t)->son[i] != NULL)
- destroy_tree(&((*t)->son[i]));
- }
-
- destroy_awale(&((*t)->aw));
-
- free(*t);
- *t = NULL;
+ g_warning("%s is died of hunger", (aw->player == HUMAN) ? "HUMAN" : "COMPUTER");
+ return TRUE;
+ }
+ else
+ return FALSE;
}
-/**
-* Fonction de destruction d'un awale.
-* Cette fonction libere l'espace memoire pris par le pointeur de pointeur de structure AWALE
-* @param a Un pointeur de pointeur de structure AWALE
-* @return void
-*/
-void destroy_awale(AWALE ** a)
-{
- free(*a);
-
- (*a) = NULL;
-}
diff --git a/src/boards/awele_utils.h b/src/boards/awele_utils.h
index 0f06074..a3dd1ce 100644
--- a/src/boards/awele_utils.h
+++ b/src/boards/awele_utils.h
@@ -12,6 +12,7 @@
* 330, Boston, MA 02111-1307 USA
*/
+#include "gcompris/gcompris.h"
#ifndef TRUE
#define TRUE 1
@@ -49,38 +50,26 @@
* Definition nouveaux types de variables
*/
typedef struct {
- short int board[NBHOLE];
- short int CapturedBeans[NBPLAYER];
- short int player;
+ short int board[NBHOLE];
+ short int CapturedBeans[NBPLAYER];
+ short int player;
+ short int last_play;
} AWALE;
-typedef struct tree {
- short int prof; /* nb de 1/2 coup depuis racine */
- short int note; /* note calculee */
- short int best; /* meilleur fils */
- AWALE *aw; /* awele courant */
- struct tree *son[HALF_SIZE];
-} TREE;
+
+
/**
* Fonction de manipulation de l'awale
*/
-short int isValidMove(short int hole, AWALE * aw); // test si mouvement valide
-short int move(short int hole, AWALE * aw);
+gboolean diedOfHunger(AWALE *aw);
+AWALE *moveAwale(short int hole, AWALE * aw);
short int think(AWALE * a, short int level);
-short int isEndOfGame(AWALE * aw);
short int randplay(AWALE * a);
-short int testMove(short int coup, AWALE * aw);
-
-void destroy_tree(TREE ** t);
-void destroy_awale(AWALE ** a);
short int switch_player(short int player);
-TREE *create_tree(short int prof, short int player, AWALE * aw);
-AWALE *create_awale();
-void awale_equal(AWALE * inp, AWALE * out);
short int threatenDelta(AWALE * aw);
short int moveDelta(AWALE * aw);
-int eval(AWALE * aw);
+gint eval(GNode *node);
diff --git a/src/boards/click_on_letter.c b/src/boards/click_on_letter.c
index 4716d35..22bcabe 100644
--- a/src/boards/click_on_letter.c
+++ b/src/boards/click_on_letter.c
@@ -159,7 +159,7 @@ static void start_board (GcomprisBoard *agcomprisBoard)
gcomprisBoard->maxlevel=NUMBER_OF_LEVELS;
gcomprisBoard->sublevel=1;
gcomprisBoard->number_of_sublevel=NUMBER_OF_SUBLEVELS; /* Go to next level after this number of 'play' */
- gcompris_bar_set(GCOMPRIS_BAR_LEVEL|GCOMPRIS_BAR_REPEAT);
+ gcompris_bar_set(GCOMPRIS_BAR_CONFIG|GCOMPRIS_BAR_LEVEL|GCOMPRIS_BAR_REPEAT);
gcompris_score_start(SCORESTYLE_NOTE,
50,
50,
@@ -248,12 +248,6 @@ static gboolean sounds_are_fine ()
gchar *locale = NULL;
gboolean fine = TRUE;
- GHashTable *config = gcompris_get_board_conf();
-
- gcompris_change_locale(g_hash_table_lookup( config, "locale"));
-
- g_hash_table_destroy(config);
-
/* TRANSLATORS: Put here the alphabet in your language */
alphabet=_("abcdefghijklmnopqrstuvwxyz");
assert(g_utf8_validate(alphabet,-1,NULL)); // require by all utf8-functions
@@ -574,10 +568,41 @@ static GHFunc save_table (gpointer key,
static GcomprisConfCallback conf_ok(GHashTable *table)
{
+ if (!table){
+ if (gcomprisBoard)
+ pause_board(FALSE);
+ return;
+ }
+
+
g_hash_table_foreach(table, (GHFunc) save_table, NULL);
board_conf = NULL;
profile_conf = NULL;
+
+ if (gcomprisBoard){
+ GHashTable *config = gcompris_get_board_conf();
+
+ gcompris_reset_locale();
+ gcompris_change_locale(g_hash_table_lookup( config, "locale"));
+
+ gchar *up_init_str = g_hash_table_lookup( config, "uppercase_only");
+
+ if (up_init_str && (strcmp(up_init_str, "True")==0))
+ uppercase_only = TRUE;
+ else
+ uppercase_only = FALSE;
+
+ g_hash_table_destroy(config);
+
+ sounds_are_fine();
+
+ click_on_letter_next_level();
+
+ gamewon = FALSE;
+ pause_board(FALSE);
+
+ }
}
static void
@@ -587,9 +612,12 @@ config_start(GcomprisBoard *agcomprisBoard,
board_conf = agcomprisBoard;
profile_conf = aProfile;
+ if (gcomprisBoard)
+ pause_board(TRUE);
+
gcompris_configuration_window( g_strdup_printf("<b>%s</b> configuration\n for profile <b>%s</b>",
agcomprisBoard->name,
- aProfile->name),
+ aProfile ? aProfile->name : ""),
(GcomprisConfCallback )conf_ok);
/* init the combo to previously saved value */
@@ -599,6 +627,10 @@ config_start(GcomprisBoard *agcomprisBoard,
gcompris_combo_locales( locale);
+ //gcompris_separator();
+
+ //gcompris_combo_locales_asset( "Select sound locale", locale_sound, "gcompris colors", NULL, "audio/x-ogg", "purple.ogg");
+
gboolean up_init = FALSE;
gchar *up_init_str = g_hash_table_lookup( config, "uppercase_only");
@@ -606,8 +638,6 @@ config_start(GcomprisBoard *agcomprisBoard,
if (up_init_str && (strcmp(up_init_str, "True")==0))
up_init = TRUE;
- gcompris_separator();
-
gcompris_boolean_box(_("Uppercase only text"),
"uppercase_only",
up_init);
diff --git a/src/boards/colors.c b/src/boards/colors.c
index a5be90a..411d24f 100644
--- a/src/boards/colors.c
+++ b/src/boards/colors.c
@@ -122,10 +122,34 @@ static GHFunc save_table (gpointer key,
static GcomprisConfCallback conf_ok(GHashTable *table)
{
+ if (!table){
+ if (gcomprisBoard)
+ pause_board(FALSE);
+ return;
+ }
+
g_hash_table_foreach(table, (GHFunc) save_table, NULL);
board_conf = NULL;
profile_conf = NULL;
+
+
+ if (gcomprisBoard){
+ GHashTable *config = gcompris_get_board_conf();
+
+ if (locale_sound)
+ g_free(locale_sound);
+ locale_sound = g_strdup(g_hash_table_lookup( config, "locale_sound"));
+
+ g_hash_table_destroy(config);
+
+ colors_next_level();
+
+ pause_board(FALSE);
+
+ }
+
+
}
static gboolean check_text(gchar *key, gchar *text, GtkLabel *label){
@@ -142,6 +166,10 @@ colors_config_start(GcomprisBoard *agcomprisBoard,
profile_conf = aProfile;
gchar *label;
+
+
+ if (gcomprisBoard)
+ pause_board(TRUE);
label = g_strdup_printf("<b>%s</b> configuration\n for profile <b>%s</b>",
agcomprisBoard->name, aProfile->name);
@@ -153,9 +181,11 @@ colors_config_start(GcomprisBoard *agcomprisBoard,
/* init the combo to previously saved value */
GHashTable *config = gcompris_get_conf( profile_conf, board_conf);
- gchar *locale_sound = g_hash_table_lookup( config, "locale_sound");
+ gchar *saved_locale_sound = g_hash_table_lookup( config, "locale_sound");
- gcompris_combo_locales_asset( "Select sound locale", locale_sound, "gcompris colors", NULL, "audio/x-ogg", "purple.ogg");
+ gcompris_combo_locales_asset( "Select sound locale", saved_locale_sound, "gcompris colors", NULL, "audio/x-ogg", "purple.ogg");
+
+ g_hash_table_destroy(config);
}
@@ -195,7 +225,9 @@ static void start_board (GcomprisBoard *agcomprisBoard) {
GHashTable *config = gcompris_get_board_conf();
- locale_sound = g_hash_table_lookup( config, "locale_sound");
+ locale_sound = g_strdup(g_hash_table_lookup( config, "locale_sound"));
+
+ g_hash_table_destroy(config);
if(agcomprisBoard!=NULL) {
gcomprisBoard=agcomprisBoard;
@@ -204,9 +236,9 @@ static void start_board (GcomprisBoard *agcomprisBoard) {
gcomprisBoard->maxlevel=1;
if(properties->fx) {
- gcompris_bar_set(GCOMPRIS_BAR_REPEAT);
+ gcompris_bar_set(GCOMPRIS_BAR_CONFIG|GCOMPRIS_BAR_REPEAT);
} else {
- gcompris_bar_set(0);
+ gcompris_bar_set(GCOMPRIS_BAR_CONFIG);
}
gamewon = FALSE;
diff --git a/src/boards/gletters.c b/src/boards/gletters.c
index 7bc0941..bb03675 100644
--- a/src/boards/gletters.c
+++ b/src/boards/gletters.c
@@ -1,6 +1,6 @@
/* gcompris - gletters.c
*
- * Time-stamp: <2005/11/16 23:11:26 yves>
+ * Time-stamp: <2006/01/31 13:25:17 yves>
*
* Copyright (C) 2000 Bruno Coudoin
*
@@ -174,7 +174,7 @@ static void level_set_score() {
gcomprisBoard->width - 220,
gcomprisBoard->height - 50,
gcomprisBoard->number_of_sublevel);
- gcompris_bar_set(GCOMPRIS_BAR_LEVEL);
+ gcompris_bar_set(GCOMPRIS_BAR_CONFIG|GCOMPRIS_BAR_LEVEL);
}
static void pause_board (gboolean pause)
@@ -772,10 +772,41 @@ static GHFunc save_table (gpointer key,
static GcomprisConfCallback conf_ok(GHashTable *table)
{
+ if (!table){
+ if (gcomprisBoard)
+ pause_board(FALSE);
+ return;
+ }
+
g_hash_table_foreach(table, (GHFunc) save_table, NULL);
board_conf = NULL;
profile_conf = NULL;
+
+ if (gcomprisBoard){
+ gcompris_reset_locale();
+ GHashTable *config = gcompris_get_board_conf();
+
+ gcompris_change_locale(g_hash_table_lookup( config, "locale"));
+
+ gchar *up_init_str = g_hash_table_lookup( config, "uppercase_only");
+
+ if (up_init_str && (strcmp(up_init_str, "True")==0))
+ uppercase_only = TRUE;
+ else
+ uppercase_only = FALSE;
+
+ g_hash_table_destroy(config);
+
+ load_default_charset();
+
+ level_set_score();
+ gletters_next_level();
+
+ pause_board(FALSE);
+
+ }
+
}
static void
@@ -786,6 +817,9 @@ gletter_config_start(GcomprisBoard *agcomprisBoard,
profile_conf = aProfile;
gchar *label;
+
+ if (gcomprisBoard)
+ pause_board(TRUE);
label = g_strdup_printf("<b>%s</b> configuration\n for profile <b>%s</b>",
agcomprisBoard->name, aProfile->name);
diff --git a/src/boards/imageid.c b/src/boards/imageid.c
index d60bab7..01935f5 100644
--- a/src/boards/imageid.c
+++ b/src/boards/imageid.c
@@ -180,7 +180,7 @@ static void start_board (GcomprisBoard *agcomprisBoard)
50,
gcomprisBoard->height - 50,
gcomprisBoard->number_of_sublevel);
- gcompris_bar_set(GCOMPRIS_BAR_LEVEL);
+ gcompris_bar_set(GCOMPRIS_BAR_CONFIG|GCOMPRIS_BAR_LEVEL);
imageid_next_level();
@@ -709,10 +709,35 @@ static GHFunc save_table (gpointer key,
static GcomprisConfCallback conf_ok(GHashTable *table)
{
+ if (!table){
+ if (gcomprisBoard)
+ pause_board(FALSE);
+ return;
+ }
+
g_hash_table_foreach(table, (GHFunc) save_table, NULL);
board_conf = NULL;
profile_conf = NULL;
+
+ if (gcomprisBoard) {
+ gcompris_reset_locale();
+
+ GHashTable *config = gcompris_get_board_conf();
+
+ gcompris_change_locale(g_hash_table_lookup( config, "locale"));
+
+ g_hash_table_destroy(config);
+
+ destroy_board_list();
+
+ init_xml();
+
+ imageid_next_level();
+
+ pause_board(FALSE);
+ }
+
}
static void
@@ -722,9 +747,12 @@ config_start(GcomprisBoard *agcomprisBoard,
board_conf = agcomprisBoard;
profile_conf = aProfile;
+ if (gcomprisBoard)
+ pause_board(TRUE);
+
gcompris_configuration_window( g_strdup_printf("<b>%s</b> configuration\n for profile <b>%s</b>",
agcomprisBoard->name,
- aProfile->name),
+ aProfile ? aProfile->name : ""),
(GcomprisConfCallback )conf_ok);
/* init the combo to previously saved value */
diff --git a/src/boards/magic_hat.c b/src/boards/magic_hat.c
new file mode 100644
index 0000000..420cb06
--- /dev/null
+++ b/src/boards/magic_hat.c
@@ -0,0 +1,730 @@
+/* gcompris - magic_hat.c
+ *
+ * Copyright (C) 2006 Marc BRUN
+ *
+ * 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 WITHMINUS 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 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
+ */
+
+#include "gcompris/gcompris.h"
+#include <string.h>
+
+#define MH_FRAME1_X 420 // Coordonates for the first frame (first operand of the operation)
+#define MH_FRAME1_Y 60
+#define MH_FRAME2_X 420 // Coordonates for the second frame (second operand of the operation)
+#define MH_FRAME2_Y 200
+#define MH_FRAME_PLAYER_X 420 // Coordonates for the 'player' frame
+#define MH_FRAME_PLAYER_Y 380
+
+#define MH_HAT_X 190 // Coordonates for the hat
+#define MH_HAT_Y 90
+#define MH_HAT_HEIGHT 250
+#define MH_HAT_WIDTH 130
+#define POINT 0 // Which hat to draw ? The one with an interrogation point or
+#define STARS 1 // the one with stars ?
+
+#define NORMAL 0
+#define EMPTY 1
+#define UNDERHAT 2
+#define DYNAMIC 3
+
+#define MAX_ITEM 10 // Max number for an item in a list
+#define MAX_LIST 3 // Max number of list of items
+#define ITEM_SIZE 30 // Items are squares (or square-included)
+#define SPACE_BETWEEN_ITEMS 5
+
+#define MODE_MINUS 0
+#define MODE_PLUS 1
+#define DEFAULT_MODE MODE_MINUS
+
+// Types
+
+// This structure describes a frame (there are 3 of them on the board)
+typedef struct {
+ int id;
+ double coord_x;
+ double coord_y;
+ int nb_stars[MAX_LIST];
+ int array_star_type[MAX_LIST][MAX_ITEM];
+ GnomeCanvasItem *array_item[MAX_LIST][MAX_ITEM];
+} frame;
+
+// This structure decribes a movement
+typedef struct {
+ int i; // i index in array_item
+ int j; // j index in array_item
+ double dx;
+ double dy;
+ int nb; // how much of x/y movement (to give a smooth effect) ?
+ int frame; // number of the concerned frame (1 or 2)
+} move_object;
+
+// Global variables
+static GcomprisBoard *gcomprisBoard = NULL;
+static gboolean board_paused = TRUE;
+static GnomeCanvasGroup *boardRootItem = NULL;
+static gint timer_id = 0;
+static gint board_mode = DEFAULT_MODE;
+static gint hat_event_id; // value returned by gtk_signal_connect. Used by gtk_signal_disconnect
+
+static GnomeCanvasItem *hat;
+static frame frame1;
+static frame frame2;
+static frame frame_player;
+
+// gcompris functions
+static void start_board (GcomprisBoard *agcomprisBoard);
+static void pause_board (gboolean pause);
+static void end_board (void);
+static gboolean is_our_board (GcomprisBoard *gcomprisBoard);
+static void process_ok ();
+static void set_level (guint level);
+static int gamewon;
+static void game_won(void);
+
+static GnomeCanvasItem *magic_hat_create_item();
+static void magic_hat_destroy_all_items(void);
+static void magic_hat_next_level(void);
+
+// magic_hat functions
+static void draw_frame(frame *);
+static void draw_table(void);
+static void draw_hat(int);
+static void place_item(frame *, int);
+static gint hat_event(GnomeCanvasItem *, GdkEvent *, gpointer);
+static gint item_event(GnomeCanvasItem *, GdkEvent *, gpointer);
+static int nb_list();
+static gint smooth_move(move_object *);
+static gint move_stars(frame *);
+static gint close_hat();
+
+/* Description of this plugin */
+static BoardPlugin menu_bp =
+ {
+ NULL,
+ NULL,
+ "Give the result of an operation.",
+ "Click on the bottom left stars to give the result of the operation.",
+ "Marc BRUN",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ start_board,
+ pause_board,
+ end_board,
+ is_our_board,
+ NULL,
+ process_ok,
+ set_level,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ };
+
+/*
+ * Main entry point mandatory for each Gcompris's game
+ * ---------------------------------------------------
+ *
+ */
+
+GET_BPLUGIN_INFO(magic_hat)
+
+static void pause_board (gboolean pause)
+{
+ if (gcomprisBoard == NULL)
+ return;
+
+ if (timer_id) {
+ gtk_timeout_remove (timer_id);
+ timer_id = 0;
+ }
+
+ /* the game is won */
+ if (gamewon == TRUE && pause == FALSE)
+ game_won();
+
+ board_paused = pause;
+}
+
+static void start_board (GcomprisBoard *agcomprisBoard)
+{
+
+ if (agcomprisBoard != NULL) {
+ gcomprisBoard = agcomprisBoard;
+ gcomprisBoard->level = 1;
+ gcomprisBoard->maxlevel = 9;
+ gcomprisBoard->sublevel = 1;
+ gcomprisBoard->number_of_sublevel = 1; // Go to next level after this number of 'play'
+ gcompris_bar_set(GCOMPRIS_BAR_LEVEL|GCOMPRIS_BAR_OK);
+
+ if (strcmp(gcomprisBoard->mode, "minus") == 0)
+ board_mode = MODE_MINUS;
+ else if (strcmp(gcomprisBoard->mode, "plus") == 0)
+ board_mode = MODE_PLUS;
+ else
+ board_mode = DEFAULT_MODE;
+
+ gcompris_set_background(gnome_canvas_root(gcomprisBoard->canvas), gcompris_image_to_skin("gcompris-bg.jpg"));
+
+ magic_hat_next_level();
+
+ gamewon = FALSE;
+ pause_board(FALSE);
+ }
+}
+
+static void end_board () {
+
+ if (timer_id) {
+ gtk_timeout_remove (timer_id);
+ timer_id = 0;
+ }
+
+ if (gcomprisBoard != NULL) {
+ pause_board(TRUE);
+ magic_hat_destroy_all_items();
+ }
+
+ gcomprisBoard = NULL;
+}
+
+// Check if player has won
+static void process_ok() {
+
+ int i;
+ int ok = TRUE;
+
+ if (board_mode == MODE_MINUS) {
+ for (i = 0 ; i < nb_list() ; i++) {
+ if (frame1.nb_stars[i] != (frame2.nb_stars[i] + frame_player.nb_stars[i]))
+ ok = FALSE;
+ }
+ } else {
+ for (i = 0 ; i < nb_list() ; i++) {
+ if (frame_player.nb_stars[i] != (frame1.nb_stars[i] + frame2.nb_stars[i]))
+ ok = FALSE;
+ }
+ }
+
+ if (ok) {
+ gamewon = TRUE;
+ gcompris_play_ogg ("bonus", NULL);
+ }
+
+ gcompris_display_bonus(gamewon, BONUS_FLOWER);
+
+}
+
+/* ======================================= */
+static void set_level (guint level) {
+
+ if (gcomprisBoard != NULL) {
+
+ gcomprisBoard->level = level;
+ gcomprisBoard->sublevel = 1;
+ magic_hat_next_level();
+ }
+}
+/* ======================================= */
+static gboolean is_our_board (GcomprisBoard *gcomprisBoard) {
+
+ if (gcomprisBoard) {
+
+ if (g_strcasecmp(gcomprisBoard->type, "magic_hat") == 0) {
+
+ /* Set the plugin entry */
+ gcomprisBoard->plugin = &menu_bp;
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+/*-------------------------------------------------------------------------------*/
+/*-------------------------------------------------------------------------------*/
+/* set initial values for the next level */
+static void magic_hat_next_level() {
+
+ gcompris_bar_set_level(gcomprisBoard);
+
+ magic_hat_destroy_all_items();
+ gamewon = FALSE;
+
+ /* Try the next level */
+ magic_hat_create_item();
+}
+
+/* ==================================== */
+/* Destroy all the items */
+static void magic_hat_destroy_all_items()
+{
+ if (timer_id) {
+ gtk_timeout_remove (timer_id);
+ timer_id = 0;
+ }
+
+ if(boardRootItem != NULL)
+ gtk_object_destroy (GTK_OBJECT(boardRootItem));
+
+ boardRootItem = NULL;
+}
+
+/* ==================================== */
+static GnomeCanvasItem *magic_hat_create_item()
+{
+ int i, j;
+ GdkPixbuf *pixmap;
+ int step;
+
+ boardRootItem = GNOME_CANVAS_GROUP(gnome_canvas_item_new (gnome_canvas_root(gcomprisBoard->canvas),
+ gnome_canvas_group_get_type (),
+ "x", (double) 0,
+ "y", (double) 0,
+ NULL));
+
+ if (board_mode == MODE_MINUS)
+ pixmap = gcompris_load_pixmap("magic_hat/magic_hat_minus_bg.png");
+ else
+ pixmap = gcompris_load_pixmap("magic_hat/magic_hat_plus_bg.png");
+
+ gnome_canvas_item_new (boardRootItem,
+ gnome_canvas_pixbuf_get_type(),
+ "pixbuf", pixmap,
+ "x", 0.0,
+ "y", 0.0,
+ "anchor", GTK_ANCHOR_NW,
+ NULL);
+ gdk_pixbuf_unref(pixmap);
+
+ // Initialisation for frame1
+ frame1.id = 1;
+ frame1.coord_x = MH_FRAME1_X;
+ frame1.coord_y = MH_FRAME1_Y;
+
+ // Initialisation for frame1
+ frame2.id = 2;
+ frame2.coord_x = MH_FRAME2_X;
+ frame2.coord_y = MH_FRAME2_Y;
+
+ // Initialisation for frame1
+ frame_player.id = 3;
+ frame_player.coord_x = MH_FRAME_PLAYER_X;
+ frame_player.coord_y = MH_FRAME_PLAYER_Y;
+
+ // The three frames of this activity : one for the sentence of the magician (top left), one for
+ // the items out of the hat (top right), one for the answer of the payer (bottom right)
+ draw_frame(&frame1);
+ draw_frame(&frame2);
+ draw_frame(&frame_player);
+
+ // Description of the 9 levels for substraction
+ // Level 1 : one list (yellow stars), from 2 to 4 stars in frame 1
+ // Level 2 : one list (yellow stars), from 2 to 7 stars in frame 1
+ // Level 3 : one list (yellow stars), from 2 to 10 stars in frame 1
+ // Level 4 : two lists (yellow and green stars), from 2 to 4 stars in frame 1
+ // Level 5 : two lists (yellow and green stars), from 2 to 7 stars in frame 1
+ // Level 6 : two lists (yellow and green stars), from 2 to 10 stars in frame 1
+ // Level 7 : three lists (yellow, green and blue stars), from 2 to 4 stars in frame 1
+ // Level 8 : three lists (yellow, green and blue stars), from 2 to 7 stars in frame 1
+ // Level 9 : three lists (yellow, green and blue stars), from 2 to 10 stars in frame 1
+ //
+ // Description of the 9 levels for addition
+ // Level 1 : one list (yellow stars), from 2 to 4 for the total
+ // Level 2 : one list (yellow stars), from 2 to 7 for the total
+ // Level 3 : one list (yellow stars), from 2 to 10 for the total
+ // Level 4 : two lists (yellow and green stars), from 2 to 4 for the total
+ // Level 5 : two lists (yellow and green stars), from 2 to 7 for the total
+ // Level 6 : two lists (yellow and green stars), from 2 to 10 for the total
+ // Level 7 : three lists (yellow, green and blue stars), from 2 to 4 for the total
+ // Level 8 : three lists (yellow, green and blue stars), from 2 to 7 for the total
+ // Level 9 : three lists (yellow, green and blue stars), from 2 to 10 for the total
+
+ step = 3;
+
+ for (i = 0 ; i < nb_list() ; i++) {
+
+ // Frame 1
+ if (board_mode == MODE_MINUS)
+ frame1.nb_stars[i] = RAND(2, (1 + (step * nb_list()))); // Minimum 2 to avoid '0' value (which is not easy to understand for kids)
+ else
+ frame1.nb_stars[i] = RAND(1, (step * nb_list()));
+
+ for (j = 0 ; j < frame1.nb_stars[i] ; j++) frame1.array_star_type[i][j] = i;
+ for ( ; j < MAX_ITEM ; j++) frame1.array_star_type[i][j] = -1;
+ for (j = 0 ; j < MAX_ITEM ; j++) frame1.array_item[i][j] = gnome_canvas_item_new (boardRootItem, gnome_canvas_pixbuf_get_type(), NULL);
+
+ // Frame 2
+ if (board_mode == MODE_MINUS)
+ frame2.nb_stars[i] = RAND(1, (frame1.nb_stars[i]) - 1); // Minimum 1 to avoid '0'
+ else
+ frame2.nb_stars[i] = RAND(1, ((step * nb_list()) - frame1.nb_stars[i] + 1));
+
+ for (j = 0 ; j < frame2.nb_stars[i] ; j++) frame2.array_star_type[i][j] = i;
+ for ( ; j < MAX_ITEM ; j++) frame2.array_star_type[i][j] = -1;
+ for (j = 0 ; j < MAX_ITEM ; j++) frame2.array_item[i][j] = gnome_canvas_item_new (boardRootItem, gnome_canvas_pixbuf_get_type(), NULL);
+
+ // Player frame
+ frame_player.nb_stars[i] = 0;
+ for (j = 0 ; j < MAX_ITEM ; j++) frame_player.array_star_type[i][j] = -1;
+ }
+
+ if (board_mode == MODE_MINUS) {
+ place_item(&frame1, NORMAL); // design the 'total' stars, with all the items
+ place_item(&frame2, UNDERHAT); // design 'out' stars, all the items are hidden under the hat
+ } else {
+ place_item(&frame1, NORMAL); // design the first frame stars, with all the items
+ place_item(&frame2, NORMAL); // design the second frame stars, with all the items
+ }
+
+ // The magic hat !! And its table
+ // The hat is designed after the 'minus' items so that it hides them
+ draw_hat(STARS);
+ draw_table();
+
+ return NULL;
+}
+
+// Display a 'end of game' animation
+static void finished() {
+
+ board_finished(BOARD_FINISHED_RANDOM);
+ timer_id = 0;
+}
+
+// One more level completed
+static void game_won() {
+
+ gcomprisBoard->sublevel++;
+
+ if (gcomprisBoard->sublevel>gcomprisBoard->number_of_sublevel) {
+ /* Try the next level */
+ gcomprisBoard->sublevel = 1;
+ gcomprisBoard->level++;
+
+ if (gcomprisBoard->level>gcomprisBoard->maxlevel) { // all levels completed : the current board is finished
+ timer_id = g_timeout_add (2000, (GtkFunction) finished, NULL);
+ return;
+ }
+ }
+ magic_hat_next_level();
+}
+
+// Draw a frame with empty small squares
+static void draw_frame(frame *my_frame) {
+
+ GnomeCanvasItem *item_frame = NULL;
+ int i, j;
+ double x = my_frame->coord_x;
+ double y = my_frame->coord_y;
+ GnomeCanvasPoints *track;
+
+ track = gnome_canvas_points_new(5);
+
+ for (i = 0 ; i < nb_list() ; i++) {
+
+ for (j = 0 ; j < MAX_ITEM ; j++) {
+
+ track->coords[0] = x + (j * (ITEM_SIZE + SPACE_BETWEEN_ITEMS));
+ track->coords[1] = y + (i * (ITEM_SIZE + SPACE_BETWEEN_ITEMS));
+ track->coords[2] = x + (j * (ITEM_SIZE + SPACE_BETWEEN_ITEMS)) + ITEM_SIZE;
+ track->coords[3] = y + (i * (ITEM_SIZE + SPACE_BETWEEN_ITEMS));
+ track->coords[4] = x + (j * (ITEM_SIZE + SPACE_BETWEEN_ITEMS)) + ITEM_SIZE;
+ track->coords[5] = y + (i * (ITEM_SIZE + SPACE_BETWEEN_ITEMS)) + ITEM_SIZE;
+ track->coords[6] = x + (j * (ITEM_SIZE + SPACE_BETWEEN_ITEMS));
+ track->coords[7] = y + (i * (ITEM_SIZE + SPACE_BETWEEN_ITEMS)) + ITEM_SIZE;
+ track->coords[8] = x + (j * (ITEM_SIZE + SPACE_BETWEEN_ITEMS));
+ track->coords[9] = y + (i * (ITEM_SIZE + SPACE_BETWEEN_ITEMS));
+
+ item_frame = gnome_canvas_item_new (boardRootItem,
+ gnome_canvas_line_get_type (),
+ "points", track,
+ "width_pixels", 1,
+ "fill_color", "#948d85",
+ NULL);
+ }
+ }
+
+ place_item(my_frame, EMPTY);
+
+}
+
+// Draw the table (line)
+static void draw_table() {
+
+ GnomeCanvasItem *item_frame = NULL;
+ GnomeCanvasPoints *track;
+
+ track = gnome_canvas_points_new(2);
+
+ track->coords[0] = MH_HAT_X;
+ track->coords[1] = MH_HAT_Y + MH_HAT_HEIGHT + 5;
+ track->coords[2] = MH_HAT_X + MH_HAT_WIDTH;
+ track->coords[3] = MH_HAT_Y + MH_HAT_HEIGHT + 5;
+
+ item_frame = gnome_canvas_item_new (boardRootItem,
+ gnome_canvas_line_get_type (),
+ "points", track,
+ "width_pixels", 1,
+ "fill_color", "black",
+ NULL);
+}
+
+// Draw the hat
+static void draw_hat(int type) {
+
+ GdkPixbuf *image;
+
+ if (type == STARS)
+ image = gcompris_load_pixmap("magic_hat/hat.png");
+ else
+ image = gcompris_load_pixmap("magic_hat/hat-point.png");
+
+ hat = gnome_canvas_item_new (boardRootItem,
+ gnome_canvas_pixbuf_get_type(),
+ "pixbuf", image,
+ "x", (double) MH_HAT_X,
+ "y", (double) MH_HAT_Y,
+ "width", (double) MH_HAT_WIDTH,
+ "height", (double) MH_HAT_HEIGHT,
+ "width_set", TRUE,
+ "height_set", TRUE,
+ "anchor", GTK_ANCHOR_NW,
+ NULL);
+
+ if (type == STARS) {
+ hat_event_id = gtk_signal_connect(GTK_OBJECT(hat), "event", (GtkSignalFunc) hat_event, NULL);
+ gtk_signal_connect(GTK_OBJECT(hat), "event", (GtkSignalFunc) gcompris_item_event_focus, NULL);
+ }
+}
+
+// Place items on the board
+// frame * my_frame : which frame to create the items on ?
+// int type : four possible values
+// EMPTY => only grey stars, which symbolise an empty item
+// NORMAL => a coloured star
+// UNDERHAT => objects are not visible, they are localised under the hat
+// DYNAMIC => the items are made clicable (for the player frame)
+static void place_item(frame * my_frame, int type) {
+
+ GnomeCanvasItem *item = NULL;
+ int i, j;
+ int k, nb_item;
+ GdkPixbuf *image;
+ double item_x, item_y;
+ double x, y;
+
+ char *image_name[MAX_LIST] = {"magic_hat/star1.png",
+ "magic_hat/star2.png",
+ "magic_hat/star3.png"};
+
+ x = my_frame->coord_x;
+ y = my_frame->coord_y;
+
+ for (i = 0 ; i < nb_list() ; i++) {
+
+ for (j = 0 ; j < MAX_ITEM ; j++) {
+
+ if ((j < my_frame->nb_stars[i]) && (type != EMPTY))
+ image = gcompris_load_pixmap(image_name[i]);
+ else
+ image = gcompris_load_pixmap("magic_hat/star-clear.png");
+
+ if (type == UNDERHAT) {
+ item_x = (MH_HAT_X + ((MH_HAT_WIDTH - ITEM_SIZE) / 2));
+ item_y = (MH_HAT_Y + MH_HAT_HEIGHT - 2 * ITEM_SIZE);
+ } else {
+ item_x = x + (j * (ITEM_SIZE + SPACE_BETWEEN_ITEMS));
+ item_y = y + (i * (ITEM_SIZE + SPACE_BETWEEN_ITEMS));
+ }
+
+ // If NORMAL, we have to create two items : the first one stays on the frame, the
+ // other one moves to the hat
+ if (type == NORMAL)
+ nb_item = 2;
+ else
+ nb_item = 1;
+
+ for (k = 0 ; k < nb_item ; k++) {
+ item = gnome_canvas_item_new (boardRootItem,
+ gnome_canvas_pixbuf_get_type(),
+ "pixbuf", image,
+ "x", item_x,
+ "y", item_y,
+ "width", (double) (ITEM_SIZE - 2),
+ "height", (double) (ITEM_SIZE - 2),
+ "width_set", TRUE,
+ "height_set", TRUE,
+ "anchor", GTK_ANCHOR_NW,
+ NULL);
+ }
+
+ gdk_pixbuf_unref(image);
+
+ if (type == DYNAMIC)
+ gtk_signal_connect(GTK_OBJECT(item), "event", (GtkSignalFunc) item_event, GINT_TO_POINTER(MAX_ITEM * i + j));
+
+ if (type == UNDERHAT || type == NORMAL)
+ my_frame->array_item[i][j] = item;
+ }
+ }
+}
+
+// When clicked, an star from the player frame changes its appearance (grey or coloured) and the counter is re-evaluated
+static gint item_event(GnomeCanvasItem *item, GdkEvent *event, gpointer data) {
+
+ int index = GPOINTER_TO_INT(data);
+ GdkPixbuf *pixmap[MAX_LIST];
+
+ if (board_paused)
+ return FALSE;
+
+ if (event->type == GDK_MOTION_NOTIFY) // Mouse moved
+ return FALSE;
+
+ if ((event->type == GDK_BUTTON_PRESS) && (event->button.button == 1)) {
+
+ if (frame_player.array_star_type[index / MAX_ITEM][index % MAX_ITEM] >= 0) {
+
+ // Desactivate the star
+ frame_player.nb_stars[index / MAX_ITEM]--;
+ frame_player.array_star_type[index / MAX_ITEM][index % MAX_ITEM] = -1;
+
+ pixmap[0] = gcompris_load_pixmap("magic_hat/star-clear.png");
+
+ gnome_canvas_item_set(item, "pixbuf", pixmap[0], NULL);
+ } else {
+
+ // Activate the star
+ frame_player.nb_stars[index / MAX_ITEM]++;
+ frame_player.array_star_type[index / MAX_ITEM][index % MAX_ITEM] = index / MAX_ITEM;
+
+ pixmap[0] = gcompris_load_pixmap("magic_hat/star1.png");
+ pixmap[1] = gcompris_load_pixmap("magic_hat/star2.png");
+ pixmap[2] = gcompris_load_pixmap("magic_hat/star3.png");
+
+ gnome_canvas_item_set(item, "pixbuf", pixmap[index / MAX_ITEM], NULL);
+ }
+ gcompris_play_ogg ("gobble", NULL);
+ }
+
+ return FALSE;
+}
+
+// When clicked, the hat rotates and a few items can go out of or into it
+// Then the hat go back in its previous position, and the game can start
+static gint hat_event(GnomeCanvasItem *item, GdkEvent *event, gpointer data) {
+
+ if (board_paused)
+ return FALSE;
+
+ if (event->type == GDK_MOTION_NOTIFY) // Mouse moved
+ return FALSE;
+
+ if ((event->type == GDK_BUTTON_PRESS) && (event->button.button == 1)) {
+
+ // disconnect hat and hat_event, so that hat can not be clicked any more
+ gtk_signal_disconnect(GTK_OBJECT(hat), hat_event_id);
+
+ // 'open' the hat
+ item_rotate_with_center(hat, -20.0, 0, MH_HAT_HEIGHT);
+
+ // Make the items move from/out the hat, depending on the mode
+ // Wait a few seconds between the two frames
+ move_stars(&frame1);
+ timer_id = g_timeout_add(1200, (GtkFunction) move_stars, &frame2);
+
+ // Wait again a few seconds before closing the hat. Then the game is ready to start
+ timer_id = g_timeout_add(2600, (GtkFunction) close_hat, NULL);
+ }
+
+ return FALSE;
+}
+
+// Return nb_list to be displayed, depending of the game level :
+// levels 1, 2 and 3 : one list
+// levels 4, 5 and 6 : two lists
+// levels 7, 8 and 9 : three lists
+static int nb_list() {
+
+ return (1 + (gcomprisBoard->level - 1) / MAX_LIST) ;
+
+}
+
+// Move all the stars of one frame to or from the hat
+static gint move_stars(frame *my_frame) {
+
+ int i, j;
+ move_object *my_move = NULL;
+
+ for (i = 0 ; i < nb_list() ; i++) {
+ for (j = 0 ; j < my_frame->nb_stars[i] ; j++) {
+ if ((my_move = g_malloc(sizeof(move_object))) == NULL) { // Freed in function smooth_move
+ g_error ("Malloc error in hat_event");
+ }
+
+ my_move->i = i;
+ my_move->j = j;
+ my_move->nb = 20;
+ my_move->dx = - ((my_frame->coord_x + (my_move->j * (ITEM_SIZE + SPACE_BETWEEN_ITEMS)) -
+ (MH_HAT_X + ((MH_HAT_WIDTH - ITEM_SIZE) / 2))) / my_move->nb);
+ my_move->dy = - ((my_frame->coord_y + (my_move->i * (ITEM_SIZE + SPACE_BETWEEN_ITEMS)) -
+ (MH_HAT_Y + MH_HAT_HEIGHT - 2 * ITEM_SIZE)) / my_move->nb);
+
+ if (board_mode == MODE_MINUS && my_frame->id == 2) {
+ my_move->dx = -my_move->dx;
+ my_move->dy = -my_move->dy;
+ }
+
+ my_move->frame = my_frame->id;
+ timer_id = g_timeout_add(50, (GtkFunction) smooth_move, my_move);
+ }
+ }
+ return FALSE;
+}
+
+// Close the hat, then the game can start
+static gint close_hat() {
+
+ // erase the hat with stars
+ gtk_object_destroy(GTK_OBJECT(hat));
+
+ // draw a hat with an interrogation point
+ draw_hat(POINT);
+
+ // draw an empty dynamic frame, each item is activable by left click
+ // before this, the player_frame is not clicable
+ place_item(&frame_player, DYNAMIC);
+
+ return FALSE;
+}
+
+// Move a star smoothly from under the hat to its final location, on the minus frame
+static gint smooth_move(move_object *my_move) {
+
+ if (!my_move->nb--) {
+ g_free(my_move);
+ return FALSE;
+ }
+
+ if (my_move->frame == 1)
+ gnome_canvas_item_move(frame1.array_item[my_move->i][my_move->j], my_move->dx, my_move->dy);
+ else
+ gnome_canvas_item_move(frame2.array_item[my_move->i][my_move->j], my_move->dx, my_move->dy);
+
+ return TRUE;
+
+}
diff --git a/src/boards/memory.c b/src/boards/memory.c
index 27917ee..8b63ef2 100644
--- a/src/boards/memory.c
+++ b/src/boards/memory.c
@@ -1,6 +1,6 @@
/* gcompris - memory.c
*
- * Time-stamp: <2005/11/21 15:57:51 yves>
+ * Time-stamp: <2006/02/09 07:58:04 yves>
*
* Copyright (C) 2000 Bruno Coudoin
*
@@ -34,6 +34,20 @@
//#define TEXT_FONT gcompris_skin_font_board_huge_bold
#define TEXT_FONT "Serif bold 28"
+static gchar *op_fonts[10] =
+ {
+ "",
+ "Serif bold 28",
+ "Serif bold 24",
+ "Serif bold 20",
+ "Serif bold 20",
+ "Serif bold 17",
+ "Serif bold 13",
+ "Serif bold 13",
+ "Serif bold 13",
+ "Serif bold 11",
+ };
+
static GcomprisBoard *gcomprisBoard = NULL;
static GnomeCanvasGroup *boardRootItem = NULL;
@@ -50,9 +64,23 @@ static Mode currentMode = MODE_NORMAL;
typedef enum
{
UIMODE_NORMAL = 0,
- UIMODE_SOUND = 1,
+ UIMODE_SOUND = 1,
} UiMode;
-static Mode currentUiMode = MODE_NORMAL;
+static UiMode currentUiMode = UIMODE_NORMAL;
+
+typedef enum
+{
+ BOARDMODE_NORMAL = 0,
+ BOARDMODE_SOUND = 1,
+ BOARDMODE_ADD = 2,
+ BOARDMODE_MINUS = 3,
+ BOARDMODE_MULT = 4,
+ BOARDMODE_DIV = 5,
+ BOARDMODE_ADD_MINUS = 6,
+ BOARDMODE_MULT_DIV = 7,
+ BOARDMODE_ADD_MINUS_MULT_DIV = 8,
+} BoardMode;
+static BoardMode currentBoardMode = BOARDMODE_NORMAL;
typedef enum
{
@@ -74,6 +102,7 @@ typedef struct {
GnomeCanvasItem *framecardItem;
GnomeCanvasItem *frontcardItem;
gboolean hidden;
+ gchar *second_value;
} MemoryItem;
static MemoryItem *firstCard = NULL;
@@ -242,6 +271,9 @@ static gchar *soundList[] =
#define NUMBER_OF_SOUNDS G_N_ELEMENTS(soundList)
+
+
+
/* Description of this plugin */
static BoardPlugin menu_bp =
{
@@ -296,6 +328,74 @@ static GList *winning_pairs = NULL;
static gint tux_id = 0;
/*
+ *
+ * Operation versions
+ *
+ */
+
+
+/* max number 1 / max number 2 */
+/* to allow level with calculus like 7*12 */
+
+static guint add_levelDescription[10][2] =
+{
+ {0,0},
+ {5,5},
+ {5,7},
+ {7,7},
+ {7,10},
+ {10,10},
+ {10,15},
+ {15,15},
+ {25,25},
+ {50,50},
+};
+
+static guint minus_levelDescription[10][2] =
+{
+ {0,0},
+ {5,5},
+ {5,7},
+ {7,7},
+ {7,10},
+ {10,10},
+ {10,15},
+ {15,15},
+ {25,25},
+ {50,50},
+};
+
+
+static guint mult_levelDescription[10][2] =
+{
+ {0,0},
+ {5,5},
+ {5,7},
+ {7,7},
+ {7,10},
+ {10,10},
+ {12,12},
+ {15,15},
+ {20,20},
+ {25,25},
+};
+
+static guint div_levelDescription[10][2] =
+{
+ {0,0},
+ {5,5},
+ {5,7},
+ {7,7},
+ {7,10},
+ {10,10},
+ {12,12},
+ {15,15},
+ {20,20},
+ {25,25},
+};
+
+
+/*
* random without repeted token
* ------------------------
*
@@ -306,6 +406,10 @@ static gint tux_id = 0;
#define TYPE_UPPERCASE 4
#define TYPE_LOWERCASE 8
#define TYPE_SOUND 16
+#define TYPE_ADD 32
+#define TYPE_MINUS 64
+#define TYPE_MULT 128
+#define TYPE_DIV 256
static GList *passed_token = NULL;
@@ -316,9 +420,11 @@ static GnomeCanvasItem *tux_score_s;
static GnomeCanvasItem *player_score_s;
/* set the type of the token returned in string in returned_type */
-void get_random_token(int token_type, gint *returned_type, gchar **string)
+void get_random_token(int token_type, gint *returned_type, gchar **string, gchar **second_value)
{
gchar *result = NULL;
+ gchar *second = NULL;
+ gboolean skip;
gint max_token;
gint j, i, k;
@@ -376,6 +482,40 @@ void get_random_token(int token_type, gint *returned_type, gchar **string)
data = g_list_append(data, dat);
}
+ if (token_type & TYPE_ADD){
+ max_token += (add_levelDescription[gcomprisBoard->level][0]+1)*(add_levelDescription[gcomprisBoard->level][1]+1);
+ DATUM *dat = g_malloc0(sizeof(DATUM));
+ dat->bound = max_token;
+ dat->type = TYPE_ADD;
+ data = g_list_append(data, dat);
+ }
+
+ if (token_type & TYPE_MINUS){
+ max_token += (minus_levelDescription[gcomprisBoard->level][0]+1)*(minus_levelDescription[gcomprisBoard->level][1]+1);
+ DATUM *dat = g_malloc0(sizeof(DATUM));
+ dat->bound = max_token;
+ dat->type = TYPE_MINUS;
+ data = g_list_append(data, dat);
+ }
+
+ if (token_type & TYPE_MULT){
+ max_token += (mult_levelDescription[gcomprisBoard->level][0]+1)*(mult_levelDescription[gcomprisBoard->level][1]+1);
+ DATUM *dat = g_malloc0(sizeof(DATUM));
+ dat->bound = max_token;
+ dat->type = TYPE_MULT;
+ data = g_list_append(data, dat);
+ }
+
+ if (token_type & TYPE_DIV){
+ max_token += (div_levelDescription[gcomprisBoard->level][0]+1)*(div_levelDescription[gcomprisBoard->level][1]+1);
+ DATUM *dat = g_malloc0(sizeof(DATUM));
+ dat->bound = max_token;
+ dat->type = TYPE_DIV;
+ data = g_list_append(data, dat);
+ }
+
+
+
g_assert(max_token >0);
i = rand()%max_token;
@@ -387,7 +527,10 @@ void get_random_token(int token_type, gint *returned_type, gchar **string)
j=-1;
do {
+ skip = FALSE;
g_free(result);
+ result = NULL;
+ g_free(second);
j++;
if ((i+j) == max_token) {
@@ -420,16 +563,53 @@ void get_random_token(int token_type, gint *returned_type, gchar **string)
g_utf8_strncpy(result, g_utf8_offset_to_pointer (alphabet_lowercase,k),1);
break;
case TYPE_SOUND:
- result= g_strdup(soundList[k]);
+ result = g_strdup(soundList[k]);
break;
+ case TYPE_ADD:
+ {
+ int i, j;
+ i = k % add_levelDescription[gcomprisBoard->level][0];
+ j = k / add_levelDescription[gcomprisBoard->level][0];
+ result = g_strdup_printf("%d+%d",i,j);
+ second = g_strdup_printf("%d",i+j);;
+ break;
+ }
+ case TYPE_MINUS:
+ {
+ int i, j;
+ i = k % minus_levelDescription[gcomprisBoard->level][0];
+ j = k / minus_levelDescription[gcomprisBoard->level][0];
+ result = g_strdup_printf("%d-%d",i+j,i);
+ second = g_strdup_printf("%d",j);;
+ break;
+ }
+ case TYPE_MULT:
+ {
+ int i, j;
+ i = k % mult_levelDescription[gcomprisBoard->level][0];
+ j = k / mult_levelDescription[gcomprisBoard->level][0];
+ result = g_strdup_printf("%dx%d",i,j);
+ second = g_strdup_printf("%d",i*j);;
+ break;
+ }
+ case TYPE_DIV:
+ {
+ int i1, i2;
+ i1 = k % div_levelDescription[gcomprisBoard->level][0];
+ if (i1==0) skip=TRUE;
+ i2 = k / div_levelDescription[gcomprisBoard->level][0];
+ result = g_strdup_printf("%d÷%d",i1*i2,i1);
+ second = g_strdup_printf("%d",i2);
+ break;
+ }
default:
/* should never append */
g_error("never !");
break;
}
- } while ((j < max_token )
- && (passed_token && result && g_list_find_custom(passed_token, result, (GCompareFunc)strcmp)));
+ } while (skip || ((j < max_token )
+ && (passed_token && result && g_list_find_custom(passed_token, result, (GCompareFunc)strcmp))));
g_assert (j < max_token);
@@ -439,6 +619,9 @@ void get_random_token(int token_type, gint *returned_type, gchar **string)
*string = result;
+ if (second_value)
+ *second_value = second;
+
for (list = data; list != NULL; list=list->next)
g_free(list->data);
@@ -512,29 +695,115 @@ static void start_board (GcomprisBoard *agcomprisBoard)
if(!gcomprisBoard->mode){
currentMode=MODE_NORMAL;
currentUiMode=UIMODE_NORMAL;
- }
- else {
+ currentBoardMode=BOARDMODE_NORMAL;
+ } else {
if(g_strcasecmp(gcomprisBoard->mode, "tux")==0){
currentMode=MODE_TUX;
currentUiMode=UIMODE_NORMAL;
- }
- else {
+ currentBoardMode=BOARDMODE_NORMAL;
+ } else {
if(g_strcasecmp(gcomprisBoard->mode, "sound")==0){
currentMode=MODE_NORMAL;
currentUiMode=UIMODE_SOUND;
+ currentBoardMode=BOARDMODE_SOUND;
} else {
if(g_strcasecmp(gcomprisBoard->mode, "sound_tux")==0){
currentMode=MODE_TUX;
currentUiMode=UIMODE_SOUND;
- }
- else{
- currentMode=MODE_NORMAL;
- currentUiMode=UIMODE_NORMAL;
- g_warning("Fallback mode set to images");
+ currentBoardMode=BOARDMODE_SOUND;
+ } else {
+ if(g_strcasecmp(gcomprisBoard->mode, "add")==0){
+ currentMode=MODE_NORMAL;
+ currentUiMode=UIMODE_NORMAL;
+ currentBoardMode=BOARDMODE_ADD;
+ } else {
+ if(g_strcasecmp(gcomprisBoard->mode, "add_tux")==0){
+ currentMode=MODE_TUX;
+ currentUiMode=UIMODE_NORMAL;
+ currentBoardMode=BOARDMODE_ADD;
+ } else {
+ if(g_strcasecmp(gcomprisBoard->mode, "minus")==0){
+ currentMode=MODE_NORMAL;
+ currentUiMode=UIMODE_NORMAL;
+ currentBoardMode=BOARDMODE_MINUS;
+ } else {
+ if(g_strcasecmp(gcomprisBoard->mode, "minus_tux")==0){
+ currentMode=MODE_TUX;
+ currentUiMode=UIMODE_NORMAL;
+ currentBoardMode=BOARDMODE_MINUS;
+ } else {
+ if(g_strcasecmp(gcomprisBoard->mode, "mult")==0){
+ currentMode=MODE_NORMAL;
+ currentUiMode=UIMODE_NORMAL;
+ currentBoardMode=BOARDMODE_MULT;
+ } else {
+ if(g_strcasecmp(gcomprisBoard->mode, "mult_tux")==0){
+ currentMode=MODE_TUX;
+ currentUiMode=UIMODE_NORMAL;
+ currentBoardMode=BOARDMODE_MULT;
+ } else {
+ if(g_strcasecmp(gcomprisBoard->mode, "div")==0){
+ currentMode=MODE_NORMAL;
+ currentUiMode=UIMODE_NORMAL;
+ currentBoardMode=BOARDMODE_DIV;
+ } else {
+ if(g_strcasecmp(gcomprisBoard->mode, "div_tux")==0){
+ currentMode=MODE_TUX;
+ currentUiMode=UIMODE_NORMAL;
+ currentBoardMode=BOARDMODE_DIV;
+ } else {
+ if(g_strcasecmp(gcomprisBoard->mode, "add_minus")==0){
+ currentMode=MODE_NORMAL;
+ currentUiMode=UIMODE_NORMAL;
+ currentBoardMode=BOARDMODE_ADD_MINUS;
+ } else {
+ if(g_strcasecmp(gcomprisBoard->mode, "add_minus_tux")==0){
+ currentMode=MODE_TUX;
+ currentUiMode=UIMODE_NORMAL;
+ currentBoardMode=BOARDMODE_ADD_MINUS;
+ } else {
+ if(g_strcasecmp(gcomprisBoard->mode, "mult_div")==0){
+ currentMode=MODE_NORMAL;
+ currentUiMode=UIMODE_NORMAL;
+ currentBoardMode=BOARDMODE_MULT_DIV;
+ } else {
+ if(g_strcasecmp(gcomprisBoard->mode, "mult_div_tux")==0){
+ currentMode=MODE_TUX;
+ currentUiMode=UIMODE_NORMAL;
+ currentBoardMode=BOARDMODE_MULT_DIV;
+ } else {
+ if(g_strcasecmp(gcomprisBoard->mode, "add_minus_mult_div")==0){
+ currentMode=MODE_NORMAL;
+ currentUiMode=UIMODE_NORMAL;
+ currentBoardMode=BOARDMODE_ADD_MINUS_MULT_DIV;
+ } else {
+ if(g_strcasecmp(gcomprisBoard->mode, "add_minus_mult_div_tux")==0){
+ currentMode=MODE_TUX;
+ currentUiMode=UIMODE_NORMAL;
+ currentBoardMode=BOARDMODE_ADD_MINUS_MULT_DIV;
+ } else {
+ currentMode=MODE_NORMAL;
+ currentUiMode=UIMODE_NORMAL;
+ g_warning("Fallback mode set to images");
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
}
}
}
}
+
if (currentUiMode == UIMODE_SOUND)
{
@@ -555,37 +824,37 @@ static void start_board (GcomprisBoard *agcomprisBoard)
base_y2 = BASE_CARD_Y2;
base_x1_tux = BASE_CARD_X1_TUX;
}
-
-
+
+
/* TRANSLATORS: Put here the numbers in your language */
numbers=_("0123456789");
assert(g_utf8_validate(numbers,-1,NULL)); // require by all utf8-functions
-
+
/* TRANSLATORS: Put here the alphabet lowercase in your language */
alphabet_lowercase=_("abcdefghijklmnopqrstuvwxyz");
assert(g_utf8_validate(alphabet_lowercase,-1,NULL)); // require by all utf8-functions
-
+
g_warning("Using lowercase %s", alphabet_lowercase);
-
+
/* TRANSLATORS: Put here the alphabet uppercase in your language */
alphabet_uppercase=_("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
assert(g_utf8_validate(alphabet_uppercase,-1,NULL)); // require by all utf8-functions
g_warning("Using uppercase %s", alphabet_uppercase);
-
+
if (currentMode == MODE_TUX){
tux_memory_size = tux_memory_sizes[gcomprisBoard->level];
tux_memory = g_queue_new ();
}
-
+
Paused = FALSE;
-
+
to_tux = FALSE;
if (currentUiMode == UIMODE_SOUND){
playing_sound = TRUE;
gcompris_play_ogg_cb("sounds/LuneRouge/musique/LRBuddhist_gong_05_by_Lionel_Allorge.ogg",start_callback);
} else
playing_sound = FALSE;
-
+
memory_next_level();
}
}
@@ -724,6 +993,8 @@ static void memory_destroy_all_items()
for(x=0; x<MAX_MEMORY_WIDTH; x++)
for(y=0; y<MAX_MEMORY_HEIGHT; y++)
{
+ if (memoryArray[x][y])
+ g_free(memoryArray[x][y]->second_value);
g_free(memoryArray[x][y]);
memoryArray[x][y] = NULL;
}
@@ -764,20 +1035,30 @@ static void get_image(MemoryItem *memoryItem, guint x, guint y)
if(memoryArray[x][y])
{
// Get the pair's image
- memoryItem->data = memoryArray[x][y]->data;
- memoryItem->type = memoryArray[x][y]->type;
- memoryArray[x][y] = memoryItem;
+ if (memoryArray[x][y]->type & (TYPE_ADD|TYPE_MINUS|TYPE_MULT|TYPE_DIV)){
+ memoryItem->data = memoryArray[x][y]->second_value;
+ memoryItem->type = memoryArray[x][y]->type;
+ memoryArray[x][y] = memoryItem;
+ // if created by g_malloc0, this is not usefull;
+ //memoryItem->second_value = NULL;
+ }
+ else {
+ memoryItem->data = memoryArray[x][y]->data;
+ memoryItem->type = memoryArray[x][y]->type;
+ memoryArray[x][y] = memoryItem;
+ }
return;
}
memoryArray[x][y] = memoryItem;
- if (currentUiMode == UIMODE_SOUND){
- get_random_token ( TYPE_SOUND, &memoryItem->type, &memoryItem->data);
+ switch (currentBoardMode) {
+ case BOARDMODE_SOUND:
+ get_random_token ( TYPE_SOUND, &memoryItem->type, &memoryItem->data, NULL);
g_assert (memoryItem->type == TYPE_SOUND);
- }
- else {
+ break;
+ case BOARDMODE_NORMAL:
switch(gcomprisBoard->level) {
case 0:
@@ -786,28 +1067,61 @@ static void get_image(MemoryItem *memoryItem, guint x, guint y)
case 3:
case 4:
/* Image mode */
- get_random_token ( TYPE_IMAGE, &memoryItem->type, &memoryItem->data);
+ get_random_token ( TYPE_IMAGE, &memoryItem->type, &memoryItem->data, NULL);
g_assert (memoryItem->type == TYPE_IMAGE);
break;
case 5:
/* Limited Text mode Numbers only */
- get_random_token ( TYPE_NUMBER, &memoryItem->type, &memoryItem->data);
+ get_random_token ( TYPE_NUMBER, &memoryItem->type, &memoryItem->data, NULL);
g_assert (memoryItem->type == TYPE_NUMBER);
break;
case 6:
/* Limited Text mode Numbers + Capitals */
- get_random_token ( TYPE_NUMBER | TYPE_UPPERCASE, &memoryItem->type, &memoryItem->data);
+ get_random_token ( TYPE_NUMBER | TYPE_UPPERCASE, &memoryItem->type, &memoryItem->data, NULL);
g_assert((memoryItem->type == TYPE_NUMBER)||(memoryItem->type==TYPE_UPPERCASE));
break;
default:
/* Text mode ALL */
- get_random_token ( TYPE_NUMBER | TYPE_UPPERCASE | TYPE_LOWERCASE, &memoryItem->type, &memoryItem->data);
+ get_random_token ( TYPE_NUMBER | TYPE_UPPERCASE | TYPE_LOWERCASE, &memoryItem->type, &memoryItem->data, NULL);
g_assert (memoryItem->type & ( TYPE_NUMBER | TYPE_UPPERCASE | TYPE_LOWERCASE));
break;
}
+ break;
+ case BOARDMODE_ADD:
+ get_random_token ( TYPE_ADD, &memoryItem->type, &memoryItem->data, &memoryItem->second_value);
+ g_assert (memoryItem->type == TYPE_ADD);
+ break;
+ case BOARDMODE_MINUS:
+ get_random_token ( TYPE_MINUS, &memoryItem->type, &memoryItem->data, &memoryItem->second_value);
+ g_assert (memoryItem->type == TYPE_MINUS);
+ break;
+ case BOARDMODE_MULT:
+ get_random_token ( TYPE_MULT, &memoryItem->type, &memoryItem->data, &memoryItem->second_value);
+ g_assert (memoryItem->type == TYPE_MULT);
+ break;
+ case BOARDMODE_DIV:
+ get_random_token ( TYPE_DIV, &memoryItem->type, &memoryItem->data, &memoryItem->second_value);
+ g_assert (memoryItem->type == TYPE_DIV);
+ break;
+ case BOARDMODE_ADD_MINUS:
+ get_random_token ( TYPE_ADD | TYPE_MINUS, &memoryItem->type, &memoryItem->data, &memoryItem->second_value);
+ g_assert (memoryItem->type & (TYPE_ADD | TYPE_MINUS));
+ break;
+ case BOARDMODE_MULT_DIV:
+ get_random_token ( TYPE_MULT | TYPE_DIV, &memoryItem->type, &memoryItem->data, &memoryItem->second_value);
+ g_assert (memoryItem->type & (TYPE_MULT | TYPE_DIV));
+ break;
+ case BOARDMODE_ADD_MINUS_MULT_DIV:
+ get_random_token ( TYPE_ADD | TYPE_MINUS |TYPE_MULT | TYPE_DIV , &memoryItem->type, &memoryItem->data, &memoryItem->second_value);
+ g_assert (memoryItem->type & (TYPE_ADD | TYPE_MINUS |TYPE_MULT | TYPE_DIV));
+ break;
+
+ default:
+ g_error("Don't now in what mode run !");
+ break;
}
g_warning("returned token %s for item x=%d y=%d", memoryItem->data, x, y);
@@ -849,8 +1163,8 @@ static void create_item(GnomeCanvasGroup *parent)
height = (base_y2-base_y1)/numberOfLine;
/* Remove a little bit of space for the card shadow */
- height2 = height * 0.9;
- width2 = width * 0.9;
+ height2 = height * 0.95;
+ width2 = width * 0.95;
if (currentUiMode == UIMODE_SOUND) {
@@ -916,7 +1230,7 @@ static void create_item(GnomeCanvasGroup *parent)
for(y=0; y<numberOfLine; y++)
{
- memoryItem = g_malloc(sizeof(MemoryItem));
+ memoryItem = g_malloc0(sizeof(MemoryItem));
memoryItem->rootItem = \
gnome_canvas_item_new (parent,
@@ -936,8 +1250,8 @@ static void create_item(GnomeCanvasGroup *parent)
"pixbuf", pixmap,
"x", (double) 0,
"y", (double) 0,
- "width", (double) width*0.9,
- "height", (double) height*0.9,
+ "width", (double) width2,
+ "height", (double) height2,
"width_set", TRUE,
"height_set", TRUE,
NULL);
@@ -951,8 +1265,8 @@ static void create_item(GnomeCanvasGroup *parent)
"pixbuf", pixmap,
"x", (double) 0,
"y", (double) 0,
- "width", (double) width*0.9,
- "height", (double) height*0.9,
+ "width", (double) width2,
+ "height", (double) height2,
"width_set", TRUE,
"height_set", TRUE,
NULL);
@@ -972,8 +1286,8 @@ static void create_item(GnomeCanvasGroup *parent)
"pixbuf", pixmap,
"x", (double) 0,
"y", (double) 0,
- "width", (double) width*0.9,
- "height", (double) height*0.9,
+ "width", (double) width2,
+ "height", (double) height2,
"width_set", TRUE,
"height_set", TRUE,
NULL);
@@ -986,17 +1300,17 @@ static void create_item(GnomeCanvasGroup *parent)
yratio=(height2*0.8)/(float)gdk_pixbuf_get_height(pixmap);
xratio=(width2*0.8)/(float)gdk_pixbuf_get_width(pixmap);
yratio=xratio=MIN(xratio, yratio);
- card_shadow_w = width*0.07;
- card_shadow_h = height*0.07;
+ card_shadow_w = width*0.05;
+ card_shadow_h = height*0.05;
memoryItem->frontcardItem = \
gnome_canvas_item_new (GNOME_CANVAS_GROUP(memoryItem->rootItem),
gnome_canvas_pixbuf_get_type (),
"pixbuf", pixmap,
- "x", (double) ((width*0.9)-
+ "x", (double) ((width2)-
gdk_pixbuf_get_width(pixmap)*xratio*0.8)/2 -
card_shadow_w,
- "y", (double) ((height*0.9)-
+ "y", (double) ((height2)-
gdk_pixbuf_get_height(pixmap)*yratio*0.8)/2 -
card_shadow_h,
"width", (double) gdk_pixbuf_get_width(pixmap)*xratio*0.8,
@@ -1007,16 +1321,21 @@ static void create_item(GnomeCanvasGroup *parent)
gdk_pixbuf_unref(pixmap);
} else {
+ gchar *font;
+ if (memoryItem->type & (TYPE_ADD|TYPE_MINUS|TYPE_MULT|TYPE_DIV))
+ font = op_fonts[gcomprisBoard->level];
+ else
+ font = TEXT_FONT;
/* It's a letter */
memoryItem->frontcardItem = \
gnome_canvas_item_new (GNOME_CANVAS_GROUP(memoryItem->rootItem),
gnome_canvas_text_get_type (),
"text", memoryItem->data,
- "font", TEXT_FONT,
- "x", (double) (width*0.8)/2,
- "y", (double) (height*0.8)/2,
+ "font", font,
+ "x", (double) (width2*0.9)/2,
+ "y", (double) (height2*0.9)/2,
"anchor", GTK_ANCHOR_CENTER,
- "fill_color_rgba", 0x99CDFFFF,
+ "fill_color_rgba", 0x559ADDFF,
NULL);
}
@@ -1301,10 +1620,19 @@ static gint
compare_card (gconstpointer a,
gconstpointer b)
{
- if (((MemoryItem *)a)->data == ((MemoryItem *)b)->data)
- return 0;
- else
- return -1;
+ MemoryItem *card1 = (MemoryItem *)a;
+ MemoryItem *card2 = (MemoryItem *)b;
+
+ if (card1->type & (TYPE_ADD|TYPE_MINUS|TYPE_MULT|TYPE_DIV)){
+ if ((!card1->second_value) && ( card2->second_value)){
+ return strcmp(card1->data,card2->second_value);
+ }
+ if ((!card2->second_value) && ( card1->second_value)){
+ return strcmp(card2->data,card1->second_value);
+ }
+ return -1;
+ }
+ return ((card1->data == card2->data) ? 0 : -1);
}
MemoryItem *find_card_in_tux_memory(MemoryItem *card)
diff --git a/src/boards/menu2.c b/src/boards/menu2.c
new file mode 100644
index 0000000..a1f9f1d
--- /dev/null
+++ b/src/boards/menu2.c
@@ -0,0 +1,1047 @@
+/* gcompris - menu2.c
+ *
+ * Time-stamp: <2006/01/29 20:15:14 yves>
+ *
+ * Copyright (C) 2000 Bruno Coudoin
+ *
+ * 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 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
+ */
+
+/**
+ * The menu display icons of each boards and let the user select one
+ *
+ * Seen from gcompris, the menu is a board like another.
+ */
+#include "gcompris/gcompris.h"
+#include "gcompris/gcompris_config.h"
+
+#define SOUNDLISTFILE PACKAGE
+#define MENU_PER_LINE 5
+
+typedef struct {
+ /* Information items (_s are shadow) */
+ GnomeCanvasItem *boardname_item;
+ GnomeCanvasRichText *description_item;
+ GnomeCanvasItem *author_item;
+ GnomeCanvasItem *boardname_item_s;
+ GnomeCanvasRichText *description_item_s;
+ GnomeCanvasItem *author_item_s;
+} MenuItems;
+
+static MenuItems *menuitems;
+
+static GcomprisBoard *gcomprisBoard = NULL;
+static gboolean board_paused = TRUE;
+
+static void menu_start (GcomprisBoard *agcomprisBoard);
+static void menu_pause (gboolean pause);
+static void menu_end (void);
+static gboolean menu_is_our_board (GcomprisBoard *gcomprisBoard);
+static void menu_config(void);
+
+static void menu_config_start(GcomprisBoard *agcomprisBoard,
+ GcomprisProfile *aProfile);
+
+static void menu_config_stop(void);
+
+static void menu_create_item(GnomeCanvasGroup *parent, MenuItems *menuitems, GcomprisBoard *board);
+static gboolean next_spot();
+static void create_info_area(GnomeCanvasGroup *parent, MenuItems *menuitems);
+static gint item_event(GnomeCanvasItem *item, GdkEvent *event, MenuItems *menuitems);
+static void display_board_icon(GcomprisBoard *board, MenuItems *menuitems);
+static void free_stuff (GtkObject *obj, gpointer data);
+static void set_content(GnomeCanvasRichText *item_content,
+ GnomeCanvasRichText *item_content_s,
+ gchar *text);
+
+static void display_section (gchar *path);
+static void display_welcome (void);
+static void create_panel(GnomeCanvasGroup *parent);
+static void create_top(GnomeCanvasGroup *parent, gchar *path);
+
+static double current_x = 0.0;
+static double current_y = 0.0;
+
+static double current_top_x = 0.0;
+static double current_top_y = 0.0;
+
+static double panel_x, panel_y, panel_w, panel_h;
+static double top_x, top_y, top_w, top_h, top_int_x;
+static double display_x, display_y, display_w, display_h, display_int_x, display_int_y;
+static double info_x, info_y, info_w, info_h;
+
+static double icon_size, icon_size_panel, icon_size_top, top_arrow_size;
+
+static gdouble get_ratio(GdkPixbuf *pixmap, gdouble size);
+
+GList *homeBoards = NULL;
+
+#define P_X 10
+#define P_Y 10
+#define P_W 90
+#define P_H 480
+
+#define T_X 175
+#define T_Y 5
+#define T_W 550
+#define T_H 55
+#define T_INT_X 5
+#define T_ARROW_SIZE 20
+
+#define D_X 175
+#define D_Y 64
+#define D_W 550
+#define D_H 320
+#define D_INT_X 50
+#define D_INT_Y 5
+
+#define I_X 120
+#define I_Y 380
+#define I_W 600
+#define I_H 125
+
+#define ICON_SIZE 100
+#define ICON_SIZE_PANEL 50
+#define ICON_SIZE_TOP 50
+
+static GnomeCanvasGroup *boardRootItem = NULL;
+static GnomeCanvasGroup *actualSectionItem = NULL;
+static GList *panelBoards = NULL;
+
+/* Description of this plugin */
+static BoardPlugin menu_bp =
+ {
+ NULL,
+ NULL,
+ N_("Main Menu Second Version"),
+ N_("Select a Board"),
+ "Bruno Coudoin <bruno.coudoin@free.fr>",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ menu_start,
+ menu_pause,
+ menu_end,
+ menu_is_our_board,
+ NULL,
+ NULL,
+ NULL,
+ menu_config,
+ NULL,
+ menu_config_start,
+ menu_config_stop
+ };
+
+/*
+ * Main entry point mandatory for each Gcompris's board
+ * ---------------------------------------------------
+ *
+ */
+
+
+GET_BPLUGIN_INFO(menu)
+
+/*
+ * in : boolean TRUE = PAUSE : FALSE = CONTINUE
+ *
+ */
+static void menu_pause (gboolean pause)
+{
+
+ if(gcomprisBoard==NULL)
+ return;
+
+ board_paused = pause;
+}
+
+/*
+ */
+static void menu_start (GcomprisBoard *agcomprisBoard)
+{
+
+ GcomprisProperties *properties = gcompris_get_properties();
+
+ current_x = 0.0;
+ current_y = 0.0;
+
+ /* initialisations */
+ /* in case we will make this parametrable */
+
+ panel_x = P_X;
+ panel_y = P_Y;
+ panel_w = P_W;
+ panel_h = P_H;
+
+ top_x = T_X;
+ top_y = T_Y;
+ top_w = T_W;
+ top_h = T_H;
+ top_int_x = T_INT_X;
+ top_arrow_size = T_ARROW_SIZE;
+
+ display_x = D_X;
+ display_y = D_Y;
+ display_w = D_W;
+ display_h = D_H;
+ display_int_x = D_INT_X;
+ display_int_y = D_INT_Y;
+
+ info_x = I_X;
+ info_y = I_Y;
+ info_w = I_W;
+ info_h = I_H;
+
+ icon_size = ICON_SIZE;
+ icon_size_panel = ICON_SIZE_PANEL;
+ icon_size_top = ICON_SIZE_TOP;
+
+ g_warning ("menu2 : start board");
+
+ if(agcomprisBoard!=NULL)
+ {
+
+ gcomprisBoard=agcomprisBoard;
+
+ menuitems = g_new(MenuItems, 1);
+
+ gcompris_set_background(gnome_canvas_root(gcomprisBoard->canvas),
+ gcompris_image_to_skin("gcompris-menu2bg.png"));
+
+ boardRootItem = GNOME_CANVAS_GROUP(
+ gnome_canvas_item_new (gnome_canvas_root(gcomprisBoard->canvas),
+ gnome_canvas_group_get_type (),
+ "x", (double) 0,
+ "y", (double) 0,
+ NULL));
+
+ g_object_set_data (G_OBJECT (boardRootItem), "menuitems", menuitems);
+ g_signal_connect (boardRootItem, "destroy",
+ G_CALLBACK (free_stuff),
+ menuitems);
+
+ create_info_area(boardRootItem, menuitems);
+
+ create_panel(boardRootItem);
+
+ if (properties->menu_position){
+ display_section(properties->menu_position);
+ }
+ else
+ display_welcome();
+
+ /* set initial values for this level */
+ gcomprisBoard->level = 1;
+ gcomprisBoard->maxlevel=1;
+ gcompris_bar_set(GCOMPRIS_BAR_CONFIG|GCOMPRIS_BAR_ABOUT);
+
+ /* FIXME : Workaround for bugged canvas */
+ //gnome_canvas_update_now(gcomprisBoard->canvas);
+
+ menu_pause(FALSE);
+
+ }
+
+}
+
+
+static void create_panel(GnomeCanvasGroup *parent)
+{
+ int n_sections;
+ GList *list = NULL;
+ GcomprisBoard *board;
+ GdkPixbuf *pixmap = NULL;
+ GnomeCanvasItem *item;
+ gdouble ratio;
+
+ gdouble x, y;
+ gint int_y;
+ GcomprisProperties *properties = gcompris_get_properties();
+
+ /* In normal mode, we show all the sections in panel */
+ /* in direct submenu access, we show the icon of the submenu */
+ if (strcmp(properties->root_menu,"/")==0)
+ panelBoards = gcompris_get_menulist(properties->root_menu);
+ else
+ panelBoards = g_list_append(list, gcomprisBoard);
+
+ n_sections = g_list_length(panelBoards);
+
+ if (n_sections == 0)
+ return;
+
+ if ( (panel_h/n_sections) <= icon_size_panel){
+ icon_size_panel = panel_h/n_sections;
+ int_y = 0;
+ }
+ else {
+ int_y = (panel_h - n_sections*icon_size_panel)/n_sections;
+ }
+
+ x = panel_x + panel_w/2.0;
+ y = panel_y + int_y/2.0;
+
+ for (list = panelBoards; list != NULL; list = list->next){
+ board = (GcomprisBoard *) list->data;
+
+ pixmap = gcompris_load_pixmap(board->icon_name);
+
+ ratio = get_ratio( pixmap, icon_size_panel);
+
+ item = gnome_canvas_item_new (parent,
+ gnome_canvas_pixbuf_get_type (),
+ "pixbuf", pixmap,
+ "x", x,
+ "y", y,
+ "width", (gdouble) gdk_pixbuf_get_width(pixmap)*ratio,
+ "height", (gdouble) gdk_pixbuf_get_height(pixmap)*ratio,
+ "width-set", TRUE,
+ "height-set", TRUE,
+ "anchor", GTK_ANCHOR_NORTH,
+ NULL);
+
+ gdk_pixbuf_unref(pixmap);
+
+ y += int_y + icon_size_panel;
+
+ g_object_set_data (G_OBJECT (item), "board", board);
+
+ gtk_signal_connect(GTK_OBJECT(item), "event",
+ (GtkSignalFunc) item_event,
+ menuitems);
+
+ gtk_signal_connect(GTK_OBJECT(item), "event",
+ (GtkSignalFunc) gcompris_item_event_focus,
+ NULL);
+
+ }
+
+
+
+}
+
+static void display_section (gchar *path)
+{
+ GList *boardlist; /* List of Board */
+
+ boardlist = gcompris_get_menulist(path);
+
+ if (actualSectionItem)
+ gtk_object_destroy (GTK_OBJECT(actualSectionItem));
+
+ current_x = 0.0;
+ current_y = 0.0;
+ current_top_x = 0.0;
+ current_top_y = 0.0;
+
+ actualSectionItem = GNOME_CANVAS_GROUP(
+ gnome_canvas_item_new ( boardRootItem,
+ gnome_canvas_group_get_type (),
+ "x", (double) 0,
+ "y", (double) 0,
+ NULL));
+
+
+ create_top (actualSectionItem, path);
+
+ g_list_foreach (boardlist, (GFunc) display_board_icon, menuitems);
+
+ if (strcmp(path,"home")!=0)
+ g_list_free(boardlist);
+
+}
+
+static void
+menu_end ()
+{
+ if(boardRootItem!=NULL)
+ {
+ /* WORKAROUND: There is a bug in the richtex item and we need to remove it first */
+ while (g_idle_remove_by_data (menuitems->description_item));
+ gtk_object_destroy (GTK_OBJECT(menuitems->description_item));
+
+ while (g_idle_remove_by_data (menuitems->description_item_s));
+ gtk_object_destroy (GTK_OBJECT(menuitems->description_item_s));
+
+ gtk_object_destroy (GTK_OBJECT(boardRootItem));
+ }
+
+ boardRootItem = NULL;
+ actualSectionItem = NULL;
+}
+
+static gboolean
+menu_is_our_board (GcomprisBoard *gcomprisBoard)
+{
+ if (gcomprisBoard)
+ {
+ if(g_strcasecmp(gcomprisBoard->type, "menu")==0)
+ {
+ /* Set the plugin entry */
+ gcomprisBoard->plugin=&menu_bp;
+
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+static void
+menu_config ()
+{
+ if(gcomprisBoard!=NULL)
+ {
+ menu_pause(TRUE);
+ gcompris_config_start();
+ }
+}
+
+
+
+/*-------------------------------------------------------------------------------*/
+/*-------------------------------------------------------------------------------*/
+/*-------------------------------------------------------------------------------*/
+/*-------------------------------------------------------------------------------*/
+
+static void display_board_icon(GcomprisBoard *board, MenuItems *menuitems)
+{
+ /* FIXME: Check board is available for the current profile */
+ if (board!=NULL
+ && board_check_file(board))
+ {
+ menu_create_item(actualSectionItem, menuitems, board);
+ }
+}
+
+/*
+ * Calculate the next stop where to place an item
+ * return false if there is no more space left
+ */
+static gboolean next_spot()
+{
+ if(current_x==0.0)
+ {
+ /* Initialisation case */
+ current_x = display_x + icon_size/2.0;
+ current_y = display_y + icon_size/2.0;
+ return(TRUE);
+ }
+
+ current_x += icon_size + display_int_x;
+
+ if(current_x > display_x + display_w - icon_size/2.0)
+ {
+ current_x = display_x + icon_size/2.0;
+ current_y += icon_size + display_int_y;
+ }
+
+ if ( current_y > display_y + display_h - icon_size/2.0 )
+ return FALSE;
+ else
+ return TRUE;
+
+}
+
+static void menu_create_item(GnomeCanvasGroup *parent, MenuItems *menuitems, GcomprisBoard *board)
+{
+ GdkPixbuf *menu_pixmap = NULL;
+ GdkPixbuf *pixmap = NULL;
+ GnomeCanvasItem *item, *menu_button;
+ int difficulty;
+ gchar *tmp_board_dir;
+ gdouble ratio, pixmap_w, pixmap_h;
+
+ /*
+ * Take care to load the board->icon_name from the dir specified
+ * in the board->board_dir
+ * To make it simple and reuse the gcompris_load_pixmap, we overwrite temporarily
+ * the gcomprisBoard->board_dir and board->board_dir
+ */
+ tmp_board_dir = gcomprisBoard->board_dir;
+ gcomprisBoard->board_dir = board->board_dir;
+ menu_pixmap = gcompris_load_pixmap(board->icon_name);
+ gcomprisBoard->board_dir = tmp_board_dir;
+
+ ratio = get_ratio (menu_pixmap, icon_size);
+
+ if (ratio < 1.0)
+ g_warning("Resize %s", board->icon_name);
+
+ pixmap_w = gdk_pixbuf_get_width(menu_pixmap)*ratio;
+ pixmap_h = gdk_pixbuf_get_height(menu_pixmap)*ratio;
+
+ next_spot();
+
+ menu_button = gnome_canvas_item_new (parent,
+ gnome_canvas_pixbuf_get_type (),
+ "pixbuf", menu_pixmap,
+ "x", (double)current_x - pixmap_w/2,
+ "y", (double)current_y - pixmap_h/2,
+ "width", (gdouble) pixmap_w,
+ "height", (gdouble) pixmap_h,
+ "width-set", TRUE,
+ "height-set", TRUE,
+ NULL);
+
+ // display difficulty stars
+ if (board->difficulty != NULL) {
+ difficulty = atoi(board->difficulty);
+ gcompris_display_difficulty_stars(parent,
+ (double)current_x - pixmap_w/2 - 25,
+ (double)current_y - pixmap_h/2,
+ (double) 0.6,
+ difficulty);
+ }
+
+ // display board availability due to sound voice not present
+ if(board->mandatory_sound_file)
+ {
+ gchar *soundfile = NULL;
+ gchar *soundfilename = NULL;
+
+ if(board->mandatory_sound_dataset) {
+ /* We have to search for an assetml sound */
+ soundfile = gcompris_get_asset_file(board->mandatory_sound_dataset, NULL, NULL,
+ board->mandatory_sound_file);
+ } else {
+ /* We search a fixed path sound file */
+ soundfilename = g_strdup_printf("%s/%s", "sounds",
+ board->mandatory_sound_file);
+ soundfile = gcompris_find_absolute_filename(soundfilename);
+ g_free(soundfilename);
+ g_warning("Checking mandatory_sound_file %s\n", soundfile);
+ }
+
+ if (!g_file_test (soundfile, G_FILE_TEST_EXISTS) || !gcompris_get_properties()->audio_works)
+ {
+ pixmap = gcompris_load_skin_pixmap("voice_bad.png");
+ }
+ else
+ {
+ pixmap = gcompris_load_skin_pixmap("voice.png");
+ }
+
+ gnome_canvas_item_new (parent,
+ gnome_canvas_pixbuf_get_type (),
+ "pixbuf", pixmap,
+ "x", (double)current_x - pixmap_w/2 - 25,
+ "y", (double)current_y - pixmap_h/2 + 28,
+ NULL);
+ gdk_pixbuf_unref(pixmap);
+ g_free(soundfile);
+ }
+
+ // display menu icon ========================== BEGIN
+ if(g_strcasecmp(board->type, "menu")==0)
+ {
+ pixmap = gcompris_load_skin_pixmap("menuicon.png");
+ item = gnome_canvas_item_new (parent,
+ gnome_canvas_pixbuf_get_type (),
+ "pixbuf", pixmap,
+ "x", (double)current_x - pixmap_w/2 - 25,
+ "y", (double)current_y - pixmap_h/2,
+ NULL);
+ gdk_pixbuf_unref(pixmap);
+ }
+
+ gdk_pixbuf_unref(menu_pixmap);
+
+ // display menu icon ========================== END
+
+ /*
+ * Now everything ready, map the events
+ * -------------------------------------
+ */
+ g_object_set_data (G_OBJECT (menu_button), "board", board);
+
+ gtk_signal_connect(GTK_OBJECT(menu_button), "event",
+ (GtkSignalFunc) item_event,
+ menuitems);
+
+ gtk_signal_connect(GTK_OBJECT(menu_button), "event",
+ (GtkSignalFunc) gcompris_item_event_focus,
+ NULL);
+
+}
+
+static gint
+item_event(GnomeCanvasItem *item, GdkEvent *event, MenuItems *menuitems)
+{
+ GcomprisBoard *board;
+ GdkPixbuf *pixmap;
+
+
+ if(board_paused)
+ return FALSE;
+
+ if(boardRootItem == NULL)
+ return FALSE;
+
+ board = g_object_get_data (G_OBJECT (item), "board");
+
+ switch (event->type)
+ {
+ case GDK_ENTER_NOTIFY:
+ if(board->title && G_IS_OBJECT(menuitems->boardname_item))
+ gnome_canvas_item_set (menuitems->boardname_item,
+ "text", board->title,
+ NULL);
+
+ if(board->description
+ && G_IS_OBJECT(menuitems->description_item)
+ && G_IS_OBJECT(menuitems->description_item_s))
+ set_content(menuitems->description_item,
+ menuitems->description_item_s,
+ board->description);
+
+ if(board->author && G_IS_OBJECT(menuitems->author_item))
+ gnome_canvas_item_set (menuitems->author_item,
+ "text", board->author,
+ NULL);
+
+ if(board->title && G_IS_OBJECT(menuitems->boardname_item_s))
+ gnome_canvas_item_set (menuitems->boardname_item_s,
+ "text", board->title,
+ NULL);
+
+ if(board->author && G_IS_OBJECT(menuitems->author_item_s))
+ gnome_canvas_item_set (menuitems->author_item_s,
+ "text", board->author,
+ NULL);
+
+ break;
+ case GDK_LEAVE_NOTIFY:
+ gnome_canvas_item_set (menuitems->boardname_item,
+ "text", " ",
+ NULL);
+
+ gnome_canvas_item_set (GNOME_CANVAS_ITEM(menuitems->description_item),
+ "text", " ",
+ NULL);
+
+ gnome_canvas_item_set (menuitems->author_item,
+ "text", " ",
+ NULL);
+
+ gnome_canvas_item_set (menuitems->boardname_item_s,
+ "text", " ",
+ NULL);
+
+ gnome_canvas_item_set (GNOME_CANVAS_ITEM(menuitems->description_item_s),
+ "text", " ",
+ NULL);
+
+ gnome_canvas_item_set (menuitems->author_item_s,
+ "text", " ",
+ NULL);
+
+ break;
+ case GDK_BUTTON_PRESS:
+ gcompris_play_ogg ("gobble", NULL);
+
+ if (strcmp(board->type,"menu")==0){
+ gchar *path = g_strdup_printf("%s/%s",board->section, board->name);
+ GcomprisProperties *properties = gcompris_get_properties();
+
+ display_section(path);
+
+ if (properties->menu_position)
+ g_free(properties->menu_position);
+
+ properties->menu_position = path;
+
+ }
+ else
+ board_run_next (board);
+
+ break;
+
+ default:
+ break;
+ }
+
+ return FALSE;
+}
+
+/* Apply the style to the given RichText item */
+static void
+set_content(GnomeCanvasRichText *item_content,
+ GnomeCanvasRichText *item_content_s,
+ gchar *text) {
+
+ GtkTextIter iter_start, iter_end;
+ GtkTextBuffer *buffer;
+ GtkTextTag *txt_tag;
+ gboolean success;
+ gchar *color_string;
+ GdkColor *color_s = (GdkColor *)malloc(sizeof(GdkColor));
+ GdkColor *color = (GdkColor *)malloc(sizeof(GdkColor));
+
+ /*
+ * Set the new text in the 2 items
+ */
+ gnome_canvas_item_set(GNOME_CANVAS_ITEM(item_content),
+ "text", text,
+ NULL);
+
+ gnome_canvas_item_set(GNOME_CANVAS_ITEM(item_content_s),
+ "text", text,
+ NULL);
+
+ /*
+ * Set the shadow
+ */
+
+ color_string = g_strdup_printf("#%x", gcompris_skin_color_shadow >> 8);
+ gdk_color_parse(color_string, color_s);
+ success = gdk_colormap_alloc_color(gdk_colormap_get_system(),
+ color_s,
+ FALSE, TRUE);
+
+ buffer = gnome_canvas_rich_text_get_buffer(GNOME_CANVAS_RICH_TEXT(item_content_s));
+ txt_tag = gtk_text_buffer_create_tag(buffer, NULL,
+ "foreground-gdk", color_s,
+ "font", gcompris_skin_font_board_medium,
+ NULL);
+ gtk_text_buffer_get_end_iter(buffer, &iter_end);
+ gtk_text_buffer_get_start_iter(buffer, &iter_start);
+ gtk_text_buffer_apply_tag(buffer, txt_tag, &iter_start, &iter_end);
+
+ g_free(color_string);
+
+ /*
+ * Set the text
+ */
+ color_string = g_strdup_printf("#%x", gcompris_skin_get_color("menu/text") >> 8);
+ gdk_color_parse(color_string, color);
+ success = gdk_colormap_alloc_color(gdk_colormap_get_system(),
+ color,
+ FALSE, TRUE);
+
+ buffer = gnome_canvas_rich_text_get_buffer(GNOME_CANVAS_RICH_TEXT(item_content));
+ txt_tag = gtk_text_buffer_create_tag(buffer, NULL,
+ "foreground-gdk", color,
+ "font", gcompris_skin_font_board_medium,
+ NULL);
+ gtk_text_buffer_get_end_iter(buffer, &iter_end);
+ gtk_text_buffer_get_start_iter(buffer, &iter_start);
+ gtk_text_buffer_apply_tag(buffer, txt_tag, &iter_start, &iter_end);
+
+}
+
+/** \brief create the area in which we display the board title and description
+ *
+ */
+static void create_info_area(GnomeCanvasGroup *parent, MenuItems *menuitems)
+{
+ gint x = (double) info_x + info_w/2.0;
+ gint y = info_y;
+
+ if(parent == NULL)
+ return;
+
+ menuitems->boardname_item_s = \
+ gnome_canvas_item_new (parent,
+ gnome_canvas_text_get_type (),
+ "text", " ",
+ "font", gcompris_skin_font_board_big,
+ "x", (double) x + 1.0,
+ "y", (double) y + 1.0,
+ "anchor", GTK_ANCHOR_NORTH,
+ "fill_color_rgba", gcompris_skin_color_shadow,
+ NULL);
+
+ menuitems->boardname_item = \
+ gnome_canvas_item_new (parent,
+ gnome_canvas_text_get_type (),
+ "text", " ",
+ "font", gcompris_skin_font_board_big,
+ "x", (double) x,
+ "y", (double) y,
+ "anchor", GTK_ANCHOR_NORTH,
+ "fill_color_rgba", gcompris_skin_get_color("menu/text"),
+ NULL);
+
+ menuitems->description_item_s = \
+ GNOME_CANVAS_RICH_TEXT(gnome_canvas_item_new (parent,
+ gnome_canvas_rich_text_get_type (),
+ "x", (double) x + 1.0,
+ "y", (double) y + 28 + 1.0,
+ "width", info_w,
+ "height", info_h - 28,
+ "anchor", GTK_ANCHOR_NORTH,
+ "justification", GTK_JUSTIFY_CENTER,
+ "grow_height", FALSE,
+ "cursor_visible", FALSE,
+ "cursor_blink", FALSE,
+ "editable", FALSE,
+ NULL));
+ menuitems->description_item = \
+ GNOME_CANVAS_RICH_TEXT(gnome_canvas_item_new (parent,
+ gnome_canvas_rich_text_get_type (),
+ "x", (double) x,
+ "y", (double) y + 28,
+ "width", info_w,
+ "height", info_h - 28,
+ "anchor", GTK_ANCHOR_NORTH,
+ "justification", GTK_JUSTIFY_CENTER,
+ "grow_height", FALSE,
+ "cursor_visible", FALSE,
+ "cursor_blink", FALSE,
+ "editable", FALSE,
+ NULL));
+
+ menuitems->author_item_s = \
+ gnome_canvas_item_new (parent,
+ gnome_canvas_text_get_type (),
+ "text", " ",
+ "font", gcompris_skin_font_board_tiny,
+ "x", (double) x + 1.0,
+ "y", (double) y + 90 + 1.0,
+ "anchor", GTK_ANCHOR_NORTH,
+ "fill_color_rgba", gcompris_skin_color_shadow,
+ "justification", GTK_JUSTIFY_CENTER,
+ NULL);
+
+ menuitems->author_item = \
+ gnome_canvas_item_new (parent,
+ gnome_canvas_text_get_type (),
+ "text", " ",
+ "font", gcompris_skin_font_board_tiny,
+ "x", (double) x,
+ "y", (double) y + 90,
+ "anchor", GTK_ANCHOR_NORTH,
+ "fill_color_rgba", gcompris_skin_get_color("menu/text"),
+ "justification", GTK_JUSTIFY_CENTER,
+ NULL);
+
+}
+
+static void
+free_stuff (GtkObject *obj, gpointer data)
+{
+ g_free (data);
+}
+
+
+static gdouble get_ratio(GdkPixbuf *pixmap, gdouble size)
+{
+
+ gdouble ratio = 1.0;
+ gint pixmap_h, pixmap_w;
+
+ pixmap_w = gdk_pixbuf_get_width(pixmap);
+ pixmap_h = gdk_pixbuf_get_height(pixmap);
+
+ if (pixmap_h <= pixmap_w){
+ if (pixmap_w > size)
+ ratio = size / pixmap_w;
+ }
+ else {
+ if (pixmap_h > size)
+ ratio = size / pixmap_h;
+ }
+
+ return ratio;
+
+}
+
+static void create_top(GnomeCanvasGroup *parent, gchar *path)
+{
+ gchar **splitted_section;
+ gint i = 1;
+ GdkPixbuf *pixmap = NULL;
+ gdouble ratio;
+ GcomprisBoard *board;
+ gchar *path1, *path2;
+
+ GnomeCanvasItem *item;
+
+ GcomprisProperties *properties = gcompris_get_properties();
+
+ if (!path)
+ return;
+
+ splitted_section = g_strsplit (path, "/", 0);
+
+ path1 = g_strdup("");
+
+ /* splitted_section[0] is always "" */
+ i = 1;
+
+ while (splitted_section[i] != NULL)
+ {
+
+ path2 = g_strdup_printf("%s/%s", path1, splitted_section[i]);
+
+ g_free(path1);
+ path1 = path2;
+
+ if (strcmp(path1, properties->root_menu)<0){
+ i++;
+ continue;
+ }
+
+ if (current_top_x == 0.0){
+ current_top_x = top_x;
+ current_top_y = top_y + top_h/2.0;
+ } else {
+ pixmap = gcompris_load_skin_pixmap("button_forward.png");
+ ratio = get_ratio(pixmap, top_arrow_size);
+
+ gnome_canvas_item_new (parent,
+ gnome_canvas_pixbuf_get_type (),
+ "pixbuf", pixmap,
+ "x", current_top_x,
+ "y", current_top_y,
+ "width", (gdouble) gdk_pixbuf_get_width(pixmap)*ratio,
+ "height", (gdouble) gdk_pixbuf_get_height(pixmap)*ratio,
+ "width-set", TRUE,
+ "height-set", TRUE,
+ "anchor", GTK_ANCHOR_WEST,
+ NULL);
+
+ gdk_pixbuf_unref(pixmap);
+
+ current_top_x += top_arrow_size + top_int_x;
+
+ }
+
+ board = gcompris_get_board_from_section(path1);
+
+ pixmap = gcompris_load_pixmap(board->icon_name);
+
+ ratio = get_ratio( pixmap, icon_size_top);
+
+ item = gnome_canvas_item_new (parent,
+ gnome_canvas_pixbuf_get_type (),
+ "pixbuf", pixmap,
+ "x", current_top_x,
+ "y", current_top_y,
+ "width", (gdouble) gdk_pixbuf_get_width(pixmap)*ratio,
+ "height", (gdouble) gdk_pixbuf_get_height(pixmap)*ratio,
+ "width-set", TRUE,
+ "height-set", TRUE,
+ "anchor", GTK_ANCHOR_WEST,
+ NULL);
+
+ gdk_pixbuf_unref(pixmap);
+
+ current_top_x += top_int_x + icon_size_top;
+
+ g_object_set_data (G_OBJECT (item), "board", board);
+
+ gtk_signal_connect(GTK_OBJECT(item), "event",
+ (GtkSignalFunc) item_event,
+ menuitems);
+
+ gtk_signal_connect(GTK_OBJECT(item), "event",
+ (GtkSignalFunc) gcompris_item_event_focus,
+ NULL);
+
+
+
+ i++;
+ }
+
+ g_free(path1);
+
+}
+
+static void display_welcome (void)
+{
+ GnomeCanvasItem *logo;
+ GdkPixbuf *pixmap;
+
+ if (actualSectionItem)
+ {
+ g_error("actualSectionItem exists in display_section !");
+ }
+
+
+ actualSectionItem = GNOME_CANVAS_GROUP(
+ gnome_canvas_item_new ( boardRootItem,
+ gnome_canvas_group_get_type (),
+ "x", (double) 0,
+ "y", (double) 0,
+ NULL));
+
+ pixmap = gcompris_load_skin_pixmap("gcompris-about.png");
+
+
+ logo = gnome_canvas_item_new (actualSectionItem,
+ gnome_canvas_pixbuf_get_type (),
+ "pixbuf", pixmap,
+ "x", (gdouble) display_x + display_w/2.0,
+ "y", (gdouble) display_y + display_h/2.0,
+ "anchor", GTK_ANCHOR_CENTER,
+ NULL);
+
+ gdk_pixbuf_unref(pixmap);
+
+ if(G_IS_OBJECT(menuitems->boardname_item))
+ gnome_canvas_item_set (menuitems->boardname_item,
+ "text", "GCompris V" VERSION,
+ NULL);
+
+ if(G_IS_OBJECT(menuitems->description_item)
+ && G_IS_OBJECT(menuitems->description_item_s))
+ set_content(menuitems->description_item,
+ menuitems->description_item_s,
+ _("GCompris is a collection of educational games that provides for children from 2 years old with different activities."));
+
+ if(G_IS_OBJECT(menuitems->author_item))
+ gnome_canvas_item_set (menuitems->author_item,
+ "text", _("Bruno Coudoin, Genius"),
+ NULL);
+ if(G_IS_OBJECT(menuitems->boardname_item_s))
+ gnome_canvas_item_set (menuitems->boardname_item_s,
+ "text", "GCompris V" VERSION,
+ NULL);
+
+ if(G_IS_OBJECT(menuitems->author_item_s))
+ gnome_canvas_item_set (menuitems->author_item_s,
+ "text", _("Bruno Coudoin, Genius"),
+ NULL);
+
+}
+
+static void
+menu_config_start(GcomprisBoard *agcomprisBoard,
+ GcomprisProfile *aProfile){
+ if(gcomprisBoard!=NULL)
+ {
+ menu_pause(TRUE);
+ gcompris_config_start();
+ }
+}
+
+/* ======================= */
+/* = config_stop = */
+/* ======================= */
+static void
+menu_config_stop()
+{
+}
+
+
+
+/* Local Variables: */
+/* mode:c */
+/* eval:(load-library "time-stamp") */
+/* eval:(make-local-variable 'write-file-hooks) */
+/* eval:(add-hook 'write-file-hooks 'time-stamp) */
+/* eval:(setq time-stamp-format '(time-stamp-yyyy/mm/dd time-stamp-hh:mm:ss user-login-name)) */
+/* End: */
diff --git a/src/boards/missingletter.c b/src/boards/missingletter.c
index 35d97fb..60a6158 100644
--- a/src/boards/missingletter.c
+++ b/src/boards/missingletter.c
@@ -173,7 +173,7 @@ static void start_board (GcomprisBoard *agcomprisBoard)
50,
gcomprisBoard->height - 50,
gcomprisBoard->number_of_sublevel);
- gcompris_bar_set(GCOMPRIS_BAR_LEVEL);
+ gcompris_bar_set(GCOMPRIS_BAR_CONFIG | GCOMPRIS_BAR_LEVEL);
missing_letter_next_level();
@@ -723,11 +723,33 @@ static GHFunc save_table (gpointer key,
static GcomprisConfCallback conf_ok(GHashTable *table)
{
+ if (!table){
+ if (gcomprisBoard)
+ pause_board(FALSE);
+ return NULL;
+ }
+
g_hash_table_foreach(table, (GHFunc) save_table, NULL);
board_conf = NULL;
profile_conf = NULL;
+ if (gcomprisBoard){
+ gcompris_reset_locale();
+ GHashTable *config = gcompris_get_board_conf();
+
+ gcompris_change_locale(g_hash_table_lookup( config, "locale"));
+
+ g_hash_table_destroy(config);
+
+ destroy_board_list();
+
+ init_xml();
+
+ missing_letter_next_level();
+
+ }
+
return NULL;
}
@@ -738,6 +760,9 @@ config_start(GcomprisBoard *agcomprisBoard,
board_conf = agcomprisBoard;
profile_conf = aProfile;
+ if (gcomprisBoard)
+ pause_board(TRUE);
+
gcompris_configuration_window( g_strdup_printf("<b>%s</b> configuration\n for profile <b>%s</b>",
agcomprisBoard->name,
aProfile->name),
diff --git a/src/boards/py-gcompris-profile.c b/src/boards/py-gcompris-profile.c
index 9f5bb39..48f1135 100644
--- a/src/boards/py-gcompris-profile.c
+++ b/src/boards/py-gcompris-profile.c
@@ -12,6 +12,9 @@ staticforward PyTypeObject pyGcomprisProfileType;
PyObject*
gcompris_new_pyGcomprisProfileObject(GcomprisProfile* profile)
{
+ if (!profile)
+ return Py_None;
+
pyGcomprisProfileObject* theprofile = NULL;
theprofile = PyObject_New(pyGcomprisProfileObject, &pyGcomprisProfileType);
diff --git a/src/boards/py-mod-anim.c b/src/boards/py-mod-anim.c
index 3047f8e..535a028 100644
--- a/src/boards/py-mod-anim.c
+++ b/src/boards/py-mod-anim.c
@@ -169,7 +169,7 @@ Animation_init(py_GcomprisAnimation *self, PyObject *args, PyObject *key)
static void Animation_free(py_GcomprisAnimation *self)
{
- printf("*** Garbage collecting Animation ***\n");
+ g_warning("*** Garbage collecting Animation ***\n");
if( self->a)
gcompris_free_animation(self->a);
PyObject_DEL(self);
@@ -211,7 +211,7 @@ AnimCanvas_init(py_GcomprisAnimCanvas *self, PyObject *args, PyObject *key)
static void
AnimCanvas_free(py_GcomprisAnimCanvas *self)
{
- printf("*** garbage collecting AnimCanvas ***\n");
+ g_warning("*** garbage collecting AnimCanvas ***\n");
if(self->item)
{
g_warning("You should really call destroy() on an AnimCanvas "
diff --git a/src/boards/py-mod-gcompris.c b/src/boards/py-mod-gcompris.c
index 7a74a7d..5dc3102 100644
--- a/src/boards/py-mod-gcompris.c
+++ b/src/boards/py-mod-gcompris.c
@@ -1067,7 +1067,10 @@ static GcomprisConfCallback pyGcomprisConfCallback(GHashTable* table){
gil = pyg_gil_state_ensure();
- result = PyObject_CallFunction(pyGcomprisConfCallbackFunc, "O", hash_to_dict(table));
+ if (table)
+ result = PyObject_CallFunction(pyGcomprisConfCallbackFunc, "O", hash_to_dict(table));
+ else
+ result = PyObject_CallFunction(pyGcomprisConfCallbackFunc, "O", Py_None);
// This callback can be called multiple time ? not now
diff --git a/src/boards/python/gnumch.py b/src/boards/python/gnumch.py
index 39b178e..61562f5 100644
--- a/src/boards/python/gnumch.py
+++ b/src/boards/python/gnumch.py
@@ -919,5 +919,9 @@ class Gcompris_gnumch:
return 0
def end(self):
+ for i in range(0, len(self.troggles)):
+ self.troggles[i].anim.destroy()
+ if self.muncher.anim:
+ self.muncher.anim.destroy()
self.stopGame()
self.rootitem.destroy()
diff --git a/src/boards/python/pythontest.py b/src/boards/python/pythontest.py
index 88130d3..72df0d8 100644
--- a/src/boards/python/pythontest.py
+++ b/src/boards/python/pythontest.py
@@ -91,7 +91,7 @@ class Gcompris_pythontest:
color_name = self.config_dict['color_line']
self.colors['line'] = self.config_colors[color_name]
- gcompris.bar_set(0)
+ gcompris.bar_set(gcompris.BAR_CONFIG)
gcompris.set_background(self.gcomprisBoard.canvas.root(),
gcompris.skin.image_to_skin("gcompris-bg.jpg"))
gcompris.bar_set_level(self.gcomprisBoard)
@@ -390,6 +390,7 @@ class Gcompris_pythontest:
# Configuration function.
def config_start(self, profile):
# keep profile in mind
+ # profile can be Py_None
self.configuring_profile = profile
# init with default values
@@ -483,10 +484,14 @@ class Gcompris_pythontest:
# Callback when the "OK" button is clicked in configuration window
# this get all the _changed_ values
def ok_callback(self, table):
+ if (table == None):
+ print 'Configuration returns None'
+ return
+
print "Keys and values returned by PythonTest config window:"
if (len(table) == 0):
- print '%20s' % 'None'
+ print '%20s' % 'None'
for key,value in table.iteritems():
print '%20s:%20s ' % (key, value)
diff --git a/src/boards/reading.c b/src/boards/reading.c
index 061d31f..c0e7b1c 100644
--- a/src/boards/reading.c
+++ b/src/boards/reading.c
@@ -1,6 +1,6 @@
/* gcompris - reading.c
*
- * Time-stamp: <2005/09/29 22:09:55 bruno>
+ * Time-stamp: <2006/01/31 09:20:51 yves>
*
* Copyright (C) 2000 Bruno Coudoin
*
@@ -189,7 +189,7 @@ static void start_board (GcomprisBoard *agcomprisBoard)
gcomprisBoard->level = 1;
gcomprisBoard->maxlevel = 9;
- gcompris_bar_set(GCOMPRIS_BAR_LEVEL);
+ gcompris_bar_set(GCOMPRIS_BAR_CONFIG|GCOMPRIS_BAR_LEVEL);
font_size = PANGO_PIXELS(pango_font_description_get_size (pango_font_description_from_string (gcompris_skin_font_board_medium)));
interline = (int) (1.5*font_size);
@@ -829,10 +829,32 @@ static GHFunc save_table (gpointer key,
static GcomprisConfCallback conf_ok(GHashTable *table)
{
+ if (!table){
+ if (gcomprisBoard)
+ pause_board(FALSE);
+ return;
+ }
+
g_hash_table_foreach(table, (GHFunc) save_table, NULL);
board_conf = NULL;
profile_conf = NULL;
+
+
+ if (gcomprisBoard){
+ gcompris_reset_locale();
+
+ GHashTable *config = gcompris_get_board_conf();
+
+ gcompris_change_locale(g_hash_table_lookup( config, "locale"));
+
+ g_hash_table_destroy(config);
+
+ reading_next_level();
+
+ pause_board(FALSE);
+ }
+
}
static void
@@ -842,9 +864,12 @@ reading_config_start(GcomprisBoard *agcomprisBoard,
board_conf = agcomprisBoard;
profile_conf = aProfile;
+ if (gcomprisBoard)
+ pause_board(TRUE);
+
gcompris_configuration_window( g_strdup_printf("<b>%s</b> configuration\n for profile <b>%s</b>",
agcomprisBoard->name,
- aProfile->name),
+ aProfile? aProfile->name: ""),
(GcomprisConfCallback )conf_ok);
/* init the combo to previously saved value */
diff --git a/src/boards/shapegame.c b/src/boards/shapegame.c
index ff0ec6a..ded9c11 100644
--- a/src/boards/shapegame.c
+++ b/src/boards/shapegame.c
@@ -1,6 +1,6 @@
/* gcompris - shapegame.c
*
- * Time-stamp: <2005/11/12 18:56:26 bruno>
+ * Time-stamp: <2006/01/31 00:13:12 yves>
*
* Copyright (C) 2000 Bruno Coudoin
*
@@ -259,7 +259,11 @@ static void start_board (GcomprisBoard *agcomprisBoard)
g_free(filename);
- gcompris_bar_set(GCOMPRIS_BAR_LEVEL|GCOMPRIS_BAR_OK);
+ if (strcmp(gcomprisBoard->name, "imagename")==0){
+ gcompris_bar_set(GCOMPRIS_BAR_CONFIG|GCOMPRIS_BAR_LEVEL|GCOMPRIS_BAR_OK);
+ } else
+ gcompris_bar_set(GCOMPRIS_BAR_LEVEL|GCOMPRIS_BAR_OK);
+
gcomprisBoard->sublevel = 0;
@@ -2092,10 +2096,31 @@ static GHFunc save_table (gpointer key,
static GcomprisConfCallback conf_ok(GHashTable *table)
{
+ if (!table){
+ if (gcomprisBoard)
+ pause_board(FALSE);
+ return;
+ }
+
g_hash_table_foreach(table, (GHFunc) save_table, NULL);
board_conf = NULL;
profile_conf = NULL;
+
+ if ((gcomprisBoard) && (strcmp(gcomprisBoard->name, "imagename")==0)){
+ GHashTable *config = gcompris_get_board_conf();
+
+ gcompris_reset_locale();
+
+ gcompris_change_locale(g_hash_table_lookup( config, "locale"));
+
+ g_hash_table_destroy(config);
+
+ shapegame_next_level();
+
+ pause_board(FALSE);
+ }
+
}
static void
@@ -2105,9 +2130,12 @@ config_start(GcomprisBoard *agcomprisBoard,
board_conf = agcomprisBoard;
profile_conf = aProfile;
+ if (gcomprisBoard)
+ pause_board(TRUE);
+
gcompris_configuration_window( g_strdup_printf("<b>%s</b> configuration\n for profile <b>%s</b>",
agcomprisBoard->name,
- aProfile->name),
+ aProfile? aProfile->name : ""),
(GcomprisConfCallback )conf_ok);
/* init the combo to previously saved value */
diff --git a/src/boards/smallnumbers.c b/src/boards/smallnumbers.c
index e2ac9e3..b14b874 100644
--- a/src/boards/smallnumbers.c
+++ b/src/boards/smallnumbers.c
@@ -1,6 +1,6 @@
/* gcompris - smallnumbers.c
*
- * Time-stamp: <2006/02/03 21:11:30 bruno>
+ * Time-stamp: <2006/03/01 01:05:57 bruno>
*
* Copyright (C) 2000 Bruno Coudoin
*
@@ -141,7 +141,7 @@ static void start_board (GcomprisBoard *agcomprisBoard)
{
GHashTable *config = gcompris_get_board_conf();
- locale_sound = g_hash_table_lookup( config, "locale_sound");
+ locale_sound = g_strdup(g_hash_table_lookup( config, "locale_sound"));
gchar *control_sound = g_hash_table_lookup( config, "with_sound");
@@ -150,6 +150,8 @@ static void start_board (GcomprisBoard *agcomprisBoard)
else
with_sound = FALSE;
+ g_hash_table_destroy(config);
+
if(agcomprisBoard!=NULL)
{
gcomprisBoard=agcomprisBoard;
@@ -166,7 +168,7 @@ static void start_board (GcomprisBoard *agcomprisBoard)
gcomprisBoard->width - 220,
gcomprisBoard->height - 50,
gcomprisBoard->number_of_sublevel);
- gcompris_bar_set(GCOMPRIS_BAR_LEVEL);
+ gcompris_bar_set(GCOMPRIS_BAR_CONFIG|GCOMPRIS_BAR_LEVEL);
number_of_dices=1;
@@ -357,11 +359,12 @@ static void smallnumbers_create_item(GnomeCanvasGroup *parent)
GnomeCanvasGroup *group_item;
guint i;
char *lettersItem;
- char *str1 = NULL;
- char *str2 = NULL;
+ gchar *str1 = NULL;
+ gchar *str2 = NULL;
guint total_number = 0;
double x = 0.0;
guint number_of_dice = number_of_dices;
+ gchar *letter;
group_item = GNOME_CANVAS_GROUP(
gnome_canvas_item_new (parent,
@@ -387,7 +390,17 @@ static void smallnumbers_create_item(GnomeCanvasGroup *parent)
lettersItem[1] = '\0';
- str1 = g_strdup_printf("%s%s", lettersItem, ".ogg");
+ gunichar *unichar_letterItem;
+
+ unichar_letterItem = g_new(gunichar,1);
+
+ *unichar_letterItem = g_utf8_get_char (lettersItem);
+
+ letter = g_new0(gchar, 6);
+ g_unichar_to_utf8 ( *unichar_letterItem, letter);
+
+ str1 = gcompris_alphabet_sound(letter);
+
str2 = gcompris_get_asset_file_locale("gcompris alphabet", NULL, "audio/x-ogg", str1, locale_sound);
if (with_sound)
@@ -494,12 +507,40 @@ static GHFunc save_table (gpointer key,
static GcomprisConfCallback conf_ok(GHashTable *table)
{
+ if (!table){
+ if (gcomprisBoard)
+ pause_board(FALSE);
+ return;
+ }
+
g_hash_table_foreach(table, (GHFunc) save_table, NULL);
board_conf = NULL;
profile_conf = NULL;
- return NULL;
+ if (gcomprisBoard){
+ GHashTable *config = gcompris_get_board_conf();
+
+ if (locale_sound)
+ g_free(locale_sound);
+
+ locale_sound = g_strdup(g_hash_table_lookup( config, "locale_sound"));
+
+ gchar *control_sound = g_hash_table_lookup( config, "with_sound");
+
+ if (control_sound && strcmp(g_hash_table_lookup( config, "with_sound"),"True")==0)
+ with_sound = TRUE;
+ else
+ with_sound = FALSE;
+
+ g_hash_table_destroy(config);
+
+ smallnumbers_next_level();
+
+ gamewon = FALSE;
+
+ pause_board(FALSE);
+ }
}
static gboolean check_text(gchar *key, gchar *text, GtkLabel *label){
@@ -522,6 +563,9 @@ smallnumber_config_start(GcomprisBoard *agcomprisBoard,
board_conf = agcomprisBoard;
profile_conf = aProfile;
+ if (gcomprisBoard)
+ pause_board(TRUE);
+
gchar *label;
label = g_strdup_printf("<b>%s</b> configuration\n for profile <b>%s</b>",
@@ -534,7 +578,7 @@ smallnumber_config_start(GcomprisBoard *agcomprisBoard,
/* init the combo to previously saved value */
GHashTable *config = gcompris_get_conf( profile_conf, board_conf);
- locale_sound = g_hash_table_lookup( config, "locale_sound");
+ gchar *saved_locale_sound = g_hash_table_lookup( config, "locale_sound");
gchar *control_sound = g_hash_table_lookup( config, "with_sound");
if (control_sound && strcmp(g_hash_table_lookup( config, "with_sound"),"True")==0)
@@ -544,7 +588,7 @@ smallnumber_config_start(GcomprisBoard *agcomprisBoard,
GtkCheckButton *sound_control = gcompris_boolean_box("Enable sounds", "with_sound", with_sound);
- GtkComboBox *sound_box = gcompris_combo_locales_asset( "Select sound locale", locale_sound, "gcompris colors", NULL, "audio/x-ogg", "purple.ogg");
+ GtkComboBox *sound_box = gcompris_combo_locales_asset( "Select sound locale", saved_locale_sound, "gcompris colors", NULL, "audio/x-ogg", "purple.ogg");
gtk_widget_set_sensitive(GTK_WIDGET(sound_box), with_sound);
@@ -552,6 +596,8 @@ smallnumber_config_start(GcomprisBoard *agcomprisBoard,
G_CALLBACK(sound_control_box_toggled),
sound_box);
+ g_hash_table_destroy(config);
+
}
/* ======================= */
/* = config_stop = */
diff --git a/src/boards/wordprocessor.c b/src/boards/wordprocessor.c
new file mode 100644
index 0000000..9e4966b
--- /dev/null
+++ b/src/boards/wordprocessor.c
@@ -0,0 +1,605 @@
+/* gcompris - wordprocessor.c
+ *
+ * Copyright (C) 2006 Bruno Coudoin
+ *
+ * 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 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
+ */
+
+#include <ctype.h>
+#include <math.h>
+#include <assert.h>
+#include <string.h>
+
+#include "gcompris/gcompris.h"
+
+/*
+ * Predefined styles
+ * -----------------
+ */
+typedef struct {
+ gchar *name;
+ gchar *font;
+ PangoWeight weight;
+ GtkJustification justification;
+ gint indent;
+ gint pixels_above_lines;
+ gint pixels_below_lines;
+ gchar *foreground;
+} style_t;
+
+static style_t doctype_default[] =
+ {
+ { "H0", "Serif 30", PANGO_WEIGHT_ULTRABOLD, GTK_JUSTIFY_CENTER, 0, 40, 20, "black"},
+ { "H1", "Serif 26", PANGO_WEIGHT_BOLD, GTK_JUSTIFY_LEFT, 0, 30, 15, "black" },
+ { "H2", "Serif 20", PANGO_WEIGHT_SEMIBOLD, GTK_JUSTIFY_LEFT, 0, 20, 12, "black" },
+ { "P", "Serif 16", PANGO_WEIGHT_NORMAL, GTK_JUSTIFY_LEFT, 30, 3, 3, "black" }
+ };
+#define NUMBER_OF_STYLE G_N_ELEMENTS(doctype_default)
+
+static style_t doctype_love_letter[] =
+ {
+ { "Hx0", "Serif 30", PANGO_WEIGHT_ULTRABOLD, GTK_JUSTIFY_CENTER, 0, 40, 20, "DeepPink" },
+ { "Hx1", "Serif 26", PANGO_WEIGHT_BOLD, GTK_JUSTIFY_LEFT, 0, 30, 15, "HotPink" },
+ { "Hx2", "Serif 20", PANGO_WEIGHT_SEMIBOLD, GTK_JUSTIFY_LEFT, 0, 20, 12, "MediumOrchid" },
+ { "Px", "Serif 16", PANGO_WEIGHT_NORMAL, GTK_JUSTIFY_LEFT, 30, 3, 3, "black" }
+ };
+
+static style_t *doctype_list[] =
+ {
+ doctype_default,
+ doctype_love_letter
+ };
+
+static GcomprisBoard *gcomprisBoard = NULL;
+static gboolean board_paused = TRUE;
+static GtkWidget *gtk_combo_filetypes = NULL;
+
+static void start_board (GcomprisBoard *agcomprisBoard);
+static void pause_board (gboolean pause);
+static void end_board (void);
+static gboolean is_our_board (GcomprisBoard *gcomprisBoard);
+static void set_level (guint level);
+static gboolean key_press_event (GtkWidget *text_view,
+ GdkEventKey *event);
+
+static GnomeCanvasGroup *boardRootItem = NULL;
+
+static GnomeCanvasItem *wordprocessor_create(void);
+static void wordprocessor_destroy_all_items(void);
+static gint item_event(GnomeCanvasItem *item, GdkEvent *event, gpointer data);
+static void display_style_buttons(GnomeCanvasGroup *boardRootItem,
+ int x,
+ int y);
+static void create_tags (GtkTextBuffer *buffer, style_t style[]);
+static void set_default_style (GtkTextBuffer *buffer, style_t *style);
+static void display_style_selector(GnomeCanvasGroup *boardRootItem);
+static void item_event_style_selection (GtkComboBox *widget, void *styles_tab[]);
+
+#define word_area_x1 120
+#define word_area_y1 80
+#define word_area_width 580
+#define word_area_height 420
+
+#define combo_style_x1 500
+#define combo_style_y1 20
+
+static style_t *current_style_default;
+static style_t **current_doctype_default;
+static GtkTextBuffer *buffer;
+static GtkWidget *view;
+static GHashTable* styles_hash = NULL;
+
+/* Description of this plugin */
+static BoardPlugin menu_bp =
+ {
+ NULL,
+ NULL,
+ "Wordprocessor",
+ "A basic word processor",
+ "Bruno Coudoin <bruno.coudoin@free.fr>",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ start_board,
+ pause_board,
+ end_board,
+ is_our_board,
+ NULL,
+ NULL,
+ set_level,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ };
+
+/*
+ * Main entry point mandatory for each Gcompris's game
+ * ---------------------------------------------------
+ *
+ */
+
+GET_BPLUGIN_INFO(wordprocessor)
+
+/*
+ * in : boolean TRUE = PAUSE : FALSE = CONTINUE
+ *
+ */
+static void pause_board (gboolean pause)
+{
+ if(gcomprisBoard==NULL)
+ return;
+
+ board_paused = pause;
+}
+
+/*
+ */
+static void start_board (GcomprisBoard *agcomprisBoard)
+{
+
+ if(agcomprisBoard!=NULL)
+ {
+ gcomprisBoard=agcomprisBoard;
+ gcomprisBoard->level=1;
+ gcomprisBoard->maxlevel=1;
+ gcomprisBoard->sublevel=1;
+ gcomprisBoard->number_of_sublevel=1; /* Go to next level after this number of 'play' */
+ gcompris_bar_set(0);
+
+ gcompris_set_background(gnome_canvas_root(gcomprisBoard->canvas),
+ gcompris_image_to_skin("gcompris-shapebg.jpg"));
+
+ wordprocessor_create();
+
+ pause_board(FALSE);
+
+ }
+}
+/* ======================================= */
+static void end_board ()
+{
+ if(gcomprisBoard!=NULL)
+ {
+ pause_board(TRUE);
+ wordprocessor_destroy_all_items();
+ }
+ gcomprisBoard = NULL;
+}
+
+/* ======================================= */
+static void set_level (guint level)
+{
+}
+/* ======================================= */
+static gboolean is_our_board (GcomprisBoard *gcomprisBoard)
+{
+ if (gcomprisBoard)
+ {
+ if(g_strcasecmp(gcomprisBoard->type, "wordprocessor")==0)
+ {
+ /* Set the plugin entry */
+ gcomprisBoard->plugin=&menu_bp;
+
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/*-------------------------------------------------------------------------------*/
+/*-------------------------------------------------------------------------------*/
+/* ==================================== */
+/* Destroy all the items */
+static void wordprocessor_destroy_all_items()
+{
+ if(boardRootItem!=NULL)
+ gtk_object_destroy (GTK_OBJECT(boardRootItem));
+
+ boardRootItem = NULL;
+}
+/* ==================================== */
+static GnomeCanvasItem *wordprocessor_create()
+{
+ GnomeCanvasItem *item = NULL;
+ GtkWidget *sw;
+
+ boardRootItem = GNOME_CANVAS_GROUP(
+ gnome_canvas_item_new (gnome_canvas_root(gcomprisBoard->canvas),
+ gnome_canvas_group_get_type (),
+ "x", (double) 0,
+ "y", (double) 0,
+ NULL));
+
+ view = gtk_text_view_new ();
+ gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (view), GTK_WRAP_WORD);
+ g_signal_connect (view, "key-release-event",
+ G_CALLBACK (key_press_event), NULL);
+
+ buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
+
+
+ sw = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
+ GTK_POLICY_AUTOMATIC,
+ GTK_POLICY_ALWAYS);
+ gtk_container_add (GTK_CONTAINER (sw), view);
+
+ item = gnome_canvas_item_new (GNOME_CANVAS_GROUP(boardRootItem),
+ gnome_canvas_widget_get_type (),
+ "widget", GTK_WIDGET(sw),
+ "x", (double) word_area_x1,
+ "y", (double) word_area_y1,
+ "width", (double) word_area_width,
+ "height", (double) word_area_height,
+ "anchor", GTK_ANCHOR_NW,
+ "size_pixels", FALSE,
+ NULL);
+ gtk_widget_show(GTK_WIDGET(view));
+ gtk_widget_show(GTK_WIDGET(sw));
+
+ /*
+ * Create the default style tags
+ */
+ current_doctype_default = &doctype_list[0];
+ create_tags(buffer, *current_doctype_default);
+
+ /*
+ * Display the style buttons
+ */
+ display_style_buttons(boardRootItem,
+ word_area_x1 + word_area_width + 10,
+ word_area_y1);
+
+ display_style_selector(boardRootItem);
+
+ return NULL;
+}
+
+/*
+ * Display the style buttons
+ */
+static void display_style_buttons(GnomeCanvasGroup *boardRootItem,
+ int x,
+ int y)
+{
+ GdkPixbuf *pixmap;
+ int offset_y, text_x, text_y;
+ int i = 0;
+ gchar *styles_tab[] = { _("TITLE"), "H0",
+ _("TITLE 1"), "H1",
+ _( "TITLE 2"), "H2",
+ _("TEXT"), "P",
+ NULL, NULL };
+
+ pixmap = gcompris_load_skin_pixmap("button_small.png");
+
+ offset_y = gdk_pixbuf_get_height(pixmap) + 10;
+ text_x = gdk_pixbuf_get_width(pixmap) / 2;
+ text_y = gdk_pixbuf_get_height(pixmap) / 2;
+
+ while(styles_tab[i])
+ {
+ GnomeCanvasItem *item;
+
+ item = gnome_canvas_item_new (boardRootItem,
+ gnome_canvas_pixbuf_get_type (),
+ "pixbuf", pixmap,
+ "x", (double) x,
+ "y", (double) y,
+ "anchor", GTK_ANCHOR_NW,
+ NULL);
+
+ gtk_signal_connect(GTK_OBJECT(item), "event", (GtkSignalFunc) item_event, styles_tab[i+1] );
+ gtk_signal_connect(GTK_OBJECT(item), "event", (GtkSignalFunc) gcompris_item_event_focus, NULL);
+
+ item = gnome_canvas_item_new (boardRootItem,
+ gnome_canvas_text_get_type (),
+ "text", styles_tab[i],
+ "font", gcompris_skin_font_board_medium,
+ "x", (double) x + text_x + 1,
+ "y", (double) y + text_y + 1,
+ "anchor", GTK_ANCHOR_CENTER,
+ "fill_color_rgba", gcompris_skin_color_shadow,
+ NULL);
+ gtk_signal_connect(GTK_OBJECT(item), "event", (GtkSignalFunc) item_event, styles_tab[i+1] );
+
+ item = gnome_canvas_item_new (boardRootItem,
+ gnome_canvas_text_get_type (),
+ "text", styles_tab[i],
+ "font", gcompris_skin_font_board_medium,
+ "x", (double) x + text_x,
+ "y", (double) y + text_y,
+ "anchor", GTK_ANCHOR_CENTER,
+ "fill_color_rgba", gcompris_skin_color_text_button,
+ NULL);
+ gtk_signal_connect(GTK_OBJECT(item), "event", (GtkSignalFunc) item_event, styles_tab[i+1] );
+
+ y += offset_y;
+
+ i += 2;
+ }
+
+ gdk_pixbuf_unref(pixmap);
+}
+
+/* ==================================== */
+
+/* ==================================== */
+static gint
+item_event(GnomeCanvasItem *item, GdkEvent *event, gpointer data)
+{
+
+ if(board_paused)
+ return FALSE;
+
+ switch (event->type)
+ {
+ case GDK_BUTTON_PRESS:
+ switch(event->button.button)
+ {
+ case 1:
+ case 2:
+ case 3:
+ {
+ GtkTextIter iter_start, iter_end;
+ gchar *current_style_name;
+
+ current_style_name = (char *)data;
+
+ gtk_text_buffer_get_iter_at_mark(buffer,
+ &iter_start,
+ gtk_text_buffer_get_insert (buffer));
+ gtk_text_iter_set_line_offset(&iter_start, 0);
+
+ iter_end = iter_start;
+ gtk_text_iter_forward_to_line_end(&iter_end);
+
+ gtk_text_buffer_remove_all_tags(buffer,
+ &iter_start,
+ &iter_end);
+
+ gtk_text_buffer_apply_tag_by_name(buffer,
+ current_style_name,
+ &iter_start,
+ &iter_end);
+ }
+ break;
+ default:
+ break;
+ }
+ default:
+ break;
+ }
+
+ return FALSE;
+}
+
+/* Create a bunch of tags. Note that it's also possible to
+ * create tags with gtk_text_tag_new() then add them to the
+ * tag table for the buffer, gtk_text_buffer_create_tag() is
+ * just a convenience function. Also note that you don't have
+ * to give tags a name; pass NULL for the name to create an
+ * anonymous tag.
+ *
+ * In any real app, another useful optimization would be to create
+ * a GtkTextTagTable in advance, and reuse the same tag table for
+ * all the buffers with the same tag set, instead of creating
+ * new copies of the same tags for every buffer.
+ *
+ * Tags are assigned default priorities in order of addition to the
+ * tag table. That is, tags created later that affect the same text
+ * property affected by an earlier tag will override the earlier
+ * tag. You can modify tag priorities with
+ * gtk_text_tag_set_priority().
+ */
+
+static void
+create_tags (GtkTextBuffer *buffer, style_t style[])
+{
+ gint i;
+
+ for(i=0; i<NUMBER_OF_STYLE; i++)
+ {
+ GtkTextTag *tag;
+
+ tag = gtk_text_buffer_create_tag (buffer, style[i].name,
+ "weight", style[i].weight,
+ "font", style[i].font,
+ "justification", style[i].justification,
+ "indent", style[i].indent,
+ "pixels-above-lines", style[i].pixels_above_lines,
+ "pixels-below-lines", style[i].pixels_below_lines,
+ "foreground", style[i].foreground,
+ NULL);
+ g_object_set_data (G_OBJECT (tag), "style", &style[i]);
+ }
+
+ /* Point to the last style */
+ i--;
+
+ current_style_default = &style[i];
+ set_default_style(buffer, current_style_default);
+}
+
+/*
+ * Set the default style
+ */
+static void
+set_default_style (GtkTextBuffer *buffer, style_t *style)
+{
+ PangoFontDescription *font_desc;
+ GdkColor color;
+
+ printf("set_default_style %s\n", style->name);
+ /* Change default font throughout the widget */
+ font_desc = pango_font_description_from_string (style->font);
+ gtk_widget_modify_font (view, font_desc);
+ pango_font_description_free (font_desc);
+
+ /* Change default color throughout the widget */
+ gdk_color_parse (style->foreground, &color);
+ gtk_widget_modify_text (view, GTK_STATE_NORMAL, &color);
+
+ /* Change left margin, justification, ... throughout the widget */
+ gtk_text_view_set_indent (GTK_TEXT_VIEW (view), style->indent);
+ gtk_text_view_set_justification(GTK_TEXT_VIEW (view), style->justification);
+ gtk_text_view_set_pixels_below_lines(GTK_TEXT_VIEW (view), style->pixels_below_lines);
+ gtk_text_view_set_pixels_above_lines(GTK_TEXT_VIEW (view), style->pixels_above_lines);
+}
+
+
+/*
+ * Create the combo with the styles
+ * --------------------------------
+ */
+static void
+display_style_selector(GnomeCanvasGroup *boardRootItem)
+{
+ int i = 0;
+
+ /* The list of all styles */
+ gchar *doctype_names[] = {
+ _("Default"),
+ _("Love letter"),
+ NULL
+ };
+
+ styles_hash = g_hash_table_new (g_str_hash, g_str_equal);
+
+ gtk_combo_filetypes = gtk_combo_box_new_text();
+
+ while ( doctype_names[i] != NULL)
+ {
+ g_hash_table_insert(styles_hash, doctype_names[i], &doctype_list[i]);
+
+ gtk_combo_box_append_text(GTK_COMBO_BOX(gtk_combo_filetypes), (gchar *)doctype_names[i]);
+
+ i++;
+ }
+
+ gnome_canvas_item_new (GNOME_CANVAS_GROUP(boardRootItem),
+ gnome_canvas_widget_get_type (),
+ "widget", GTK_WIDGET(gtk_combo_filetypes),
+ "x", (double) combo_style_x1,
+ "y", (double) combo_style_y1,
+ "width", (double) BOARDWIDTH - combo_style_x1 - 10,
+ "height", 35.0,
+ "anchor", GTK_ANCHOR_NW,
+ "size_pixels", FALSE,
+ NULL);
+
+ gtk_widget_show(GTK_WIDGET(gtk_combo_filetypes));
+ gtk_combo_box_set_active(GTK_COMBO_BOX(gtk_combo_filetypes), 0);
+
+ g_signal_connect(G_OBJECT(gtk_combo_filetypes),
+ "changed",
+ G_CALLBACK(item_event_style_selection),
+ doctype_names);
+}
+
+/* Catch all typing events to apply the proper tags
+ *
+ */
+static void
+item_event_style_selection (GtkComboBox *widget,
+ void *doctype_names[])
+{
+ gchar *style_str;
+ style_t **doctype;
+
+ style_str = gtk_combo_box_get_active_text((GtkComboBox *)widget);
+
+ printf("item_event_style_selection %s\n", style_str);
+
+ /* Search the doctype */
+ doctype = (style_t *)(g_hash_table_lookup(styles_hash, style_str));
+ if(doctype) {
+ int i = 0;
+
+ while(doctype[i])
+ {
+ printf("==>%s\n", doctype[i]->name);
+ i++;
+ }
+ }
+}
+
+
+/* Catch all typing events to apply the proper tags
+ *
+ */
+static gboolean
+key_press_event (GtkWidget *text_view,
+ GdkEventKey *event)
+{
+ GtkTextIter iter_start, iter_end;
+ GtkTextBuffer *buffer;
+
+ {
+ GSList *tags = NULL, *tagp = NULL;
+
+ buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (text_view));
+
+ gtk_text_buffer_get_iter_at_mark(buffer,
+ &iter_start,
+ gtk_text_buffer_get_insert (buffer));
+ gtk_text_iter_set_line_offset(&iter_start, 0);
+
+ iter_end = iter_start;
+ gtk_text_iter_forward_to_line_end(&iter_end);
+
+ tags = gtk_text_iter_get_tags (&iter_start);
+ printf("length %d\n", g_slist_length(tags));
+ if(g_slist_length(tags) == 0)
+ {
+ gtk_text_iter_backward_char (&iter_end);
+ tags = gtk_text_iter_get_tags (&iter_end);
+ gtk_text_iter_forward_char (&iter_end);
+ printf("2 length %d\n", g_slist_length(tags));
+ }
+
+ for (tagp = tags; tagp != NULL; tagp = tagp->next)
+ {
+ GtkTextTag *tag = tagp->data;
+ gchar *name;
+ g_object_get (G_OBJECT (tag), "name", &name, NULL);
+ style_t *style = g_object_get_data (G_OBJECT (tag), "style");
+
+ printf("name=%s style=%s\n", name, style->name);
+ set_default_style(buffer, style);
+ gtk_text_buffer_apply_tag_by_name(buffer,
+ name,
+ &iter_start,
+ &iter_end);
+ }
+
+ if (tags)
+ g_slist_free (tags);
+ else
+ {
+ /* Set the default style */
+ set_default_style(buffer, current_style_default);
+ gtk_text_buffer_apply_tag_by_name(buffer,
+ current_style_default->name,
+ &iter_start,
+ &iter_end);
+ }
+ }
+
+ return FALSE;
+}
+
diff --git a/src/gcompris/Makefile.am b/src/gcompris/Makefile.am
index 37b5f7b..1bb9a32 100644
--- a/src/gcompris/Makefile.am
+++ b/src/gcompris/Makefile.am
@@ -93,6 +93,7 @@ libgcomprisinclude_HEADERS = \
gcompris.h \
gcompris-board.h \
board_config.h \
+ gcompris_alphabeta.h \
gcompris_config.h \
gcompris_db.h \
gcompris_im.h \
@@ -120,7 +121,9 @@ libgcompris_1_la_SOURCES = \
pixbuf_util.c \
board.h board.c \
board_config.h board_config.c \
+ gcompris_alphabeta.c \
gcompris_files.c \
+ gcompris_confirm.c \
profile.c \
wordlist.c \
gcompris_db.c \
diff --git a/src/gcompris/anim.c b/src/gcompris/anim.c
index 569337d..e6eb66d 100644
--- a/src/gcompris/anim.c
+++ b/src/gcompris/anim.c
@@ -138,6 +138,11 @@ void gcompris_deactivate_animation(GcomprisAnimCanvasItem *item)
return;
}
+ if (GNOME_IS_CANVAS_ITEM(item->canvas)){
+ gtk_object_destroy(GTK_OBJECT(item->canvas));
+ item->canvas = NULL;
+ }
+
active = g_slist_delete_link(active, node);
g_object_unref(item->iter);
g_free(item);
@@ -177,7 +182,7 @@ static gboolean anim_tick(void *ignore)
{
if(active == NULL)
{
- printf("deactivating anim_tick\n");
+ g_warning("deactivating anim_tick\n");
return FALSE;
}
diff --git a/src/gcompris/bar.c b/src/gcompris/bar.c
index 8ef55f6..5433dcb 100644
--- a/src/gcompris/bar.c
+++ b/src/gcompris/bar.c
@@ -1,6 +1,6 @@
/* gcompris - bar.c
*
- * Time-stamp: <2006/02/25 12:31:09 bruno>
+ * Time-stamp: <2006/03/01 01:05:02 bruno>
*
* Copyright (C) 2000-2003 Bruno Coudoin
*
@@ -54,6 +54,8 @@ static guint level_handler_id;
static gint sound_play_id = 0;
+void confirm_quit(gboolean answer);
+
/*
* Main entry point
* ----------------
@@ -544,9 +546,10 @@ item_event_bar(GnomeCanvasItem *item, GdkEvent *event, gchar *data)
}
else if(!strcmp((char *)data, "configuration"))
{
- if(gcomprisBoard->plugin->config != NULL)
+ if(gcomprisBoard->plugin->config_start != NULL)
{
- gcomprisBoard->plugin->config();
+ gcomprisBoard->plugin->config_start(gcomprisBoard,
+ gcompris_get_current_profile());
}
}
else if(!strcmp((char *)data, "about"))
@@ -555,7 +558,12 @@ item_event_bar(GnomeCanvasItem *item, GdkEvent *event, gchar *data)
}
else if(!strcmp((char *)data, "quit"))
{
- gcompris_exit();
+ //gcompris_exit();
+ gcompris_confirm( "GCompris confirmation",
+ "Sure you want to quit ?",
+ "Yes, i am sure !",
+ "No, i am Bruno\'s daughter",
+ (ConfirmCallBack) confirm_quit);
}
break;
@@ -566,7 +574,11 @@ item_event_bar(GnomeCanvasItem *item, GdkEvent *event, gchar *data)
}
-
+void confirm_quit(gboolean answer)
+{
+ if (answer)
+ gcompris_exit();
+}
/* Local Variables: */
diff --git a/src/gcompris/board_config.c b/src/gcompris/board_config.c
index efc7ace..03ba270 100644
--- a/src/gcompris/board_config.c
+++ b/src/gcompris/board_config.c
@@ -1,6 +1,6 @@
/* gcompris - board_config.c
*
- * Time-stamp: <2005/10/01 14:34:12 bruno>
+ * Time-stamp: <2006/01/30 08:57:29 yves>
*
* Copyright (C) 2001 Pascal Georges
*
@@ -80,104 +80,90 @@ static void check_key(gchar *key)
g_error(" Key %s forbiden ! Change !", key);
}
-void gcompris_close_board_conf (GtkButton *button,
- gpointer user_data)
+void gcompris_close_board_conf (GtkDialog *dialog,
+ gpointer user_data)
{
- gtk_object_destroy ((GtkObject *)conf_window);
+ gtk_object_destroy (GTK_OBJECT(dialog));
g_hash_table_destroy (hash_conf);
hash_conf = NULL;
- Confcallback = NULL;
+
+ /* in case we close without response */
+ if (Confcallback){
+ Confcallback(NULL);
+ Confcallback = NULL;
+ }
+
g_free(label_markup);
}
-void gcompris_apply_board_conf (GtkButton *button,
- gpointer user_data)
+void gcompris_response_board_conf (GtkButton *button,
+ gint arg1,
+ gpointer user_data)
{
- if (Confcallback != NULL)
- Confcallback(hash_conf);
- gcompris_close_board_conf (button,
- user_data);
+ if (Confcallback){
+
+ switch (arg1){
+ case GTK_RESPONSE_APPLY:
+ Confcallback(hash_conf);
+ break;
+ case GTK_RESPONSE_CANCEL:
+ Confcallback(NULL);
+ break;
+ case GTK_RESPONSE_NONE:
+ Confcallback(NULL);
+ break;
+ default:
+ Confcallback(NULL);
+ break;
+ }
+
+ Confcallback = NULL;
+ }
+
+ gcompris_close_board_conf (GTK_DIALOG(conf_window), NULL);
+
}
GtkVBox *gcompris_configuration_window(gchar *label, GcomprisConfCallback callback)
{
- GtkButton *button, *button_ok;
- GtkWidget *footer;
GtkWidget *header;
- GtkWidget *separator;
/* init static values or callbacks */
Confcallback = callback;
hash_conf = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
/* main configuration window */
- conf_window = GTK_WINDOW(gtk_window_new (GTK_WINDOW_TOPLEVEL));
+ conf_window = GTK_WINDOW(gtk_dialog_new_with_buttons ("GCompris",
+ GTK_WINDOW(gtk_widget_get_toplevel (GTK_WIDGET(get_current_gcompris_board()->canvas))),
+ GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_STOCK_CANCEL,
+ GTK_RESPONSE_CANCEL,
+ GTK_STOCK_APPLY,
+ GTK_RESPONSE_APPLY,
+ NULL));
+
/* parameters */
- gtk_window_set_default_size (conf_window,
- 320,
- 300);
-
- gtk_window_set_resizable (conf_window, TRUE);
+ gtk_window_set_position (conf_window,
+ GTK_WIN_POS_CENTER_ALWAYS);
- gtk_window_set_transient_for(conf_window,
- GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(get_current_gcompris_board()->canvas))));
- gtk_window_set_modal(conf_window, TRUE);
gtk_widget_show(GTK_WIDGET(conf_window));
/* main vbox in window */
- main_conf_box = GTK_VBOX(gtk_vbox_new ( FALSE, 0));
- gtk_widget_show(GTK_WIDGET(main_conf_box));
- gtk_container_add(GTK_CONTAINER(conf_window), GTK_WIDGET(main_conf_box));
-
- /* hbox for apply and close buttons */
- separator = gtk_hseparator_new();
- gtk_widget_show(separator);
-
- footer = gtk_hbox_new (FALSE, 0);
- gtk_widget_show(footer);
-
- gtk_box_pack_end (GTK_BOX(main_conf_box),
- footer,
- FALSE,
- FALSE,
- 0);
+ main_conf_box = GTK_VBOX(GTK_DIALOG(conf_window)->vbox);
-
- gtk_box_pack_end (GTK_BOX(main_conf_box),
- separator,
- FALSE,
- FALSE,
- 8);
- /* Close button */
- button = GTK_BUTTON(gtk_button_new_from_stock(GTK_STOCK_CLOSE));
- gtk_widget_show(GTK_WIDGET(button));
-
- g_signal_connect(G_OBJECT(button),
- "clicked",
- G_CALLBACK(gcompris_close_board_conf),
+ g_signal_connect(G_OBJECT(conf_window),
+ "response",
+ G_CALLBACK(gcompris_response_board_conf),
NULL);
- /* Ok button */
- button_ok = GTK_BUTTON(gtk_button_new_from_stock(GTK_STOCK_OK));
- gtk_widget_show(GTK_WIDGET(button_ok));
- g_signal_connect (G_OBJECT(button_ok),
- "clicked",
- G_CALLBACK(gcompris_apply_board_conf),
+ g_signal_connect (G_OBJECT(conf_window),
+ "close",
+ G_CALLBACK(gcompris_close_board_conf),
NULL);
- gtk_box_pack_end (GTK_BOX(footer),
- GTK_WIDGET(button_ok),
- FALSE,
- FALSE,
- 0);
-
- gtk_box_pack_end (GTK_BOX(footer),
- GTK_WIDGET(button),
- FALSE,
- FALSE,
- 0);
+
/* Label header */
header = gtk_label_new ((gchar *)NULL);
@@ -340,7 +326,6 @@ GtkComboBox *gcompris_combo_box(const gchar *label, GList *strings, gchar *key,
return GTK_COMBO_BOX(combobox);
}
-static gchar *radio_value = NULL;
static GSList *radio_group = NULL;
static GtkWidget *radio_box;
static gchar *radio_key = NULL;
@@ -665,8 +650,13 @@ GtkComboBox *gcompris_combo_locales(gchar *init)
static gchar *current_locale = NULL;
void gcompris_change_locale(gchar *locale)
{
- if ((!locale) || strcmp(locale, "NULL") == 0)
+ if (!locale)
+ return;
+
+ if (strcmp(locale, "NULL") == 0){
+ gcompris_reset_locale();
return;
+ }
current_locale = g_strdup(gcompris_get_locale());
diff --git a/src/gcompris/gameutil.c b/src/gcompris/gameutil.c
index 600f42d..618d2ac 100644
--- a/src/gcompris/gameutil.c
+++ b/src/gcompris/gameutil.c
@@ -1,6 +1,6 @@
/* gcompris - gameutil.c
*
- * Time-stamp: <2005/11/17 11:13:26 yves>
+ * Time-stamp: <2006/01/20 10:06:29 yves>
*
* Copyright (C) 2000 Bruno Coudoin
*
@@ -683,6 +683,8 @@ GList *gcompris_get_menulist(gchar *section)
GList *result_list = NULL;
gchar *model;
+ GcomprisProperties *properties = gcompris_get_properties();
+
if (strlen(section)==1)
model = g_strdup("");
else
@@ -696,6 +698,10 @@ GList *gcompris_get_menulist(gchar *section)
for(list = boards_list; list != NULL; list = list->next) {
GcomprisBoard *board = list->data;
+ if ( (!properties->experimental) &&
+ (strcmp (board->name, "experimental") == 0))
+ continue;
+
if (strcmp (model, board->section) == 0) {
if (strlen(board->name) != 0)
result_list = g_list_append(result_list, board);
diff --git a/src/gcompris/gcompris.c b/src/gcompris/gcompris.c
index f115626..68e40e8 100644
--- a/src/gcompris/gcompris.c
+++ b/src/gcompris/gcompris.c
@@ -1277,6 +1277,7 @@ gcompris_init (int argc, char *argv[])
else {
g_warning("Using menu %s as root.", popt_root_menu);
properties->root_menu = g_strdup(popt_root_menu);
+ properties->menu_position = g_strdup(popt_root_menu);
}
}
diff --git a/src/gcompris/gcompris.h b/src/gcompris/gcompris.h
index c9d5a6c..80bee96 100644
--- a/src/gcompris/gcompris.h
+++ b/src/gcompris/gcompris.h
@@ -1,6 +1,6 @@
/* gcompris - gcompris.h
*
- * Time-stamp: <2005/11/11 12:50:47 bruno>
+ * Time-stamp: <2006/02/05 08:44:11 yves>
*
* Copyright (C) 2000,2001,2002 Bruno Coudoin
*
@@ -53,6 +53,7 @@
#include "gcompris_files.h"
#include "wordlist.h"
#include "gcompris_im.h"
+#include "gcompris_alphabeta.h"
#ifdef USE_CAIRO
#include "gcompris-cairo.h"
@@ -147,6 +148,16 @@ void gcompris_exit();
gchar *gcompris_get_database();
+typedef void (*ConfirmCallBack) (gboolean answer);
+
+void gcompris_confirm (gchar *title,
+ gchar *question_text,
+ gchar *yes_text,
+ gchar *no_text,
+ ConfirmCallBack iscb);
+
+void gcompris_confirm_stop (void);
+
/* Trace Log */
#define GCOMPRIS_LOG_STATUS_PASSED "PASSED"
#define GCOMPRIS_LOG_STATUS_FAILED "FAILED"
diff --git a/src/gcompris/gcompris_alphabeta.c b/src/gcompris/gcompris_alphabeta.c
new file mode 100644
index 0000000..256f6ae
--- /dev/null
+++ b/src/gcompris/gcompris_alphabeta.c
@@ -0,0 +1,131 @@
+/* gcompris - gcompris_alphabeta.c
+ *
+ * Time-stamp: <2006/02/06 18:34:37 yves>
+ *
+ * Copyright (C) 2000 Bruno Coudoin
+ *
+ * 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 should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "gcompris.h"
+
+/* gcompris_alphabeta returns the best value of evaluation functions */
+/* set the bestChild to the index of child with this value */
+/* maximize : TRUE if depth is maximize one, neither FALSE. */
+/* treeGame : pointer on game to pass to others functions, */
+/* bestChild : pointer on GList wich will contains list of indexes fo best plays. */
+/* isLeaf : TRUE if game correspond to a Leaf of Tree. */
+/* firstChild : return pointer on first child of a node. */
+/* nextSibling : return pointer on next sibling of a node. */
+/* heuristic : evaluation function of game. */
+/* depth is max depth of recursion */
+gint gcompris_alphabeta (gboolean maximize,
+ gpointer treeGame,
+ EvalFunction heuristic,
+ gint *bestChild,
+ FirstChildGameFunction firstChild,
+ NextSiblingGameFunction nextSibling,
+ gint alpha,
+ gint beta,
+ gint depth
+ )
+{
+ gpointer child;
+ gint m, t, nextBest, index;
+
+ g_assert (depth >= 0);
+
+ child = firstChild(treeGame);
+
+ *bestChild = -1;
+
+/* g_warning("gcompris_alphabeta %d %d %d", depth, alpha, beta); */
+
+ /* directly return value for leaf node*/
+ if ((!child) || (depth == 0)){
+/* g_warning("gcompris_alphabeta %d returns %d bestChild %d", depth, heuristic(treeGame), *bestChild); */
+ return heuristic(treeGame);
+ }
+
+ index = 0;
+
+ if (maximize) {
+ m = alpha;
+ while (child){
+ t = gcompris_alphabeta (!maximize,
+ child,
+ heuristic,
+ &nextBest,
+ firstChild,
+ nextSibling,
+ m,
+ beta,
+ depth - 1
+ );
+ if (t > m){
+ m = t;
+ *bestChild = index;
+ }
+ if ( m >= beta){
+/* g_warning("gcompris_alphabeta %d returns %d bestChild %d", depth, heuristic(treeGame), *bestChild); */
+ return m;
+ }
+ index++;
+ child = nextSibling(child);
+ }
+/* g_warning("gcompris_alphabeta %d returns %d bestChild %d", depth, heuristic(treeGame), *bestChild); */
+ return m;
+ }
+ else {
+ /* minimize */
+ m = beta;
+ while (child){
+ t = gcompris_alphabeta (!maximize,
+ child,
+ heuristic,
+ &nextBest,
+ firstChild,
+ nextSibling,
+ alpha,
+ m,
+ depth - 1
+ );
+ if (t < m){
+ m = t;
+ *bestChild = index;
+ }
+ if ( m <= alpha){
+/* g_warning("gcompris_alphabeta %d returns %d bestChild %d", depth, heuristic(treeGame), *bestChild); */
+ return m;
+ }
+ index++;
+ child = nextSibling(child);
+ }
+/* g_warning("gcompris_alphabeta %d returns %d bestChild %d", depth, heuristic(treeGame), *bestChild); */
+ return m;
+
+ }
+
+}
+
+
+
+/* Local Variables: */
+/* mode:c */
+/* eval:(load-library "time-stamp") */
+/* eval:(make-local-variable 'write-file-hooks) */
+/* eval:(add-hook 'write-file-hooks 'time-stamp) */
+/* eval:(setq time-stamp-format '(time-stamp-yyyy/mm/dd time-stamp-hh:mm:ss user-login-name)) */
+/* End: */
diff --git a/src/gcompris/gcompris_alphabeta.h b/src/gcompris/gcompris_alphabeta.h
new file mode 100644
index 0000000..486f3fd
--- /dev/null
+++ b/src/gcompris/gcompris_alphabeta.h
@@ -0,0 +1,62 @@
+/* gcompris - gcompris_alphabeta.h
+ *
+ * Time-stamp: <2006/02/05 09:27:20 yves>
+ *
+ * Copyright (C) 2000 Bruno Coudoin
+ *
+ * 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 should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _GOMPRIS_ALPHABETA_H_
+#define _GOMPRIS_ALPHABETA_H_
+
+#include "gcompris.h"
+
+/* gcompris_alphabeta returns the best value of evaluation functions */
+/* set the bestChild to the index of child with this value */
+/* maximize : TRUE if depth is maximize one, neither FALSE. */
+/* treeGame : pointer on game to pass to others functions, */
+/* bestChild : pointer on GList wich will contains list of indexes fo best plays. */
+/* isLeaf : TRUE if game correspond to a Leaf of Tree. */
+/* firstChild : return pointer on first child of a node. */
+/* nextSibling : return pointer on next sibling of a node. */
+/* heuristic : evaluation function of game. */
+/* depth is max depth of recursion */
+
+typedef gint (*EvalFunction) (gpointer treeGame);
+typedef gboolean (*LeafFunction) (gpointer treeGame);
+typedef gpointer (*FirstChildGameFunction) (gpointer treeGame);
+typedef gpointer (*NextSiblingGameFunction) (gpointer treeGame);
+
+gint gcompris_alphabeta (gboolean maximize,
+ gpointer treeGame,
+ EvalFunction heuristic,
+ gint *bestChild,
+ FirstChildGameFunction firstChild,
+ NextSiblingGameFunction nextSibling,
+ gint alpha,
+ gint beta,
+ gint depth
+ );
+
+#endif
+
+/* Local Variables: */
+/* mode:c */
+/* eval:(load-library "time-stamp") */
+/* eval:(make-local-variable 'write-file-hooks) */
+/* eval:(add-hook 'write-file-hooks 'time-stamp) */
+/* eval:(setq time-stamp-format '(time-stamp-yyyy/mm/dd time-stamp-hh:mm:ss user-login-name)) */
+/* End: */
diff --git a/src/gcompris/gcompris_confirm.c b/src/gcompris/gcompris_confirm.c
new file mode 100644
index 0000000..8ebe684
--- /dev/null
+++ b/src/gcompris/gcompris_confirm.c
@@ -0,0 +1,491 @@
+/* gcompris - gcompris_confirm.c
+ *
+ * Time-stamp: <2006/01/29 16:06:02 bruno>
+ *
+ * Copyright (C) 2000 Bruno Coudoin
+ *
+ * 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 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
+ */
+#include <string.h>
+
+/**
+ * A confirmation popup for gcompris
+ *
+ */
+#include "gcompris.h"
+
+static void display_confirm(gchar *title,
+ gchar *question_text,
+ gchar *yes_text,
+ gchar *no_text,
+ ConfirmCallBack iscb);
+
+static gint
+button_event(GnomeCanvasItem *item, GdkEvent *event, gchar *answer);
+
+static void set_content(GnomeCanvasRichText *item_content,
+ GnomeCanvasRichText *item_content_s,
+ gchar *text);
+
+static gboolean confirm_displayed = FALSE;
+
+static GnomeCanvasItem *rootitem = NULL;
+static GnomeCanvasItem *no_button = NULL;
+static GnomeCanvasItem *yes_button = NULL;
+static GnomeCanvasItem *yes_stick = NULL;
+static GnomeCanvasItem *no_cross = NULL;
+
+static ConfirmCallBack confirmCallBack = NULL;
+
+static gdouble bg_x;
+static gdouble bg_y;
+
+static gdouble titre_x;
+static gdouble titre_w;
+static gdouble titre_y;
+static gdouble titre_h;
+
+
+static gdouble text_zone_x;
+static gdouble text_zone_w;
+static gdouble text_zone_y;
+static gdouble text_zone_h;
+
+
+static gdouble button_x;
+static gdouble button_w;
+static gdouble button_y;
+static gdouble button_h;
+static gdouble button_x_int;
+
+/* background */
+#define BG_X 400
+#define BG_Y 0
+
+/* TITLE */
+#define T_X 80
+#define T_Y 24
+#define T_W 620
+#define T_H 30
+
+/* Text */
+#define T_Z_X 80
+#define T_Z_Y 120
+#define T_Z_W 620
+#define T_Z_H 115
+
+/* Buttons */
+#define T_B_X 80
+#define T_B_Y 250
+#define T_B_W 620
+#define T_B_H 192
+#define T_B_X_INT 30
+
+
+/*
+ * Main entry point
+ * ----------------
+ *
+ */
+
+/*
+ * Do all the file_selector display and register the events
+ * file_types is A Comma separated text explaining the different file types
+ */
+
+void gcompris_confirm (gchar *title,
+ gchar *question_text,
+ gchar *yes_text,
+ gchar *no_text,
+ ConfirmCallBack iscb)
+{
+ display_confirm(title,
+ question_text,
+ yes_text,
+ no_text,
+ iscb);
+}
+
+/*
+ * Remove the displayed file_selector.
+ * Do nothing if none is currently being dislayed
+ */
+
+void gcompris_confirm_stop ()
+{
+ GcomprisBoard *gcomprisBoard = get_current_gcompris_board();
+
+ // Destroy the box
+ /* FIXME: Crashes randomly */
+ if(rootitem!=NULL)
+ gtk_object_destroy(GTK_OBJECT(rootitem));
+
+ rootitem = NULL;
+
+ if(gcomprisBoard!=NULL && confirm_displayed)
+ {
+ if(gcomprisBoard->plugin->pause_board != NULL)
+ {
+ gcomprisBoard->plugin->pause_board(FALSE);
+ }
+ }
+
+ gcompris_bar_hide(FALSE);
+ confirm_displayed = FALSE;
+}
+
+
+
+/*-------------------------------------------------------------------------------*/
+/*-------------------------------------------------------------------------------*/
+/*-------------------------------------------------------------------------------*/
+/*-------------------------------------------------------------------------------*/
+
+
+static void
+display_confirm(gchar *title,
+ gchar *question_text,
+ gchar *yes_text,
+ gchar *no_text,
+ ConfirmCallBack iscb) {
+
+ GcomprisBoard *gcomprisBoard = get_current_gcompris_board();
+
+
+ GnomeCanvasItem *item, *item2, *richtext_s, *richtext;
+ GdkPixbuf *pixmap = NULL;
+ GdkPixbuf *pixmap_cross = NULL;
+ GdkPixbuf *pixmap_stick = NULL;
+ gint y_start = 0;
+ gint x_start = 0;
+
+ if(rootitem)
+ return;
+
+ bg_x = BG_X;
+ bg_y = BG_Y;
+
+ titre_x = T_X;
+ titre_w = T_W;
+ titre_y = T_Y;;
+ titre_h = T_H;
+
+
+ text_zone_x = T_Z_X;
+ text_zone_w = T_Z_W;
+ text_zone_y = T_Z_Y;
+ text_zone_h = T_Z_H;
+
+
+ button_x = T_B_X;
+ button_w = T_B_W;
+ button_y = T_B_Y;
+ button_h = T_B_Y;
+ button_x_int = T_B_X_INT;
+
+ gcompris_bar_hide(TRUE);
+
+ if(gcomprisBoard!=NULL)
+ {
+ if(gcomprisBoard->plugin->pause_board != NULL)
+ gcomprisBoard->plugin->pause_board(TRUE);
+ }
+
+ confirmCallBack=iscb;
+
+ rootitem = \
+ gnome_canvas_item_new (gnome_canvas_root(gcompris_get_canvas()),
+ gnome_canvas_group_get_type (),
+ "x", (double)0,
+ "y", (double)0,
+ NULL);
+
+ pixmap = gcompris_load_skin_pixmap("help_bg.png");
+ y_start = (BOARDHEIGHT - gdk_pixbuf_get_height(pixmap))/2;
+ if (y_start < 0)
+ y_start = 0;
+ x_start = (BOARDWIDTH)/2;
+ item = gnome_canvas_item_new (GNOME_CANVAS_GROUP(rootitem),
+ gnome_canvas_pixbuf_get_type (),
+ "pixbuf", pixmap,
+ "x", (double) x_start,
+ "y", (double) y_start,
+ "anchor", GTK_ANCHOR_NORTH,
+ NULL);
+
+ gdk_pixbuf_unref(pixmap);
+
+ /* Title */
+ gnome_canvas_item_new (GNOME_CANVAS_GROUP(rootitem),
+ gnome_canvas_text_get_type (),
+ "text", title,
+ "x", (gdouble) titre_x + titre_w/2 + 1.0,
+ "y", (gdouble) titre_y + titre_h/2 + 1.0,
+ "font", gcompris_skin_font_title,
+ "anchor", GTK_ANCHOR_CENTER,
+ "fill_color_rgba", gcompris_skin_color_shadow,
+ NULL);
+
+ gnome_canvas_item_new (GNOME_CANVAS_GROUP(rootitem),
+ gnome_canvas_text_get_type (),
+ "text", title,
+ "x", (gdouble) titre_x + titre_w/2,
+ "y", (gdouble) titre_y + titre_h/2,
+ "font", gcompris_skin_font_title,
+ "anchor", GTK_ANCHOR_CENTER,
+ "fill_color_rgba", gcompris_skin_color_title,
+ NULL);
+
+ richtext_s = gnome_canvas_item_new (GNOME_CANVAS_GROUP(rootitem),
+ gnome_canvas_rich_text_get_type (),
+ "x", (double) text_zone_x + 1.0,
+ "y", (double) text_zone_y + 1.0,
+ "width", text_zone_w,
+ "height", text_zone_h,
+ "anchor", GTK_ANCHOR_NW,
+ "justification", GTK_JUSTIFY_CENTER,
+ "grow_height", FALSE,
+ "cursor_visible", FALSE,
+ "cursor_blink", FALSE,
+ "editable", FALSE,
+ NULL);
+
+
+ richtext = gnome_canvas_item_new (GNOME_CANVAS_GROUP(rootitem),
+ gnome_canvas_rich_text_get_type (),
+ "x", (double) text_zone_x ,
+ "y", (double) text_zone_y,
+ "width", text_zone_w,
+ "height", text_zone_h,
+ "anchor", GTK_ANCHOR_NW,
+ "justification", GTK_JUSTIFY_CENTER,
+ "grow_height", FALSE,
+ "cursor_visible", FALSE,
+ "cursor_blink", FALSE,
+ "editable", FALSE,
+ NULL);
+
+ set_content (GNOME_CANVAS_RICH_TEXT(richtext),
+ GNOME_CANVAS_RICH_TEXT(richtext_s),
+ question_text);
+
+
+ /*
+ * Buttons
+ * -------
+ */
+
+ pixmap = gcompris_load_skin_pixmap("button_large.png");
+ pixmap_stick = gcompris_load_skin_pixmap("button_checked.png");
+ pixmap_cross = gcompris_load_skin_pixmap("bad.png");
+
+ // CANCEL
+ no_button = gnome_canvas_item_new (GNOME_CANVAS_GROUP(rootitem),
+ gnome_canvas_pixbuf_get_type (),
+ "pixbuf", pixmap,
+ "x", (double) button_x ,
+ "y", (double) button_y + 2*button_h/3,
+ "anchor", GTK_ANCHOR_WEST,
+ NULL);
+
+ //gdk_pixbuf_unref(pixmap);
+
+ gtk_signal_connect(GTK_OBJECT(no_button), "event",
+ (GtkSignalFunc) button_event,
+ "/no/");
+
+ gtk_signal_connect(GTK_OBJECT(no_button), "event",
+ (GtkSignalFunc) gcompris_item_event_focus,
+ NULL);
+
+ // CANCEL CROSS
+ no_cross = gnome_canvas_item_new (GNOME_CANVAS_GROUP(rootitem),
+ gnome_canvas_pixbuf_get_type (),
+ "pixbuf", pixmap_cross,
+ "x", (double) button_x + gdk_pixbuf_get_width(pixmap)/2,
+ "y", (double) button_y + 2*button_h/3,
+ "anchor", GTK_ANCHOR_CENTER,
+ NULL);
+
+ gdk_pixbuf_unref(pixmap_cross);
+
+ gtk_signal_connect(GTK_OBJECT(no_cross), "event",
+ (GtkSignalFunc) button_event,
+ "/no/");
+ gtk_signal_connect(GTK_OBJECT(no_cross), "event",
+ (GtkSignalFunc) gcompris_item_event_focus,
+ NULL);
+
+
+ gnome_canvas_item_new (GNOME_CANVAS_GROUP(rootitem),
+ gnome_canvas_text_get_type (),
+ "text", no_text,
+ "font", gcompris_skin_font_title,
+ "x", (double) button_x + gdk_pixbuf_get_width(pixmap) + button_x_int ,
+ "y", (double) button_y + 2*button_h/3,
+ "anchor", GTK_ANCHOR_WEST,
+ "fill_color_rgba", gcompris_skin_color_text_button,
+ NULL);
+
+ // OK
+ yes_button = gnome_canvas_item_new (GNOME_CANVAS_GROUP(rootitem),
+ gnome_canvas_pixbuf_get_type (),
+ "pixbuf", pixmap,
+ "x", (double) button_x ,
+ "y", (double) button_y + button_h/3,
+ "anchor", GTK_ANCHOR_WEST,
+ NULL);
+
+ gdk_pixbuf_unref(pixmap);
+
+ gtk_signal_connect(GTK_OBJECT(yes_button), "event",
+ (GtkSignalFunc) button_event,
+ "/yes/");
+
+ gtk_signal_connect(GTK_OBJECT(yes_button), "event",
+ (GtkSignalFunc) gcompris_item_event_focus,
+ NULL);
+
+ // OK stick
+ yes_stick = gnome_canvas_item_new (GNOME_CANVAS_GROUP(rootitem),
+ gnome_canvas_pixbuf_get_type (),
+ "pixbuf", pixmap_stick,
+ "x", (double) button_x + gdk_pixbuf_get_width(pixmap)/2,
+ "y", (double) button_y + button_h/3,
+ "anchor", GTK_ANCHOR_CENTER,
+ NULL);
+
+ gdk_pixbuf_unref(pixmap_stick);
+
+ gtk_signal_connect(GTK_OBJECT(yes_stick), "event",
+ (GtkSignalFunc) button_event,
+ "/yes/");
+ gtk_signal_connect(GTK_OBJECT(yes_stick), "event",
+ (GtkSignalFunc) gcompris_item_event_focus,
+ NULL);
+
+
+ item2 = gnome_canvas_item_new (GNOME_CANVAS_GROUP(rootitem),
+ gnome_canvas_text_get_type (),
+ "text", yes_text,
+ "font", gcompris_skin_font_title,
+ "x", (double) button_x + gdk_pixbuf_get_width(pixmap) + button_x_int ,
+ "y", (double) button_y + button_h/3,
+ "anchor", GTK_ANCHOR_WEST,
+ "fill_color_rgba", gcompris_skin_color_text_button,
+ NULL);
+
+ confirm_displayed = TRUE;
+
+}
+
+static void
+free_stuff (GtkObject *obj, gchar *data)
+{
+ g_free(data);
+}
+
+/* Apply the style to the given RichText item */
+static void
+set_content(GnomeCanvasRichText *item_content,
+ GnomeCanvasRichText *item_content_s,
+ gchar *text) {
+
+ GtkTextIter iter_start, iter_end;
+ GtkTextBuffer *buffer;
+ GtkTextTag *txt_tag;
+ gboolean success;
+ gchar *color_string;
+ GdkColor *color_s = (GdkColor *)malloc(sizeof(GdkColor));
+ GdkColor *color = (GdkColor *)malloc(sizeof(GdkColor));
+
+ /*
+ * Set the new text in the 2 items
+ */
+ gnome_canvas_item_set(GNOME_CANVAS_ITEM(item_content),
+ "text", text,
+ NULL);
+
+ gnome_canvas_item_set(GNOME_CANVAS_ITEM(item_content_s),
+ "text", text,
+ NULL);
+
+ /*
+ * Set the shadow
+ */
+
+ color_string = g_strdup_printf("#%x", gcompris_skin_color_shadow >> 8);
+ gdk_color_parse(color_string, color_s);
+ success = gdk_colormap_alloc_color(gdk_colormap_get_system(),
+ color_s,
+ FALSE, TRUE);
+
+ buffer = gnome_canvas_rich_text_get_buffer(GNOME_CANVAS_RICH_TEXT(item_content_s));
+ txt_tag = gtk_text_buffer_create_tag(buffer, NULL,
+ "foreground-gdk", color_s,
+ "font", gcompris_skin_font_board_medium,
+ NULL);
+ gtk_text_buffer_get_end_iter(buffer, &iter_end);
+ gtk_text_buffer_get_start_iter(buffer, &iter_start);
+ gtk_text_buffer_apply_tag(buffer, txt_tag, &iter_start, &iter_end);
+
+ g_free(color_string);
+
+ /*
+ * Set the text
+ */
+ color_string = g_strdup_printf("#%x", gcompris_skin_get_color("menu/text") >> 8);
+ gdk_color_parse(color_string, color);
+ success = gdk_colormap_alloc_color(gdk_colormap_get_system(),
+ color,
+ FALSE, TRUE);
+
+ buffer = gnome_canvas_rich_text_get_buffer(GNOME_CANVAS_RICH_TEXT(item_content));
+ txt_tag = gtk_text_buffer_create_tag(buffer, NULL,
+ "foreground-gdk", color,
+ "font", gcompris_skin_font_board_medium,
+ NULL);
+ gtk_text_buffer_get_end_iter(buffer, &iter_end);
+ gtk_text_buffer_get_start_iter(buffer, &iter_start);
+ gtk_text_buffer_apply_tag(buffer, txt_tag, &iter_start, &iter_end);
+
+}
+
+static gint
+button_event(GnomeCanvasItem *item, GdkEvent *event, gchar *answer)
+{
+ if (event->type != GDK_BUTTON_PRESS)
+ return FALSE;
+
+ /* Callback with the proper params */
+ if (confirmCallBack){
+ if (strcmp(answer, "/no/")==0)
+ confirmCallBack(FALSE);
+ else
+ confirmCallBack(TRUE);
+ }
+ gcompris_confirm_stop();
+
+ return TRUE;
+
+}
+
+/* Local Variables: */
+/* mode:c */
+/* eval:(load-library "time-stamp") */
+/* eval:(make-local-variable 'write-file-hooks) */
+/* eval:(add-hook 'write-file-hooks 'time-stamp) */
+/* eval:(setq time-stamp-format '(time-stamp-yyyy/mm/dd time-stamp-hh:mm:ss user-login-name)) */
+/* End: */
diff --git a/src/gcompris/properties.c b/src/gcompris/properties.c
index dc1eb60..de318eb 100644
--- a/src/gcompris/properties.c
+++ b/src/gcompris/properties.c
@@ -1,6 +1,6 @@
/* gcompris - properties.c
*
- * Time-stamp: <2006/01/18 15:11:03 yves>
+ * Time-stamp: <2006/01/21 20:50:15 yves>
*
* Copyright (C) 2000,2003 Bruno Coudoin
*
@@ -177,6 +177,7 @@ GcomprisProperties *gcompris_properties_new ()
tmp->administration = FALSE;
tmp->reread_menu = FALSE;
tmp->experimental = FALSE;
+ tmp->menu_position = NULL;
gcompris_user_dir = get_gcompris_user_root_directory() ;
create_rootdir( gcompris_user_dir );
diff --git a/src/gcompris/properties.h b/src/gcompris/properties.h
index a04b102..a422b0a 100644
--- a/src/gcompris/properties.h
+++ b/src/gcompris/properties.h
@@ -1,6 +1,6 @@
/* gcompris - properties.h
*
- * Time-stamp: <2006/01/18 15:07:00 yves>
+ * Time-stamp: <2006/01/21 20:49:43 yves>
*
* Copyright (C) 2000 Bruno Coudoin
*
@@ -55,6 +55,7 @@ typedef struct {
GtkIMContext *context;
gchar *default_context;
gint experimental;
+ gchar *menu_position;
} GcomprisProperties;
GcomprisProperties *gcompris_get_properties (void);
diff --git a/tools/list_missing_sounds.sh b/tools/list_missing_sounds.sh
new file mode 100755
index 0000000..411ea0c
--- /dev/null
+++ b/tools/list_missing_sounds.sh
@@ -0,0 +1,45 @@
+#!/bin/sh
+#
+# Copyright (C) 2006 Jose JORGE
+#
+# 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 should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+#######################################################################
+#
+# This script lists the sounds missing in some locale compared to english
+# It much be run with the list of locale sound you want to compare
+# list_missing_sounds fr en de
+#
+snd_path="boards/sounds/"
+reference="en"
+
+if test "$1" == ""
+then
+ echo "Usage: $0 <locale>"
+ echo "With locale being a locale as found in boards/sounds like fr"
+ echo "Run it in the GCompris root directory"
+ exit 1
+fi
+
+for locale in $@
+do
+ if test -d boards/sounds/$locale; then
+ find $snd_path$locale | grep .ogg > ~/tmp/sounds_$locale.lst
+ find $snd_path$reference | grep .ogg | sed s+/$reference/+/$locale/+ > ~/tmp/sounds_$reference.lst
+ echo "The sounds avaliable in $reference that miss in $locale are :"
+ grep -v -f ~/tmp/sounds_$locale.lst ~/tmp/sounds_$reference.lst
+ fi
+done
+rm ~/tmp/sounds_$locale.lst ~/tmp/sounds_$reference.lst
diff --git a/tools/shapegame/HOWTO b/tools/shapegame/HOWTO
new file mode 100644
index 0000000..d2c8bbe
--- /dev/null
+++ b/tools/shapegame/HOWTO
@@ -0,0 +1,114 @@
+#
+# creating region puzzle for germany
+#
+#
+# 1. got map from wikipedia ->
+# source/Deutschland_Bundeslaender_1990_thresshold.tif
+#
+# 2. used gimp to extract individual regions by filling all others with
+# white and save them as "bayern.png" etc. The size of each
+# indivudual image must be the same as the full image
+#
+# 3. create the background image by filling the separation lines and
+# store it as Deutschland_komplett.png
+#
+# 4. Now crop away borders and compute the coordiantes for the puzzle
+# pieces, using pnmcrop from "netpbm" package, and the compute the
+# target spots with the distance transform, based on the great
+# algorithm and source code from Pedro F. Felzenszwalb and Daniel
+# P. Huttenlocher, see http://people.cs.uchicago.edu/~pff/dt/
+#
+cd ~/gcompris_dev/gcompris/boards/geography/germany_region/source2
+rm -f coordinates.txt
+for i in baden-wuerttemberg.png bayern.png berlin.png brandenburg.png bremen.png hamburg.png hessen.png mecklenburg-vorpommern.png niedersachsen.png nordrhein-westfalen.png rheinland-pfalz.png saarland.png sachsen-anhalt.png sachsen.png schleswig_holstein.png thueringen.png; do
+ echo filename: $i >> coordinates.txt
+ pngtopnm $i |pnmscale 0.8| pnmcrop --white --verbose 2>> coordinates.txt | pnmtopng -transparent white > ../$i
+ echo shape: `pngtopnm ../$i | head -2 | tail -1` >> coordinates.txt
+ pngtopnm ../$i | ppmtopgm | pgmtopbm -threshold -value 0.9 | pnminvert > binmask.pbm
+ ~/gcompris_dev/gcompris/tool/shapegame/nice_target_spot binmask.pbm target.ppm
+ pnmtopng -transparent white target.ppm > ../target_$i
+done
+
+#
+# simulate output from pnmcrop for background-image
+#
+
+pngtopnm Deutschland_komplett.png |pnmscale 0.8| pnmtopng -transparent white > ../back.png
+echo filename: back.png >> coordinates.txt
+echo pnmcrop: cropping 0 rows off the top >> coordinates.txt
+echo pnmcrop: cropping 0 cols off the left >> coordinates.txt
+echo shape: `pngtopnm ../back.png | head -2 | tail -1` >> coordinates.txt
+
+#
+# 5. Now create the xml-file board6_0.xml.in from created
+# source2/coordinates.txt
+#
+cd ~/gcompris_dev/gcompris/boards/geography/germany_region/source2
+
+cat > realnames.txt <<EOF
+Baden-Württemberg
+Bayern
+Berlin
+Brandenburg
+Bremen
+Hamburg
+Hessen
+Mecklenburg-Vorpommern
+Niedersachsen
+Nordrhein-Westfalen
+Rheinland-Pfalz
+Saarland
+Sachsen-Anhalt
+Sachsen
+Schleswig-Holstein
+Thüringen
+EOF
+
+
+grep "filename:" coordinates.txt | awk '{print $2}' > filenames.txt
+grep "off the left" coordinates.txt | awk '{print $3}' > coords_x.txt
+grep "off the top" coordinates.txt | awk '{print $3}' > coords_y.txt
+grep "shape:" coordinates.txt | awk '{print $2, $3}' > shape.txt
+
+paste filenames.txt coords_x.txt coords_y.txt shape.txt realnames.txt> hurz.txt
+
+echo '<?xml version="1.0" encoding="UTF-8"?>
+<ShapeGame>
+ <Title x="600" y="495" justification="GTK_JUSTIFY_CENTER">
+ <_name>Deutschland Bundesländer</_name>
+ </Title>' > board6_0.xml.in
+
+awk '{
+if($1 != "back.png")
+{
+ print " <Shape name=\"A"NR"\" pixmapfile=\"geography/germany_region/"$1"\" targetfile=\"geography/germany_region/target_"$1"\" x=\""$2+100+$4/2"\" y=\""$3+$5/2"\" zoomx=\"1\" zoomy=\"1\" position=\"0\"><_tooltip>"$6"</_tooltip></Shape>";
+}
+else
+{
+ print " <Shape name=\"1\" pixmapfile=\"geography/germany_region/"$1"\" type=\"SHAPE_BACKGROUND\" x=\""$2+100+$4/2"\" y=\""$3+$5/2"\" zoomx=\"1\" zoomy=\"1\" position=\"0\"/>";
+}
+}' < hurz.txt >> board6_0.xml.in
+
+echo '</ShapeGame>' >> board6_0.xml.in
+
+cp -f board6_0.xml.in ../../board6_0.xml.in
+
+
+#
+# edit gcompris/boards/geography/Makefile.am to include board6_0.xml.in
+#
+
+cd ~/gcompris_dev/gcompris
+intltoolize && automake && autoconf && ./configure --prefix $PWD
+
+cd ~/gcompris_dev/gcompris
+make install
+
+~/gcompris_dev/gcompris/bin/gcompris
+
+
+#
+# Create the distribution for Bruno
+#
+cd ~/gcompris_dev/
+tar -zcvf germany_regions_2006_01_29.tar.gz gcompris/tool/ gcompris/boards/geography/germany_region/ gcompris/boards/geography/Makefile.am
diff --git a/tools/shapegame/Makefile b/tools/shapegame/Makefile
new file mode 100644
index 0000000..2fcc763
--- /dev/null
+++ b/tools/shapegame/Makefile
@@ -0,0 +1,2 @@
+
+all: nice_target_spot
diff --git a/tools/shapegame/dt/.cvsignore b/tools/shapegame/dt/.cvsignore
new file mode 100644
index 0000000..a33a4d7
--- /dev/null
+++ b/tools/shapegame/dt/.cvsignore
@@ -0,0 +1 @@
+dt
diff --git a/tools/shapegame/dt/Makefile b/tools/shapegame/dt/Makefile
new file mode 100644
index 0000000..91ea042
--- /dev/null
+++ b/tools/shapegame/dt/Makefile
@@ -0,0 +1,23 @@
+INCDIR = -I.
+DBG = -g
+OPT = -O3
+CPP = g++
+CFLAGS = $(DBG) $(OPT) $(INCDIR)
+LINK = -lm
+
+.cpp.o:
+ $(CPP) $(CFLAGS) -c $< -o $@
+
+all: dt
+
+dt: dt.cpp
+ $(CPP) $(CFLAGS) -o dt dt.cpp $(LINK)
+
+clean:
+ /bin/rm -f dt *.o
+
+clean-all: clean
+ /bin/rm -f *~
+
+
+
diff --git a/tools/shapegame/dt/README b/tools/shapegame/dt/README
new file mode 100644
index 0000000..ddf45c3
--- /dev/null
+++ b/tools/shapegame/dt/README
@@ -0,0 +1,34 @@
+Implementation of the distance transform algorithm described in:
+
+Distance Transforms of Sampled Functions
+Pedro F. Felzenszwalb and Daniel P. Huttenlocher
+Cornell Computing and Information Science TR2004-1963
+http://people.cs.uchicago.edu/~pff/dt/
+
+The main program "dt.cpp" computes the standard distance transform of
+a binary image. The algorithm for computing the transform of a
+sampled function is in "dt.h".
+
+1) Type make to compile "dt".
+
+2) Run "./dt input.pbm output.pgm" to compute the distance transform
+of a binary image. The input is a binary PBM image and the output is
+a grayscale PGM image. Note that the actual distance values are
+scaled to fit in the [0-255] grayscale range.
+
+The code in this directory is Copyrighted by Pedro Felzenszwalb and is
+released under GPL:
+
+ Betreff: Re: Gnu public license for your distance transform code?
+ Datum: Sun, 29 Jan 2006 19:20:05 -0600
+ Von: Pedro Felzenszwalb <pff@cs.uchicago.edu>
+ An: Olaf Ronneberger <Olaf@Ronneberger.net>
+ Referenzen: <43DD45AB.1060706@Ronneberger.net>
+
+ Dear Olaf,
+
+ I am glad to hear the code is being used in your software and I am
+ happy to release it under the GPL.
+ Do you need me to send you anything in particular?
+
+ Pedro
diff --git a/tools/shapegame/dt/dt.cpp b/tools/shapegame/dt/dt.cpp
new file mode 100644
index 0000000..214b14d
--- /dev/null
+++ b/tools/shapegame/dt/dt.cpp
@@ -0,0 +1,58 @@
+/* dt - dt.cpp
+ *
+ * Copyright (C) 2006 Pedro Felzenszwalb
+ *
+ * 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 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
+ */
+
+#include <cstdio>
+#include <cstdlib>
+#include <cmath>
+#include "pnmfile.h"
+#include "imconv.h"
+#include "dt.h"
+
+int main(int argc, char **argv) {
+ if (argc != 3) {
+ fprintf(stderr, "usage: %s input(pbm) output(pgm)\n", argv[0]);
+ return 1;
+ }
+
+ char *input_name = argv[1];
+ char *output_name = argv[2];
+
+ // load input
+ image<uchar> *input = loadPBM(input_name);
+
+ // compute dt
+ image<float> *out = dt(input);
+
+ // take square roots
+ for (int y = 0; y < out->height(); y++) {
+ for (int x = 0; x < out->width(); x++) {
+ imRef(out, x, y) = sqrt(imRef(out, x, y));
+ }
+ }
+
+ // convert to grayscale
+ image<uchar> *gray = imageFLOATtoUCHAR(out);
+
+ // save output
+ savePGM(gray, output_name);
+
+ delete input;
+ delete out;
+ delete gray;
+}
diff --git a/tools/shapegame/dt/dt.h b/tools/shapegame/dt/dt.h
new file mode 100644
index 0000000..efe557e
--- /dev/null
+++ b/tools/shapegame/dt/dt.h
@@ -0,0 +1,115 @@
+/* dt - dt.h
+ *
+ * Copyright (C) 2006 Pedro Felzenszwalb
+ *
+ * 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 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
+ */
+/* distance transform */
+
+#ifndef DT_H
+#define DT_H
+
+#include <algorithm>
+#include "image.h"
+
+#define INF 1E20
+
+/* dt of 1d function using squared distance */
+static float *dt(float *f, int n) {
+ float *d = new float[n];
+ int *v = new int[n];
+ float *z = new float[n+1];
+ int k = 0;
+ v[0] = 0;
+ z[0] = -INF;
+ z[1] = +INF;
+ for (int q = 1; q <= n-1; q++) {
+ float s = ((f[q]+square(q))-(f[v[k]]+square(v[k])))/(2*q-2*v[k]);
+ while (s <= z[k]) {
+ k--;
+ s = ((f[q]+square(q))-(f[v[k]]+square(v[k])))/(2*q-2*v[k]);
+ }
+ k++;
+ v[k] = q;
+ z[k] = s;
+ z[k+1] = +INF;
+ }
+
+ k = 0;
+ for (int q = 0; q <= n-1; q++) {
+ while (z[k+1] < q)
+ k++;
+ d[q] = square(q-v[k]) + f[v[k]];
+ }
+
+ delete [] v;
+ delete [] z;
+ return d;
+}
+
+/* dt of 2d function using squared distance */
+static void dt(image<float> *im) {
+ int width = im->width();
+ int height = im->height();
+ float *f = new float[std::max(width,height)];
+
+ // transform along columns
+ for (int x = 0; x < width; x++) {
+ for (int y = 0; y < height; y++) {
+ f[y] = imRef(im, x, y);
+ }
+ float *d = dt(f, height);
+ for (int y = 0; y < height; y++) {
+ imRef(im, x, y) = d[y];
+ }
+ delete [] d;
+ }
+
+ // transform along rows
+ for (int y = 0; y < height; y++) {
+ for (int x = 0; x < width; x++) {
+ f[x] = imRef(im, x, y);
+ }
+ float *d = dt(f, width);
+ for (int x = 0; x < width; x++) {
+ imRef(im, x, y) = d[x];
+ }
+ delete [] d;
+ }
+
+ delete f;
+}
+
+
+/* dt of binary image using squared distance */
+static image<float> *dt(image<uchar> *im, uchar on = 1) {
+ int width = im->width();
+ int height = im->height();
+
+ image<float> *out = new image<float>(width, height, false);
+ for (int y = 0; y < height; y++) {
+ for (int x = 0; x < width; x++) {
+ if (imRef(im, x, y) == on)
+ imRef(out, x, y) = 0;
+ else
+ imRef(out, x, y) = INF;
+ }
+ }
+
+ dt(out);
+ return out;
+}
+
+#endif
diff --git a/tools/shapegame/dt/image.h b/tools/shapegame/dt/image.h
new file mode 100644
index 0000000..4f385dc
--- /dev/null
+++ b/tools/shapegame/dt/image.h
@@ -0,0 +1,101 @@
+/* dt - image.h
+ *
+ * Copyright (C) 2006 Pedro Felzenszwalb
+ *
+ * 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 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
+ */
+/* a simple image class */
+
+#ifndef IMAGE_H
+#define IMAGE_H
+
+#include <cstring>
+
+template <class T>
+class image {
+ public:
+ /* create an image */
+ image(const int width, const int height, const bool init = true);
+
+ /* delete an image */
+ ~image();
+
+ /* init an image */
+ void init(const T &val);
+
+ /* copy an image */
+ image<T> *copy() const;
+
+ /* get the width of an image. */
+ int width() const { return w; }
+
+ /* get the height of an image. */
+ int height() const { return h; }
+
+ /* image data. */
+ T *data;
+
+ /* row pointers. */
+ T **access;
+
+ private:
+ int w, h;
+};
+
+/* use imRef to access image data. */
+#define imRef(im, x, y) (im->access[y][x])
+
+/* use imPtr to get pointer to image data. */
+#define imPtr(im, x, y) &(im->access[y][x])
+
+template <class T>
+image<T>::image(const int width, const int height, const bool init) {
+ w = width;
+ h = height;
+ data = new T[w * h]; // allocate space for image data
+ access = new T*[h]; // allocate space for row pointers
+
+ // initialize row pointers
+ for (int i = 0; i < h; i++)
+ access[i] = data + (i * w);
+
+ if (init)
+ memset(data, 0, w * h * sizeof(T));
+}
+
+template <class T>
+image<T>::~image() {
+ delete [] data;
+ delete [] access;
+}
+
+template <class T>
+void image<T>::init(const T &val) {
+ T *ptr = imPtr(this, 0, 0);
+ T *end = imPtr(this, w-1, h-1);
+ while (ptr <= end)
+ *ptr++ = val;
+}
+
+
+template <class T>
+image<T> *image<T>::copy() const {
+ image<T> *im = new image<T>(w, h, false);
+ memcpy(im->data, data, w * h * sizeof(T));
+ return im;
+}
+
+#endif
+
diff --git a/tools/shapegame/dt/imconv.h b/tools/shapegame/dt/imconv.h
new file mode 100644
index 0000000..2ecbd0b
--- /dev/null
+++ b/tools/shapegame/dt/imconv.h
@@ -0,0 +1,177 @@
+/* dt - imconv.h
+ *
+ * Copyright (C) 2006 Pedro Felzenszwalb
+ *
+ * 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 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
+ */
+/* image conversion */
+
+#ifndef CONV_H
+#define CONV_H
+
+#include <climits>
+#include "image.h"
+#include "imutil.h"
+#include "misc.h"
+
+#define RED_WEIGHT 0.299
+#define GREEN_WEIGHT 0.587
+#define BLUE_WEIGHT 0.114
+
+static image<uchar> *imageRGBtoGRAY(image<rgb> *input) {
+ int width = input->width();
+ int height = input->height();
+ image<uchar> *output = new image<uchar>(width, height, false);
+
+ for (int y = 0; y < height; y++) {
+ for (int x = 0; x < width; x++) {
+ imRef(output, x, y) = (uchar)
+ (imRef(input, x, y).r * RED_WEIGHT +
+ imRef(input, x, y).g * GREEN_WEIGHT +
+ imRef(input, x, y).b * BLUE_WEIGHT);
+ }
+ }
+ return output;
+}
+
+static image<rgb> *imageGRAYtoRGB(image<uchar> *input) {
+ int width = input->width();
+ int height = input->height();
+ image<rgb> *output = new image<rgb>(width, height, false);
+
+ for (int y = 0; y < height; y++) {
+ for (int x = 0; x < width; x++) {
+ imRef(output, x, y).r = imRef(input, x, y);
+ imRef(output, x, y).g = imRef(input, x, y);
+ imRef(output, x, y).b = imRef(input, x, y);
+ }
+ }
+ return output;
+}
+
+static image<float> *imageUCHARtoFLOAT(image<uchar> *input) {
+ int width = input->width();
+ int height = input->height();
+ image<float> *output = new image<float>(width, height, false);
+
+ for (int y = 0; y < height; y++) {
+ for (int x = 0; x < width; x++) {
+ imRef(output, x, y) = imRef(input, x, y);
+ }
+ }
+ return output;
+}
+
+static image<float> *imageINTtoFLOAT(image<int> *input) {
+ int width = input->width();
+ int height = input->height();
+ image<float> *output = new image<float>(width, height, false);
+
+ for (int y = 0; y < height; y++) {
+ for (int x = 0; x < width; x++) {
+ imRef(output, x, y) = imRef(input, x, y);
+ }
+ }
+ return output;
+}
+
+static image<uchar> *imageFLOATtoUCHAR(image<float> *input,
+ float min, float max) {
+ int width = input->width();
+ int height = input->height();
+ image<uchar> *output = new image<uchar>(width, height, false);
+
+ if (max == min)
+ return output;
+
+ float scale = UCHAR_MAX / (max - min);
+ for (int y = 0; y < height; y++) {
+ for (int x = 0; x < width; x++) {
+ uchar val = (uchar)((imRef(input, x, y) - min) * scale);
+ imRef(output, x, y) = bound(val, (uchar)0, (uchar)UCHAR_MAX);
+ }
+ }
+ return output;
+}
+
+static image<uchar> *imageFLOATtoUCHAR(image<float> *input) {
+ float min, max;
+ min_max(input, &min, &max);
+ return imageFLOATtoUCHAR(input, min, max);
+}
+
+static image<long> *imageUCHARtoLONG(image<uchar> *input) {
+ int width = input->width();
+ int height = input->height();
+ image<long> *output = new image<long>(width, height, false);
+
+ for (int y = 0; y < height; y++) {
+ for (int x = 0; x < width; x++) {
+ imRef(output, x, y) = imRef(input, x, y);
+ }
+ }
+ return output;
+}
+
+static image<uchar> *imageLONGtoUCHAR(image<long> *input, long min, long max) {
+ int width = input->width();
+ int height = input->height();
+ image<uchar> *output = new image<uchar>(width, height, false);
+
+ if (max == min)
+ return output;
+
+ float scale = UCHAR_MAX / (float)(max - min);
+ for (int y = 0; y < height; y++) {
+ for (int x = 0; x < width; x++) {
+ uchar val = (uchar)((imRef(input, x, y) - min) * scale);
+ imRef(output, x, y) = bound(val, (uchar)0, (uchar)UCHAR_MAX);
+ }
+ }
+ return output;
+}
+
+static image<uchar> *imageLONGtoUCHAR(image<long> *input) {
+ long min, max;
+ min_max(input, &min, &max);
+ return imageLONGtoUCHAR(input, min, max);
+}
+
+static image<uchar> *imageSHORTtoUCHAR(image<short> *input,
+ short min, short max) {
+ int width = input->width();
+ int height = input->height();
+ image<uchar> *output = new image<uchar>(width, height, false);
+
+ if (max == min)
+ return output;
+
+ float scale = UCHAR_MAX / (float)(max - min);
+ for (int y = 0; y < height; y++) {
+ for (int x = 0; x < width; x++) {
+ uchar val = (uchar)((imRef(input, x, y) - min) * scale);
+ imRef(output, x, y) = bound(val, (uchar)0, (uchar)UCHAR_MAX);
+ }
+ }
+ return output;
+}
+
+static image<uchar> *imageSHORTtoUCHAR(image<short> *input) {
+ short min, max;
+ min_max(input, &min, &max);
+ return imageSHORTtoUCHAR(input, min, max);
+}
+
+#endif
diff --git a/tools/shapegame/dt/imutil.h b/tools/shapegame/dt/imutil.h
new file mode 100644
index 0000000..6fcfca9
--- /dev/null
+++ b/tools/shapegame/dt/imutil.h
@@ -0,0 +1,66 @@
+/* dt - imutil.h
+ *
+ * Copyright (C) 2006 Pedro Felzenszwalb
+ *
+ * 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 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
+ */
+/* some image utilities */
+
+#ifndef IMUTIL_H
+#define IMUTIL_H
+
+#include "image.h"
+#include "misc.h"
+
+/* compute minimum and maximum value in an image */
+template <class T>
+void min_max(image<T> *im, T *ret_min, T *ret_max) {
+ int width = im->width();
+ int height = im->height();
+
+ T min = imRef(im, 0, 0);
+ T max = imRef(im, 0, 0);
+ for (int y = 0; y < height; y++) {
+ for (int x = 0; x < width; x++) {
+ T val = imRef(im, x, y);
+ if (min > val)
+ min = val;
+ if (max < val)
+ max = val;
+ }
+ }
+
+ *ret_min = min;
+ *ret_max = max;
+}
+
+/* threshold image */
+template <class T>
+image<uchar> *threshold(image<T> *src, int t) {
+ int width = src->width();
+ int height = src->height();
+ image<uchar> *dst = new image<uchar>(width, height);
+
+ for (int y = 0; y < height; y++) {
+ for (int x = 0; x < width; x++) {
+ imRef(dst, x, y) = (imRef(src, x, y) >= t);
+ }
+ }
+
+ return dst;
+}
+
+#endif
+
diff --git a/tools/shapegame/dt/input.pbm b/tools/shapegame/dt/input.pbm
new file mode 100644
index 0000000..7e26ca9
--- /dev/null
+++ b/tools/shapegame/dt/input.pbm
Binary files differ
diff --git a/tools/shapegame/dt/misc.h b/tools/shapegame/dt/misc.h
new file mode 100644
index 0000000..b7b2f50
--- /dev/null
+++ b/tools/shapegame/dt/misc.h
@@ -0,0 +1,65 @@
+/* dt - misc.h
+ *
+ * Copyright (C) 2006 Pedro Felzenszwalb
+ *
+ * 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 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
+ */
+/* random stuff */
+
+#ifndef MISC_H
+#define MISC_H
+
+#include <cmath>
+
+#ifndef M_PI
+#define M_PI 3.141592653589793
+#endif
+
+typedef unsigned char uchar;
+
+typedef struct { uchar r, g, b; } rgb;
+
+inline bool operator==(const rgb &a, const rgb &b) {
+ return ((a.r == b.r) && (a.g == b.g) && (a.b == b.b));
+}
+
+template <class T>
+inline T abs(const T &x) { return (x > 0 ? x : -x); };
+
+template <class T>
+inline int sign(const T &x) { return (x >= 0 ? 1 : -1); };
+
+template <class T>
+inline T square(const T &x) { return x*x; };
+
+template <class T>
+inline T bound(const T &x, const T &min, const T &max) {
+ return (x < min ? min : (x > max ? max : x));
+}
+
+template <class T>
+inline bool check_bound(const T &x, const T&min, const T &max) {
+ return ((x < min) || (x > max));
+}
+
+inline int vlib_round(float x) { return (int)(x + 0.5F); }
+
+inline int vlib_round(double x) { return (int)(x + 0.5); }
+
+inline double gaussian(double val, double sigma) {
+ return exp(-square(val/sigma)/2)/(sqrt(2*M_PI)*sigma);
+}
+
+#endif
diff --git a/tools/shapegame/dt/pnmfile.h b/tools/shapegame/dt/pnmfile.h
new file mode 100644
index 0000000..eacf1a1
--- /dev/null
+++ b/tools/shapegame/dt/pnmfile.h
@@ -0,0 +1,211 @@
+/* dt - pnmfile.h
+ *
+ * Copyright (C) 2006 Pedro Felzenszwalb
+ *
+ * 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 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
+ */
+/* basic image I/O */
+
+#ifndef PNM_FILE_H
+#define PNM_FILE_H
+
+#include <cstdlib>
+#include <climits>
+#include <cstring>
+#include <fstream>
+#include "image.h"
+#include "misc.h"
+
+#define BUF_SIZE 256
+
+class pnm_error { };
+
+static void read_packed(unsigned char *data, int size, std::ifstream &f) {
+ unsigned char c = 0;
+
+ int bitshift = -1;
+ for (int pos = 0; pos < size; pos++) {
+ if (bitshift == -1) {
+ c = f.get();
+ bitshift = 7;
+ }
+ data[pos] = (c >> bitshift) & 1;
+ bitshift--;
+ }
+}
+
+static void write_packed(unsigned char *data, int size, std::ofstream &f) {
+ unsigned char c = 0;
+
+ int bitshift = 7;
+ for (int pos = 0; pos < size; pos++) {
+ c = c | (data[pos] << bitshift);
+ bitshift--;
+ if ((bitshift == -1) || (pos == size-1)) {
+ f.put(c);
+ bitshift = 7;
+ c = 0;
+ }
+ }
+}
+
+/* read PNM field, skipping comments */
+static void pnm_read(std::ifstream &file, char *buf) {
+ char doc[BUF_SIZE];
+ char c;
+
+ file >> c;
+ while (c == '#') {
+ file.getline(doc, BUF_SIZE);
+ file >> c;
+ }
+ file.putback(c);
+
+ file.width(BUF_SIZE);
+ file >> buf;
+ file.ignore();
+}
+
+static image<uchar> *loadPBM(const char *name) {
+ char buf[BUF_SIZE];
+
+ /* read header */
+ std::ifstream file(name, std::ios::in | std::ios::binary);
+ pnm_read(file, buf);
+ if (strncmp(buf, "P4", 2))
+ throw pnm_error();
+
+ pnm_read(file, buf);
+ int width = atoi(buf);
+ pnm_read(file, buf);
+ int height = atoi(buf);
+
+ /* read data */
+ image<uchar> *im = new image<uchar>(width, height);
+ for (int i = 0; i < height; i++)
+ read_packed(imPtr(im, 0, i), width, file);
+
+ return im;
+}
+
+static void savePBM(image<uchar> *im, const char *name) {
+ int width = im->width();
+ int height = im->height();
+ std::ofstream file(name, std::ios::out | std::ios::binary);
+
+ file << "P4\n" << width << " " << height << "\n";
+ for (int i = 0; i < height; i++)
+ write_packed(imPtr(im, 0, i), width, file);
+}
+
+static image<uchar> *loadPGM(const char *name) {
+ char buf[BUF_SIZE];
+
+ /* read header */
+ std::ifstream file(name, std::ios::in | std::ios::binary);
+ pnm_read(file, buf);
+ if (strncmp(buf, "P5", 2))
+ throw pnm_error();
+
+ pnm_read(file, buf);
+ int width = atoi(buf);
+ pnm_read(file, buf);
+ int height = atoi(buf);
+
+ pnm_read(file, buf);
+ if (atoi(buf) > UCHAR_MAX)
+ throw pnm_error();
+
+ /* read data */
+ image<uchar> *im = new image<uchar>(width, height);
+ file.read((char *)imPtr(im, 0, 0), width * height * sizeof(uchar));
+
+ return im;
+}
+
+static void savePGM(image<uchar> *im, const char *name) {
+ int width = im->width();
+ int height = im->height();
+ std::ofstream file(name, std::ios::out | std::ios::binary);
+
+ file << "P5\n" << width << " " << height << "\n" << UCHAR_MAX << "\n";
+ file.write((char *)imPtr(im, 0, 0), width * height * sizeof(uchar));
+}
+
+static image<rgb> *loadPPM(const char *name) {
+ char buf[BUF_SIZE], doc[BUF_SIZE];
+
+ /* read header */
+ std::ifstream file(name, std::ios::in | std::ios::binary);
+ pnm_read(file, buf);
+ if (strncmp(buf, "P6", 2))
+ throw pnm_error();
+
+ pnm_read(file, buf);
+ int width = atoi(buf);
+ pnm_read(file, buf);
+ int height = atoi(buf);
+
+ pnm_read(file, buf);
+ if (atoi(buf) > UCHAR_MAX)
+ throw pnm_error();
+
+ /* read data */
+ image<rgb> *im = new image<rgb>(width, height);
+ file.read((char *)imPtr(im, 0, 0), width * height * sizeof(rgb));
+
+ return im;
+}
+
+static void savePPM(image<rgb> *im, const char *name) {
+ int width = im->width();
+ int height = im->height();
+ std::ofstream file(name, std::ios::out | std::ios::binary);
+
+ file << "P6\n" << width << " " << height << "\n" << UCHAR_MAX << "\n";
+ file.write((char *)imPtr(im, 0, 0), width * height * sizeof(rgb));
+}
+
+template <class T>
+void load_image(image<T> **im, const char *name) {
+ char buf[BUF_SIZE];
+
+ /* read header */
+ std::ifstream file(name, std::ios::in | std::ios::binary);
+ pnm_read(file, buf);
+ if (strncmp(buf, "VLIB", 9))
+ throw pnm_error();
+
+ pnm_read(file, buf);
+ int width = atoi(buf);
+ pnm_read(file, buf);
+ int height = atoi(buf);
+
+ /* read data */
+ *im = new image<T>(width, height);
+ file.read((char *)imPtr((*im), 0, 0), width * height * sizeof(T));
+}
+
+template <class T>
+void save_image(image<T> *im, const char *name) {
+ int width = im->width();
+ int height = im->height();
+ std::ofstream file(name, std::ios::out | std::ios::binary);
+
+ file << "VLIB\n" << width << " " << height << "\n";
+ file.write((char *)imPtr(im, 0, 0), width * height * sizeof(T));
+}
+
+#endif
diff --git a/tools/shapegame/nice_target_spot.cpp b/tools/shapegame/nice_target_spot.cpp
new file mode 100644
index 0000000..aa3c31d
--- /dev/null
+++ b/tools/shapegame/nice_target_spot.cpp
@@ -0,0 +1,126 @@
+/* gcompris - nice_target_spot.cpp
+ *
+ * Copyright (C) 2006 Olaf Ronneberger
+ *
+ * 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 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
+ */
+
+/**************************************************************************
+** Title: create nice target spot
+**
+** create nice target spots for puzzle pieces in gcpomris shapegame
+** based on distance transform from Pedro F. Felzenszwalb and
+** Daniel P. Huttenlocher.
+**
+**************************************************************************/
+
+#include <cstdio>
+#include <cstdlib>
+#include <cmath>
+#include "dt/pnmfile.h"
+#include "dt/imconv.h"
+#include "dt/dt.h"
+
+int main(int argc, char **argv) {
+ if (argc != 3) {
+ fprintf(stderr, "usage: %s input(pbm) output(ppm)\n", argv[0]);
+ return 1;
+ }
+
+ char *input_name = argv[1];
+ char *output_name = argv[2];
+
+ // load input
+ image<uchar> *input = loadPBM(input_name);
+
+ // compute dt
+ image<float> *out = dt(input);
+
+ // take square roots
+ for (int y = 0; y < out->height(); y++) {
+ for (int x = 0; x < out->width(); x++) {
+ imRef(out, x, y) = sqrt(imRef(out, x, y));
+ }
+ }
+
+ // find maximum
+ int xmax = 0;
+ int ymax = 0;
+ float maxValue = 0;
+ for (int y = 0; y < out->height(); y++) {
+ for (int x = 0; x < out->width(); x++) {
+ if( imRef(out, x, y) > maxValue)
+ {
+ xmax = x;
+ ymax = y;
+ maxValue = imRef(out, x, y);
+ }
+ }
+ }
+
+ // draw circle at max position into new image (not touching the border)
+ image<rgb>* circleimage = new image<rgb>( input->width(),
+ input->height(), false);
+ rgb white;
+ white.r = 255;
+ white.g = 255;
+ white.b = 255;
+
+ circleimage->init(white);
+
+ float circleRadius = 3.5;
+ float borderThickness = 1;
+
+ float innerCircleSqrRadius = square(circleRadius);
+ float outerCircleSqrRadius = square(circleRadius+borderThickness);
+
+ rgb dotColor;
+ dotColor.r = 255;
+ dotColor.g = 0;
+ dotColor.b = 0;
+
+ rgb borderColor;
+ borderColor.r = 0;
+ borderColor.g = 0;
+ borderColor.b = 0;
+
+
+ for (int y = 0; y < out->height(); y++) {
+ for (int x = 0; x < out->width(); x++) {
+ float currentSqrRadius = square(x - xmax) + square(y - ymax);
+
+ if( currentSqrRadius <= outerCircleSqrRadius
+ && imRef(out, x, y) > 1)
+ {
+ if( currentSqrRadius <= innerCircleSqrRadius)
+ {
+ imRef( circleimage, x, y) = dotColor;
+ }
+ else
+ {
+ imRef( circleimage, x, y) = borderColor;
+ }
+ }
+ }
+ }
+
+ // save output
+ savePPM(circleimage, output_name);
+
+ delete input;
+ delete out;
+ delete circleimage;
+
+}
diff --git a/tools/shapegame/test.pbm b/tools/shapegame/test.pbm
new file mode 100644
index 0000000..97a57ea
--- /dev/null
+++ b/tools/shapegame/test.pbm
Binary files differ