Back to index

gcompris  8.2.2
algebra.c
Go to the documentation of this file.
00001 /* gcompris - algebra.c
00002  *
00003  * Time-stamp: <2006/08/21 23:29:57 bruno>
00004  *
00005  * Copyright (C) 2000 Bruno Coudoin
00006  *
00007  *   This program is free software; you can redistribute it and/or modify
00008  *   it under the terms of the GNU General Public License as published by
00009  *   the Free Software Foundation; either version 2 of the License, or
00010  *   (at your option) any later version.
00011  *
00012  *   This program is distributed in the hope that it will be useful,
00013  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  *   GNU General Public License for more details.
00016  *
00017  *   You should have received a copy of the GNU General Public License
00018  *   along with this program; if not, write to the Free Software
00019  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00020  */
00021 
00022 #include <ctype.h>
00023 #include <string.h>
00024 
00025 #include "gcompris/gcompris.h"
00026 
00027 #define TIMER_X 400
00028 #define TIMER_Y 140
00029 
00030 #define PLUSSIGNFILE   '+'
00031 #define MINUSSIGNFILE  '-'
00032 #define BYSIGNFILE     'x'
00033 #define DIVIDESIGNFILE ':'
00034 
00035 /* Some constants for the numbers layout */
00036 #define NUMBERSWIDTH       45
00037 
00038 #define SOUNDLISTFILE PACKAGE
00039 
00040 static gboolean       board_paused = TRUE;
00041 static int     leavenow;
00042 static int     gamewon;
00043 static void    game_won(void);
00044 
00045 static int     maxtime;
00046 
00047 static GList *item_list = NULL;
00048 
00049 static GcomprisBoard *gcomprisBoard = NULL;
00050 
00051 static char *expected_result = NULL;
00052 
00053 static gboolean operation_done[11];
00054 
00055 typedef struct _ToBeFoundItem ToBeFoundItem;
00056 
00057 struct _ToBeFoundItem{
00058   guint index;
00059   GnomeCanvasItem *item;
00060   GnomeCanvasItem *focus_item;
00061   GnomeCanvasItem *bad_item;
00062   ToBeFoundItem *next;
00063   ToBeFoundItem *previous;
00064   char value;
00065   gboolean in_error;
00066 };
00067 static ToBeFoundItem *currentToBeFoundItem = NULL;
00068 
00069 static GnomeCanvasGroup *boardRootItem = NULL;
00070 
00071 static char currentOperation[2];
00072 
00073 static void           start_board (GcomprisBoard *agcomprisBoard);
00074 static void           pause_board (gboolean pause);
00075 static void           end_board (void);
00076 static gboolean              is_our_board (GcomprisBoard *gcomprisBoard);
00077 static void           set_level (guint level);
00078 static gint           key_press(guint keyval, gchar *commit_str, gchar *preedit_str);
00079 static void           process_ok(void);
00080 
00081 static GnomeCanvasItem      *algebra_create_item(GnomeCanvasGroup *parent);
00082 static void           algebra_destroy_item(GnomeCanvasItem *item);
00083 static void           algebra_destroy_all_items(void);
00084 static void           display_operand(GnomeCanvasGroup *parent, 
00085                                     double x_align,
00086                                     double y, 
00087                                     char *operand_str,
00088                                     gboolean masked);
00089 static void           get_random_number(guint *first_operand, guint *second_operand);
00090 static void           algebra_next_level(void);
00091 static gint           item_event(GnomeCanvasItem *item, GdkEvent *event, gpointer data);
00092 static void           set_focus_item(ToBeFoundItem *toBeFoundItem, gboolean status);
00093 static void           init_operation(void);
00094 
00095 /* Description of this plugin */
00096 static BoardPlugin menu_bp =
00097 {
00098    NULL,
00099    NULL,
00100    "Practice the math operation",
00101    "Answer some algebra questions",
00102    "Bruno Coudoin <bruno.coudoin@free.fr>",
00103    NULL,
00104    NULL,
00105    NULL,
00106    NULL,
00107    start_board,
00108    pause_board,
00109    end_board,
00110    is_our_board,
00111    key_press,
00112    process_ok,
00113    set_level,
00114    NULL,
00115    NULL,
00116    NULL,
00117    NULL
00118 };
00119 
00120 /*
00121  * Main entry point mandatory for each Gcompris's game
00122  * ---------------------------------------------------
00123  *
00124  */
00125 
00126 GET_BPLUGIN_INFO(algebra)
00127 
00128 /*
00129  * in : boolean TRUE = PAUSE : FALSE = CONTINUE
00130  *
00131  */
00132 static void pause_board (gboolean pause)
00133 {
00134   if(gcomprisBoard==NULL)
00135     return;
00136 
00137   /* Make the timer follow our pause status */
00138   gc_timer_pause(pause);
00139 
00140   if(gamewon == TRUE && pause == FALSE) /* the game is won */
00141       algebra_next_level();
00142 
00143   if(leavenow == TRUE && pause == FALSE)
00144     gc_bonus_end_display(BOARD_FINISHED_RANDOM);
00145 
00146   board_paused = pause;
00147 }
00148 
00149 /*
00150  */
00151 static void start_board (GcomprisBoard *agcomprisBoard)
00152 {
00153 
00154   if(agcomprisBoard!=NULL)
00155     {
00156       gcomprisBoard=agcomprisBoard;
00157 
00158       /* disable im_context */
00159       gcomprisBoard->disable_im_context = TRUE;
00160 
00161       gc_set_background(gnome_canvas_root(gcomprisBoard->canvas), "images/scenery2_background.png");
00162 
00163       /* set initial values for this level */
00164       gcomprisBoard->level=1;
00165       gcomprisBoard->maxlevel=9;
00166       gcomprisBoard->sublevel=1;
00167       gcomprisBoard->number_of_sublevel=10; /* Go to next level after this number of 'play' */
00168       gc_score_start(SCORESTYLE_NOTE, 
00169                         gcomprisBoard->width - 220, 
00170                         gcomprisBoard->height - 50, 
00171                         gcomprisBoard->number_of_sublevel);
00172       gc_bar_set(GC_BAR_LEVEL|GC_BAR_OK);
00173 
00174       /* The mode defines the operation */
00175 
00176       /* Default mode */
00177       if(!gcomprisBoard->mode)
00178        currentOperation[0]=PLUSSIGNFILE;
00179       else if(g_strncasecmp(gcomprisBoard->mode, "+", 1)==0)
00180        currentOperation[0]=PLUSSIGNFILE;
00181       else if(g_strncasecmp(gcomprisBoard->mode, "-", 1)==0)
00182        currentOperation[0]=MINUSSIGNFILE;
00183       else if(g_strncasecmp(gcomprisBoard->mode, "*", 1)==0)
00184        currentOperation[0]=BYSIGNFILE;
00185       else if(g_strncasecmp(gcomprisBoard->mode, "/", 1)==0)
00186        currentOperation[0]=DIVIDESIGNFILE;
00187       currentOperation[1]='\0';
00188 
00189       init_operation();
00190       algebra_next_level();
00191 
00192       gamewon = FALSE;
00193       leavenow = FALSE;
00194       pause_board(FALSE);
00195     }
00196 
00197 }
00198 
00199 static void
00200 end_board ()
00201 {
00202   if(gcomprisBoard!=NULL)
00203     {
00204       pause_board(TRUE);
00205       gc_score_end();
00206       algebra_destroy_all_items();
00207     }
00208   gcomprisBoard = NULL;
00209 }
00210 
00211 static void
00212 set_level (guint level)
00213 {
00214 
00215 
00216   if(gcomprisBoard!=NULL)
00217     {
00218       gcomprisBoard->level=level;
00219       gcomprisBoard->sublevel=1;
00220       algebra_next_level();
00221     }
00222 }
00223 
00224 static gint key_press(guint keyval, gchar *commit_str, gchar *preedit_str)
00225 {
00226   guint c;
00227   gboolean stop = FALSE;
00228 
00229   if(!boardRootItem)
00230     return FALSE;
00231 
00232   /* Add some filter for control and shift key */
00233   switch (keyval)
00234     {
00235       /* Avoid all this keys to be interpreted by this game */
00236     case GDK_Shift_L:
00237     case GDK_Shift_R:
00238     case GDK_Control_L:
00239     case GDK_Control_R:
00240     case GDK_Caps_Lock:
00241     case GDK_Shift_Lock:
00242     case GDK_Meta_L:
00243     case GDK_Meta_R:
00244     case GDK_Alt_L:
00245     case GDK_Alt_R:
00246     case GDK_Super_L:
00247     case GDK_Super_R:
00248     case GDK_Hyper_L:
00249     case GDK_Hyper_R:
00250     case GDK_Num_Lock:
00251       return FALSE; 
00252     case GDK_KP_Enter:
00253     case GDK_Return:
00254       process_ok();
00255       return TRUE;
00256     case GDK_Right:
00257       if(currentToBeFoundItem->previous!=NULL)
00258        {
00259          set_focus_item(currentToBeFoundItem, FALSE);
00260          currentToBeFoundItem = (ToBeFoundItem *)currentToBeFoundItem->previous;
00261          set_focus_item(currentToBeFoundItem, TRUE);
00262        }
00263       return TRUE;
00264     case GDK_Delete:
00265     case GDK_BackSpace:
00266     case GDK_Left:
00267       if(currentToBeFoundItem->next!=NULL)
00268        {
00269          set_focus_item(currentToBeFoundItem, FALSE);
00270          currentToBeFoundItem = (ToBeFoundItem *)currentToBeFoundItem->next;
00271          set_focus_item(currentToBeFoundItem, TRUE);
00272        }
00273       return TRUE;
00274     }
00275 
00276   c = tolower(keyval); 
00277 
00278   if(currentToBeFoundItem!=NULL &&
00279      keyval>=GDK_0 && keyval<=GDK_9)
00280     {
00281       char number[2];
00282       number[1] = '\0';
00283       number[0] = (char)c;
00284 
00285       currentToBeFoundItem->value = c;
00286       gnome_canvas_item_set (currentToBeFoundItem->item,
00287                           "text", (char *)&number,
00288                           NULL);
00289 
00290       /* Not a failure (yet) */
00291       gnome_canvas_item_hide(currentToBeFoundItem->bad_item);
00292       currentToBeFoundItem->in_error = FALSE;
00293 
00294       set_focus_item(currentToBeFoundItem, FALSE);
00295 
00296       /* Move the focus to the next appropriate digit */
00297       while(!stop)
00298        {
00299          if(currentToBeFoundItem->previous!=NULL)
00300            currentToBeFoundItem = (ToBeFoundItem *)currentToBeFoundItem->previous;
00301          else
00302            stop = TRUE;
00303 
00304          if(currentToBeFoundItem->in_error==TRUE ||
00305             currentToBeFoundItem->value=='?')
00306            stop = TRUE;
00307        }
00308 
00309       set_focus_item(currentToBeFoundItem, TRUE);
00310     }
00311   return TRUE;
00312 }
00313 
00314 
00315 
00316 static gboolean
00317 is_our_board (GcomprisBoard *gcomprisBoard)
00318 {
00319   if (gcomprisBoard)
00320     {
00321       if(g_strcasecmp(gcomprisBoard->type, "algebra")==0)
00322        {
00323          /* Set the plugin entry */
00324          gcomprisBoard->plugin=&menu_bp;
00325 
00326          return TRUE;
00327        }
00328     }
00329   return FALSE;
00330 }
00331 
00332 
00333 /*-------------------------------------------------------------------------------*/
00334 /*-------------------------------------------------------------------------------*/
00335 /*-------------------------------------------------------------------------------*/
00336 /*-------------------------------------------------------------------------------*/
00337 
00338 static void timer_end()
00339 {
00340   gamewon = FALSE;
00341   leavenow = TRUE;
00342   algebra_destroy_all_items();
00343   gc_bonus_display(gamewon, BONUS_SMILEY);
00344 }
00345 
00346 
00347 /* set initial values for the next level */
00348 static void algebra_next_level() 
00349 {
00350 
00351   gc_bar_set_level(gcomprisBoard);
00352   gc_score_set(gcomprisBoard->sublevel);
00353 
00354   algebra_destroy_all_items();
00355 
00356   boardRootItem = GNOME_CANVAS_GROUP(
00357                                  gnome_canvas_item_new (gnome_canvas_root(gcomprisBoard->canvas),
00358                                                      gnome_canvas_group_get_type (),
00359                                                      "x", (double) 0,
00360                                                      "y", (double) 0,
00361                                                      NULL));
00362 
00363   maxtime = 20;
00364   gc_timer_display(TIMER_X, TIMER_Y, 
00365                       GCOMPRIS_TIMER_BALLOON, maxtime, timer_end);
00366 
00367   /* Try the next level */
00368   algebra_create_item(boardRootItem);
00369 
00370 }
00371 
00372 
00373 static void algebra_destroy_item(GnomeCanvasItem *item)
00374 {
00375   item_list = g_list_remove (item_list, item);
00376   gtk_object_destroy (GTK_OBJECT(item));
00377 }
00378 
00379 /* Destroy all the items */
00380 static void algebra_destroy_all_items()
00381 {
00382   GnomeCanvasItem *item;
00383   ToBeFoundItem *next;
00384 
00385   gc_timer_end();
00386 
00387   while(g_list_length(item_list)>0) 
00388     {
00389       item = g_list_nth_data(item_list, 0);
00390       algebra_destroy_item(item);
00391     }
00392 
00393   while(currentToBeFoundItem)
00394   {
00395       next = currentToBeFoundItem -> next;
00396       g_free(currentToBeFoundItem);
00397       currentToBeFoundItem = next;
00398   }
00399 
00400   if(boardRootItem!=NULL)
00401     gtk_object_destroy (GTK_OBJECT(boardRootItem));
00402   
00403   boardRootItem=NULL;
00404 }
00405 
00406 static void display_operand(GnomeCanvasGroup *parent, 
00407                          double x_align,
00408                          double y, 
00409                          char *operand_str,
00410                          gboolean masked)
00411 {
00412   GnomeCanvasItem *item, *focus_item = NULL, *bad_item = NULL;
00413   int i;
00414   ToBeFoundItem *toBeFoundItem=NULL;
00415   ToBeFoundItem *previousToBeFoundItem=NULL;;
00416 
00417   for(i=strlen(operand_str)-1; i>=0; i--)
00418     {
00419       char operand[2] = "?";
00420 
00421       if(!masked)
00422        operand[0] = operand_str[i];
00423       
00424       item = gnome_canvas_item_new (parent,
00425                                 gnome_canvas_text_get_type (),
00426                                 "text", &operand, 
00427                                 "font", gc_skin_font_board_huge_bold,
00428                                 "anchor", GTK_ANCHOR_CENTER,
00429                                 "x", x_align-((strlen(operand_str)-i)*NUMBERSWIDTH),
00430                                 "y", y,
00431                                 "fill_color_rgba", 0x2c2cFFFF,
00432                                 NULL);
00433       item_list = g_list_append (item_list, item);
00434 
00435       if(masked) 
00436        {
00437          focus_item = gnome_canvas_item_new (parent,
00438                                          gnome_canvas_text_get_type (),
00439                                          "text", "_",
00440                                          "font", gc_skin_font_board_huge_bold,
00441                                          "anchor", GTK_ANCHOR_CENTER,
00442                                          "x", x_align-((strlen(operand_str)-i)*NUMBERSWIDTH),
00443                                          "y", y,
00444                                          "fill_color_rgba", 0x00ae00FF,
00445                                          NULL);
00446 
00447          item_list = g_list_append (item_list, focus_item);
00448 
00449          bad_item = gnome_canvas_item_new (parent,
00450                                        gnome_canvas_text_get_type (),
00451                                        "text", "/",
00452                                        "font", gc_skin_font_board_huge_bold,
00453                                        "anchor", GTK_ANCHOR_CENTER,
00454                                        "x", x_align-((strlen(operand_str)-i)*NUMBERSWIDTH),
00455                                        "y", y,
00456                                        "fill_color_rgba", 0xFF0000FF,
00457                                        NULL);
00458          gnome_canvas_item_hide(bad_item);
00459 
00460          item_list = g_list_append (item_list, bad_item);
00461 
00462        }
00463 
00464       if(masked) 
00465        {
00466          toBeFoundItem = malloc(sizeof(ToBeFoundItem));
00467          toBeFoundItem->bad_item=bad_item;
00468          toBeFoundItem->index=i;
00469          toBeFoundItem->value='?';
00470          toBeFoundItem->item=item;
00471          toBeFoundItem->focus_item=focus_item;
00472          toBeFoundItem->previous=previousToBeFoundItem;
00473          toBeFoundItem->next=NULL;
00474 
00475          /* I Create a double linked list with the toBeFoundItem in order to navigate through them */
00476          if(previousToBeFoundItem!=NULL)
00477            previousToBeFoundItem->next=toBeFoundItem;
00478 
00479          previousToBeFoundItem=toBeFoundItem;
00480 
00481          /* Init the focussed item on the right digit */
00482          if(i==0)
00483            {
00484              currentToBeFoundItem=toBeFoundItem;
00485              set_focus_item(toBeFoundItem, TRUE);
00486            }
00487          else
00488            {
00489              set_focus_item(toBeFoundItem, FALSE);
00490            }
00491          gtk_signal_connect(GTK_OBJECT(item), "event",
00492                           (GtkSignalFunc) item_event,
00493                           toBeFoundItem);
00494        }
00495     }
00496 }
00497 
00498 static GnomeCanvasItem *algebra_create_item(GnomeCanvasGroup *parent)
00499 {
00500   GnomeCanvasItem *item;
00501   guint first_operand = 0;
00502   guint second_operand = 0;
00503   char *first_operand_str = NULL;
00504   char *second_operand_str = NULL;
00505   char *audioOperand = NULL;
00506   guint longuest;
00507   double x_align;
00508   double x, y;
00509   double y_firstline = 0;
00510 
00511 
00512 
00513   /* Some globals for this board layout */
00514   y_firstline = gcomprisBoard->height/5;
00515 
00516 
00517   get_random_number(&first_operand, &second_operand);
00518   first_operand_str = g_strdup_printf("%d", first_operand);
00519 
00520   second_operand_str = g_strdup_printf("%d", second_operand);
00521 
00522   /* Calc the longuest value */
00523   longuest = MAX(strlen(first_operand_str), strlen(second_operand_str));
00524 
00525   x_align = (gcomprisBoard->width - (longuest*3*NUMBERSWIDTH))/2 + NUMBERSWIDTH*(strlen(first_operand_str)) - 200;
00526 
00527   /* First operand */
00528   display_operand(parent, x_align, y_firstline, first_operand_str, FALSE);
00529 
00530   /* Second operand */
00531   display_operand(parent, x_align + NUMBERSWIDTH*(strlen(second_operand_str)+1),
00532                 y_firstline, second_operand_str, FALSE);
00533 
00534   /* Display the operator */
00535   x=(double) x_align;
00536   y=(double) y_firstline;
00537   item = gnome_canvas_item_new (parent,
00538                             gnome_canvas_text_get_type (),
00539                             "text", currentOperation, 
00540                             "font", gc_skin_font_board_huge_bold,
00541                             "x", x,
00542                             "y", y,
00543                             "anchor", GTK_ANCHOR_CENTER,
00544                             "fill_color_rgba", 0xFF3333FF,
00545                             NULL);
00546   item_list = g_list_append (item_list, item);
00547 
00548   /* Now the equal sign*/
00549   item = gnome_canvas_item_new (parent,
00550                             gnome_canvas_text_get_type (),
00551                             "text", "=", 
00552                             "font", gc_skin_font_board_huge_bold,
00553                             "x", x_align + NUMBERSWIDTH*(strlen(second_operand_str)+1),
00554                             "y", y,
00555                             "anchor", GTK_ANCHOR_CENTER,
00556                             "fill_color_rgba", 0xFF3333FF,
00557                             NULL);
00558   item_list = g_list_append (item_list, item);
00559 
00560   /* Display the empty area */
00561   g_free(expected_result);
00562   switch(currentOperation[0])
00563     {
00564     case PLUSSIGNFILE:
00565       expected_result = g_strdup_printf("%d", first_operand+second_operand);
00566       audioOperand = "sounds/$LOCALE/misc/plus.ogg";
00567       break;
00568     case MINUSSIGNFILE:
00569       expected_result = g_strdup_printf("%d", first_operand-second_operand);
00570       audioOperand = "sounds/$LOCALE/misc/minus.ogg";
00571       break;
00572     case BYSIGNFILE:
00573       expected_result = g_strdup_printf("%d", first_operand*second_operand);
00574       audioOperand = "sounds/$LOCALE/misc/by.ogg";
00575       break;
00576     case DIVIDESIGNFILE:
00577       expected_result = g_strdup_printf("%d", first_operand/second_operand);
00578       audioOperand = "sounds/$LOCALE/misc/outof.ogg";
00579       break;
00580     default:
00581       g_error("Bad Operation");
00582     }
00583   display_operand(parent, x_align + NUMBERSWIDTH*(strlen(second_operand_str)+
00584                                             strlen(expected_result)+2),
00585                 y_firstline, expected_result, TRUE);
00586   
00587 
00588   {
00589     gchar *str1 = NULL;
00590     gchar *str2 = NULL;
00591 
00592     if(strlen(first_operand_str)==1)
00593       str1 = gc_sound_alphabet(first_operand_str);
00594     else
00595       str1 = g_strdup_printf("%s.ogg", first_operand_str);
00596 
00597     if(strlen(second_operand_str)==1)
00598       str2 = gc_sound_alphabet(second_operand_str);
00599     else
00600       str2 = g_strdup_printf("%s.ogg", second_operand_str);
00601 
00602     g_free(first_operand_str);
00603     g_free(second_operand_str);
00604 
00605     first_operand_str = g_strdup_printf("sounds/$LOCALE/alphabet/%s", str1);
00606     second_operand_str = g_strdup_printf("sounds/$LOCALE/alphabet/%s", str2);
00607 
00608     gc_sound_play_ogg(first_operand_str, audioOperand , second_operand_str, "sounds/$LOCALE/misc/equal.ogg", NULL);
00609 
00610     g_free(str1);
00611     g_free(str2);
00612 
00613     g_free(first_operand_str);
00614     g_free(second_operand_str);
00615   }
00616   return (item);
00617 }
00618 
00619 static void set_focus_item(ToBeFoundItem *toBeFoundItem, gboolean status)
00620 {
00621   if(status)
00622     {
00623       gnome_canvas_item_show (toBeFoundItem->focus_item);
00624     }
00625   else
00626     {
00627       gnome_canvas_item_hide (toBeFoundItem->focus_item);
00628     }
00629 }
00630 
00631 static void process_ok()
00632 {
00633   ToBeFoundItem *toBeFoundItem;
00634   ToBeFoundItem *hasfail=NULL;
00635 
00636   set_focus_item(currentToBeFoundItem, FALSE);
00637   /* Go to the rightmost digit */
00638   while(currentToBeFoundItem->previous!=NULL)
00639     {
00640       currentToBeFoundItem=(ToBeFoundItem *)currentToBeFoundItem->previous;
00641     }
00642   
00643   toBeFoundItem=currentToBeFoundItem;
00644   /* Check the numbers one by one and redline errors */
00645   while(currentToBeFoundItem!=NULL)
00646     {
00647       if(currentToBeFoundItem->value!=expected_result[currentToBeFoundItem->index])
00648        {
00649          gnome_canvas_item_show(currentToBeFoundItem->bad_item);
00650          currentToBeFoundItem->in_error = TRUE;
00651          /* remember the appropriate digit to focus next */
00652          hasfail=currentToBeFoundItem;
00653        }
00654       currentToBeFoundItem=(ToBeFoundItem *)currentToBeFoundItem->next;
00655     }
00656   currentToBeFoundItem=toBeFoundItem;
00657   
00658   if(hasfail==NULL)
00659     {
00660       game_won();
00661     }
00662   else
00663     {
00664       set_focus_item(hasfail, TRUE);
00665       currentToBeFoundItem=hasfail;
00666     }
00667 }
00668 
00669 /* Callback for the 'toBeFoundItem' */
00670 static gint
00671 item_event(GnomeCanvasItem *item, GdkEvent *event, gpointer data)
00672 {
00673   ToBeFoundItem *toBeFoundItem;
00674 
00675   toBeFoundItem=(ToBeFoundItem *)data;
00676 
00677   if(board_paused)
00678     return FALSE;
00679 
00680   switch (event->type) 
00681     {
00682     case GDK_ENTER_NOTIFY:
00683       break;
00684     case GDK_LEAVE_NOTIFY:
00685 
00686       break;
00687     case GDK_BUTTON_PRESS:
00688       /* Remove focus from previous selection */
00689       set_focus_item(currentToBeFoundItem, FALSE);
00690 
00691       /* Set focus on current selection */
00692       set_focus_item(toBeFoundItem, TRUE);
00693 
00694       currentToBeFoundItem=toBeFoundItem;
00695 
00696       gc_sound_play_ogg ("sounds/gobble.ogg", NULL);
00697       break;
00698       
00699     default:
00700       break;
00701     }
00702   return FALSE;
00703 }
00704 
00705 /*
00706  * Return the next non already chosed operand
00707  *
00708  */
00709 static gint get_operand()
00710 {
00711   gint j = 10;
00712   gint i = (1+rand()%10);
00713   
00714   // Get the next free slot
00715   while(operation_done[i]==TRUE && j>=0)
00716     {
00717       j--;
00718       i++;
00719       if(i>10)
00720        i=1;
00721     }
00722   operation_done[i]=TRUE;
00723   return i;
00724 }
00725 
00726 static void init_operation()
00727 {
00728   int i;
00729 
00730   for(i=1; i<=10; i++)
00731     operation_done[i] = FALSE;
00732 }
00733 
00734 /* Returns a random int based on the current level */
00735 static void get_random_number(guint *first_operand, guint *second_operand)
00736 {
00737   guint min, max;
00738 
00739   switch(currentOperation[0])
00740     {
00741     case PLUSSIGNFILE:
00742       *first_operand = get_operand();
00743       *second_operand  = gcomprisBoard->level;
00744       break;
00745     case BYSIGNFILE:
00746       *first_operand  = gcomprisBoard->level;
00747       *second_operand = get_operand();
00748       break;
00749     case MINUSSIGNFILE:
00750       *first_operand  = gcomprisBoard->level+9;
00751       *second_operand = get_operand();
00752       break;
00753     case DIVIDESIGNFILE:
00754       switch(gcomprisBoard->level)
00755        {
00756        case 1 :
00757          min = 1;
00758          max = 2;
00759          break;
00760        case 2 :
00761          min = 2;
00762          max = 3;
00763          break;
00764        case 3 :
00765          min = 4;
00766          max = 5;
00767          break;
00768        case 4 :
00769          min = 6;
00770          max = 7;
00771          break;
00772        case 5 :
00773          min = 8;
00774          max = 9;
00775          break;
00776        case 6 :
00777          min = 1;
00778          max = 10;
00779          break;
00780        default :
00781          min = 1;
00782          max = 10;
00783        }
00784       *second_operand = (min+rand()%(max-min+1));
00785       *first_operand  = *second_operand*(min+rand()%max);
00786       break;
00787     default:
00788       g_error("Bad Operation");
00789     }
00790 }
00791 
00792 /* ==================================== */
00793 static void game_won()
00794 {
00795   gcomprisBoard->sublevel++;
00796 
00797   if(gcomprisBoard->sublevel>gcomprisBoard->number_of_sublevel) {
00798     /* Try the next level */
00799     gcomprisBoard->sublevel=1;
00800     gcomprisBoard->level++;
00801     if(gcomprisBoard->level>gcomprisBoard->maxlevel) { // the current board is finished : bail out
00802       gc_bonus_end_display(BOARD_FINISHED_RANDOM);
00803       return;
00804     }
00805 
00806     gamewon = TRUE;
00807     algebra_destroy_all_items();
00808     gc_bonus_display(gamewon, BONUS_SMILEY);
00809     init_operation();
00810     return;
00811   }
00812   algebra_next_level();
00813 }