2
* gcompris - awele.c Copyright (C) 2005 Frederic Mazzarol This program is
3
* free software; you can redistribute it and/or modify it under the terms
4
* of the GNU General Public License as published by the Free Software
5
* Foundation; either version 2 of the License, or (at your option) any
6
* later version. This program is distributed in the hope that it will
7
* be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
8
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
9
* General Public License for more details. You should have received a
10
* copy of the GNU General Public License along with this program; if not,
11
* write to the Free Software Foundation, Inc., 59 Temple Place, Suite
12
* 330, Boston, MA 02111-1307 USA
15
#include "gcompris/gcompris.h"
16
#include <awele_utils.h>
22
static GcomprisBoard *gcomprisBoard = NULL;
23
static gboolean board_paused = TRUE;
28
{ 102, 206, 309, 413, 522, 628, 626, 520, 411, 307, 201, 100 };
29
static GRAPHICS_ELT *graphsElt = NULL;
31
static void start_board (GcomprisBoard * agcomprisBoard);
32
static void pause_board (gboolean pause);
33
static void end_board (void);
34
static void set_level (guint level);
36
static void game_won (void);
37
static void repeat(void);
39
static GnomeCanvasGroup *boardRootItem = NULL;
41
static gboolean is_our_board (GcomprisBoard * gcomprisBoard);
42
static GnomeCanvasItem *awele_create_item (GnomeCanvasGroup * parent);
43
static void awele_destroy_all_items (void);
44
static void awele_next_level (void);
45
static gboolean to_computer(gpointer data);
46
static gint timeout = 0;
47
static gboolean computer_turn = FALSE;
48
static gboolean sublevel_finished = FALSE;
50
/*=============================================*/
51
static GcomprisAnimation *animation;
52
static GcomprisAnimCanvasItem *anim_item;
55
* Description of this plugin
57
static BoardPlugin menu_bp = {
60
"The awele game", /* The name that describe this board */
61
"African strategy board game", /* The description that describes
63
"Frederic Mazzarol <fmazzarol@gmail.com>", /* The author of this
65
NULL, /* Called when the plugin is loaded */
66
NULL, /* Called when gcompris exit */
67
NULL, /* Show the about box */
68
NULL, /* Show the configuration dialog */
69
start_board, /* Callback to start_board implementation */
72
is_our_board, /* Return 1 if the plugin can handle the board file */
83
* Main entry point mandatory for each Gcompris's game
84
* ---------------------------------------------------
88
GET_BPLUGIN_INFO (awele)
90
* in : boolean TRUE = PAUSE : FALSE = CONTINUE
93
static void pause_board (gboolean pause)
95
if (gcomprisBoard == NULL)
100
if (pause == FALSE) {
105
timeout = g_timeout_add (2000,
106
(GSourceFunc) to_computer,
108
anim_item = gc_anim_activate( boardRootItem,
110
gnome_canvas_item_show(GNOME_CANVAS_ITEM(anim_item->canvas));
115
gc_anim_deactivate(anim_item);
117
g_source_remove(timeout);
127
start_board (GcomprisBoard * agcomprisBoard)
130
if (agcomprisBoard != NULL)
133
GdkPixbuf *pixmap = NULL;
135
gcomprisBoard = agcomprisBoard;
136
gcomprisBoard->level = 1;
137
gcomprisBoard->maxlevel = 9;
138
gcomprisBoard->sublevel = 1;
139
gcomprisBoard->number_of_sublevel = 1; /* Go to next level after
140
* this number of 'play' */
142
str = gc_skin_image_get("button_reload.png");
143
pixmap = gc_pixmap_load(str);
146
gc_bar_set_repeat_icon(pixmap);
147
gdk_pixbuf_unref(pixmap);
148
gc_bar_set(GC_BAR_LEVEL|GC_BAR_REPEAT_ICON);
150
gc_bar_set(GC_BAR_LEVEL|GC_BAR_REPEAT);
153
animation = gc_anim_load( "connect4/sablier.txt" );
163
* =======================================
168
if (gcomprisBoard != NULL)
171
gc_anim_free(animation);
172
awele_destroy_all_items ();
174
gcomprisBoard = NULL;
178
is_our_board (GcomprisBoard * gcomprisBoard)
182
if (g_strcasecmp (gcomprisBoard->type, "awele") == 0)
185
* Set the plugin entry
187
gcomprisBoard->plugin = &menu_bp;
196
* Repeat let the user restart the current level
199
static void repeat (){
201
gc_anim_deactivate(anim_item);
203
g_source_remove(timeout);
212
set_level (guint level)
215
if(gcomprisBoard!=NULL)
217
gcomprisBoard->level=level;
218
gcomprisBoard->sublevel = 1;
221
gc_anim_deactivate(anim_item);
223
g_source_remove(timeout);
233
/*-------------------------------------------------------------------------------*/
234
/*-------------------------------------------------------------------------------*/
236
* set initial values for the next level
243
img = gc_skin_image_get ("gcompris-bg.jpg");
244
gc_set_background (gnome_canvas_root (gcomprisBoard->canvas),
248
gc_bar_set_level (gcomprisBoard);
250
awele_destroy_all_items ();
252
computer_turn = FALSE;
257
awele_create_item (gnome_canvas_root (gcomprisBoard->canvas));
259
if ((gcomprisBoard->level % 2) ==0){
260
computer_turn = TRUE;
261
staticAwale->player = HUMAN;
262
timeout = g_timeout_add (2000,
263
(GSourceFunc) to_computer,
265
anim_item = gc_anim_activate( boardRootItem,
267
gnome_canvas_item_show(GNOME_CANVAS_ITEM(anim_item->canvas));
270
computer_turn = FALSE;
275
* ====================================
278
* Destroy all the items
281
awele_destroy_all_items ()
285
if (boardRootItem != NULL)
286
gtk_object_destroy (GTK_OBJECT (boardRootItem));
288
boardRootItem = NULL;
292
for (i = 0; i < NBHOLE / 2; i++)
294
gdk_pixbuf_unref(graphsElt->pixbufButton[i]);
295
gdk_pixbuf_unref(graphsElt->pixbufButtonNotify[i]);
296
gdk_pixbuf_unref(graphsElt->pixbufButtonClicked[i]);
305
* ====================================
307
static GnomeCanvasItem *
308
awele_create_item (GnomeCanvasGroup * parent)
311
GdkPixbuf *pixmap = NULL;
314
gchar xpmFile[35] = BOUTON;
315
gchar xpmFileNotify[35] = BOUTON_NOTIFY;
316
gchar xpmFileClic[35] = BOUTON_CLIC;
319
GNOME_CANVAS_GROUP (gnome_canvas_item_new
321
(gcomprisBoard->canvas),
322
gnome_canvas_group_get_type (), "x",
323
(double) 0, "y", (double) 0, NULL));
326
* Load the cute frame
328
pixmap = gc_pixmap_load ("awele/awele_frame.png");
330
gnome_canvas_item_new (boardRootItem,
331
gnome_canvas_pixbuf_get_type (),
336
(double) gdk_pixbuf_get_width (pixmap),
338
(double) gdk_pixbuf_get_height (pixmap),
339
"width_set", TRUE, "height_set", TRUE, NULL);
340
gdk_pixbuf_unref(pixmap);
350
gnome_canvas_item_new (boardRootItem,
351
gnome_canvas_text_get_type (),
353
"font", gc_skin_font_board_medium,
356
"anchor", GTK_ANCHOR_CENTER,
357
"fill_color_rgba", gc_skin_color_shadow,
360
gnome_canvas_item_new (boardRootItem,
361
gnome_canvas_text_get_type (),
363
"font", gc_skin_font_board_medium,
366
"anchor", GTK_ANCHOR_CENTER,
367
"fill_color_rgba", gc_skin_color_text_button,
372
gnome_canvas_item_new (boardRootItem,
373
gnome_canvas_text_get_type (),
375
"font", gc_skin_font_board_medium,
378
"anchor", GTK_ANCHOR_CENTER,
379
"fill_color_rgba", gc_skin_color_shadow,
382
gnome_canvas_item_new (boardRootItem,
383
gnome_canvas_text_get_type (),
385
"font", gc_skin_font_board_medium,
388
"anchor", GTK_ANCHOR_CENTER,
389
"fill_color_rgba", gc_skin_color_text_button,
394
staticAwale = (AWALE *) g_malloc (sizeof (AWALE));
399
for (i = 0; i < NBHOLE; i++)
401
staticAwale->board[i] = NBBEANSPERHOLE;
404
/* ->player is last player */
406
staticAwale->player = COMPUTER;
408
for (i = 0; i < NBPLAYER; i++)
410
staticAwale->CapturedBeans[i] = 0;
413
graphsElt = (GRAPHICS_ELT *) g_malloc (sizeof (GRAPHICS_ELT));
416
* Boucle pour creer et positionner les boutons qui serviront
417
* a selectionner la case a jouer
419
for (i = 0; i < NBHOLE / 2; i++)
421
sprintf (buffer, "%d", i + 1);
422
xpmFile[12] = buffer[0];
423
graphsElt->pixbufButton[i] = gc_pixmap_load (xpmFile);
424
xpmFileNotify[12] = buffer[0];
425
graphsElt->pixbufButtonNotify[i] =
426
gc_pixmap_load (xpmFileNotify);
427
xpmFileClic[12] = buffer[0];
428
graphsElt->pixbufButtonClicked[i] =
429
gc_pixmap_load (xpmFileClic);
432
* Ajustement de l'ordonnee x, pour positionner le bouton sur la barre de boutons.
457
* Ajout des boutons comme items sur le rootGroup du canevas.
458
* et sauvegarde dans tableau button de type Gnome Canvas Item
459
* pour attacher les pointeurs de la fonction de rappel buttonClick
460
* qui servira a detecter quel est l'evenement souris, et en fonction
461
* declencher la procedure associee. Passage en argument a cette fonction
462
* du numero de case selectionne par tableau chaine
464
graphsElt->button[i] = gnome_canvas_item_new (boardRootItem,
465
gnome_canvas_pixbuf_get_type
476
gtk_signal_connect (GTK_OBJECT (graphsElt->button[i]),
477
"event", GTK_SIGNAL_FUNC (buttonClick),
484
* Affichage initial du nombre de graine courant dans le trou i.
485
* Sauvegarde des items d'affichage dans nbBeansHole, pour mise a jour
488
for (i = 11; i >= 0; i--)
491
sprintf (buffer, "%d", staticAwale->board[i]);
493
graphsElt->nbBeansHole[i] =
494
gnome_canvas_item_new (boardRootItem,
495
gnome_canvas_text_get_type (),
499
"x", (double) (caseCoord[i] + 45),
500
"y", (double) ((i < 6) ? 378 : 94),
501
"fill_color", "black", NULL);
505
* Affichage initial du nombre de graine capturees par chaque joueur.
506
* Sauvegarde des items d'affichage dans Captures[i], pour mise a jour
509
for (i = 0; i < 2; i++)
512
x1 = (i == 1) ? 32 : 762;
514
sprintf (buffer, "%d", staticAwale->CapturedBeans[i]);
516
graphsElt->Captures[i] = gnome_canvas_item_new (boardRootItem,
517
gnome_canvas_text_get_type
533
* Initialisation du buffer xpmFile avec le chemin relatif des fichiers graine
534
* Creation des pixbuf et sauvegarde dans variable pixbufBeans
536
strcpy (xpmFile, BEAN);
537
for (i = 0; i < 4; i++)
539
sprintf (buffer, "%d", i + 1);
540
xpmFile[12] = buffer[0];
541
graphsElt->pixbufBeans[i] = gc_pixmap_load (xpmFile);
545
* Reservation d'un espace memoire egal a NBTOTALBEAN x taille struct BEANHOLE_LINK
546
* pour y stocker chaque item de graine ainsi que la case dans laquelle se trouve la graine.
547
* Puis creation de toutes les graines et affichage sur le plateau.
549
initBoardGraphics (graphsElt);
551
graphsElt->msg = gnome_canvas_item_new (boardRootItem,
552
gnome_canvas_text_get_type (),
553
"text", _("Choose a house"),
559
"anchor", GTK_ANCHOR_CENTER,
567
* ====================================
572
if (sublevel_finished){
573
gcomprisBoard->sublevel++;
575
if (gcomprisBoard->sublevel > gcomprisBoard->number_of_sublevel)
580
gcomprisBoard->sublevel = 1;
581
gcomprisBoard->level++;
582
if (gcomprisBoard->level > gcomprisBoard->maxlevel)
590
gc_bonus_end_display (BOARD_FINISHED_RANDOM);
596
sublevel_finished = FALSE;
601
* Fonction effectuant l'initialisation des graines sur le plateau
602
* Cette fonction est appelee a chaque debut de partie
603
* @param data un pointeur de type void, pour passer en argument a la fonction\n
604
* les elements graphiques a modifier.
608
initBoardGraphics (GRAPHICS_ELT * graphsElt)
611
int i, j, k, idxTabBeans = 0;
614
//if (graphsElt->ptBeansHoleLink != NULL)
615
// free(graphsElt->ptBeansHoleLink);
617
graphsElt->ptBeansHoleLink =
618
(BEANHOLE_LINK *) malloc (NBTOTALBEAN *
619
sizeof (BEANHOLE_LINK));
621
for (i = NBHOLE - 1; i >= 0; i--)
624
j < staticAwale->board[i] && idxTabBeans < NBTOTALBEAN;
628
graphsElt->ptBeansHoleLink[idxTabBeans].beanPixbuf =
629
gnome_canvas_item_new (boardRootItem,
630
gnome_canvas_pixbuf_get_type
632
(double) caseCoord[i] +
641
pixbufBeans[k], NULL);
643
graphsElt->ptBeansHoleLink[idxTabBeans].hole = i;
649
static gboolean to_computer(gpointer data)
654
g_warning ("to_computer called but not compter_turn");
659
g_warning ("to_computer called but board paused");
664
coup = think (staticAwale, gcomprisBoard->level);
666
gc_anim_deactivate(anim_item);
667
computer_turn = FALSE;
670
AWALE *tmpAw = staticAwale;
671
staticAwale = moveAwale (coup, tmpAw);
673
g_error("le coup devrait être bon !");
675
gboolean IAmHungry = diedOfHunger(staticAwale);
679
updateCapturedBeans ();
680
g_object_set (graphsElt->msg, "text",
681
_("Your turn to play ..."), NULL);
683
/* computer hungry but human can't give it beans */
684
/* Human player win by catching all the beans left. */
686
sublevel_finished = TRUE;
687
gc_bonus_display(TRUE, BONUS_FLOWER);
690
/* computer can't play. Why? human is hungry and i cannot give it
692
/* if human has 24 beans, it's draw (human win in gcompris) */
693
/* if not, all staying are captured by computer and computer win */
695
sublevel_finished = (staticAwale->CapturedBeans[HUMAN] == 24);
696
gc_bonus_display(sublevel_finished, BONUS_FLOWER);
704
* Fonction effectuant la procedure associe a un clic sur pixmap
705
* Cette fonction est appelee quand un clic sur un bouton est effectue.\n
706
* Selon l'event->Type declenchement de procedure differentes, modification de l'aspect des boutons\n
707
* et declenchement d'un mouvement choisi par le joueur, puis lancement du coup de la machine.
708
* @param widget pointeur sur le widget ayant declenche l'evenement eventDelete
709
* @param event pointeur sur le type d'evenement
710
* @param data un pointeur de type void, pour passer en argument a la fonction\n
711
* les elements graphiques a modifier.
715
buttonClick (GtkWidget * item, GdkEvent * event, gpointer data)
717
gint numeroCase = GPOINTER_TO_INT(data);
721
case GDK_ENTER_NOTIFY:
722
g_object_set (GTK_OBJECT
723
(graphsElt->button[numeroCase]),
725
graphsElt->pixbufButtonNotify[numeroCase],
726
"y", (double) Y_BOUTONS, NULL);
728
case GDK_LEAVE_NOTIFY:
729
g_object_set (GTK_OBJECT
730
(graphsElt->button[numeroCase]),
732
graphsElt->pixbufButton[numeroCase],
733
"y", (double) Y_BOUTONS, NULL);
735
case GDK_BUTTON_PRESS:
739
g_object_set (GTK_OBJECT
740
(graphsElt->button[numeroCase]),
742
graphsElt->pixbufButtonClicked[numeroCase],
743
"y", (double) Y_BOUTONS + 3, NULL);
745
g_object_set (graphsElt->msg, "text", "", NULL);
747
AWALE *tmpaw = moveAwale (numeroCase, staticAwale);
750
g_object_set (graphsElt->msg, "text", _("Not allowed! Try again !"),
758
updateCapturedBeans ();
760
computer_turn = TRUE;
761
timeout = g_timeout_add (2000,
762
(GSourceFunc) to_computer,
764
anim_item = gc_anim_activate( boardRootItem,
770
case GDK_BUTTON_RELEASE:
771
g_object_set (GTK_OBJECT
772
(graphsElt->button[numeroCase]),
774
graphsElt->pixbufButtonNotify[numeroCase],
775
"y", (double) Y_BOUTONS, NULL);
785
* Fonction de gestion des graines dessinees sur le plateau
786
* Cette fonction est appelee apres chaque mouvement, \n
787
* pour remettre a jour le nombre de graines dessinees sur le plateau, \n
788
* et diminuer la zone d'allocation ou les pixmap des graines sont stockees.
789
* @param nbBeansHole[NBHOLE] Tableau de pointeur sur les gnomeCanvasItem\n
790
* affichant le nombre de graine par case
791
* @param rootGroup Pointeur sur le groupe contenant tous les items inseres dans le canevas
792
* @param ptLink pointeur sur zone memoire ou sont stockees toutes les images des graines du plateau.
793
* @param alpha entier pour differencier une mise a jour du plateau ou le lancement d'une nouvelle partie.
794
* @return Renvoi du pointeur sur la zone memoire apres redimension (n'a probablement pas changé d'adresse).
796
static BEANHOLE_LINK *
797
updateNbBeans (int alpha)
800
char buffer[3]; //Manipulation chaines de caracteres
801
int i, j, k, idxTabBeans = 0; //Compteur Boucle Manipulation Elements graphiques
802
static short int nbActiveBean = NBTOTALBEAN; //nbre graine restant sur plateau
803
static short int nbOldActiveBean; //nbre graine restant sur plateau au tour precedent
804
BEANHOLE_LINK *ptBeansHoleLink = NULL; //pointeur sur structures stockant les item graines et la case dans laquelle elles se trouvent.
807
* Sauvegarde du nombre de graines restantes sur le plateau de jeu
808
* pour le prochain appel a la fonction.
809
* Mise a jour de nbActiveBean avec nouvelle configuration du plateau de jeu.
813
nbOldActiveBean = 48;
817
nbOldActiveBean = nbActiveBean;
821
NBTOTALBEAN - (staticAwale->CapturedBeans[HUMAN] +
822
staticAwale->CapturedBeans[COMPUTER]);
825
* Destruction d'autant d'elements graphiques graines
826
* qu'il y a eu de captures pdt ce tour de jeu
828
for (ptBeansHoleLink = &(graphsElt->ptBeansHoleLink)[nbActiveBean], i = 0;
829
i < nbOldActiveBean - nbActiveBean; i++, ptBeansHoleLink++)
831
gtk_object_destroy (GTK_OBJECT (ptBeansHoleLink->beanPixbuf));
836
* Allocation d'un nouvel espace memoire stockant les item graines
837
* et la case dans laquelle elles se trouvent. Puis liberation de la fin de
838
* l'ancien espace memoire.
842
(BEANHOLE_LINK *) realloc (graphsElt->ptBeansHoleLink,
844
sizeof (BEANHOLE_LINK));
847
* Pour chaque case du plateau, mise a jour du nbre de graines qu'elle contient.
848
* Et pour chaque graine de cette case, deplacement d'un element graphique type graine
849
* dans cette case. Et mise a jour de l'information hole dans la structure BEANHOLE_LINK.
851
for (i = NBHOLE - 1; i >= 0; i--)
853
sprintf (buffer, "%d", staticAwale->board[i]);
854
gnome_canvas_item_set (graphsElt->nbBeansHole[i], "text", buffer, NULL);
857
j < staticAwale->board[i] && idxTabBeans < nbActiveBean;
863
gnome_canvas_item_set (ptBeansHoleLink[idxTabBeans].
865
(double) caseCoord[i] +
869
rand () % 60), NULL);
871
ptBeansHoleLink[idxTabBeans].hole = i;
877
* Renvoi du pointeur sur la zone memoire retaillee (n'a probablement pas change d'adresse).
880
graphsElt->ptBeansHoleLink = ptBeansHoleLink;
881
return ptBeansHoleLink;
886
* Fonction de gestion de l'affichage des scores
887
* Cette fonction est appelee apres chaque mouvement, \n
888
* pour remettre a jour le score des joueurs
889
* @param Captures[2] pointeur sur les gnomeCanvasItem d'affichage des scores
892
updateCapturedBeans ()
898
for (i = 0; i < 2; i++)
900
sprintf (buffer, "%d", staticAwale->CapturedBeans[i]);
901
g_object_set (graphsElt->Captures[i], "text", buffer, NULL);
902
if (staticAwale->CapturedBeans[i] > 24)
905
sublevel_finished = (i==0);
906
gc_bonus_display(sublevel_finished, BONUS_FLOWER);