Back to index

gcompris  8.2.2
algebra_guesscount.c
Go to the documentation of this file.
00001 /* gcompris - algebra_guesscount.c
00002  *
00003  * Copyright (C) 2001 Pascal Georges
00004  *
00005  *   This program is free software; you can redistribute it and/or modify
00006  *   it under the terms of the GNU General Public License as published by
00007  *   the Free Software Foundation; either version 2 of the License, or
00008  *   (at your option) any later version.
00009  *
00010  *   This program is distributed in the hope that it will be useful,
00011  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  *   GNU General Public License for more details.
00014  *
00015  *   You should have received a copy of the GNU General Public License
00016  *   along with this program; if not, write to the Free Software
00017  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00018  */
00019 
00020 #include "gcompris/gcompris.h"
00021 
00022 static GcomprisBoard *gcomprisBoard = NULL;
00023 static gboolean board_paused = TRUE;
00024 
00025 static void           start_board (GcomprisBoard *agcomprisBoard);
00026 static void           pause_board (gboolean pause);
00027 static void           end_board (void);
00028 static gboolean              is_our_board (GcomprisBoard *gcomprisBoard);
00029 static void           set_level (guint level);
00030 
00031 static int gamewon;
00032 static gint process_time_id = 0;
00033 
00034 static void           process_ok(void);
00035 static void           process_time(void);
00036 static void           game_won(void);
00037 static void           destroy_board(void);
00038 
00039 /* 4 levels :
00040  * 1evel 1 : 2 numbers and 1 operation
00041  * 1evel 2 : 3 numbers and 2 operations
00042  * 1evel 3 : 4 numbers and 3 operations
00043  * 1evel 4 : 5 numbers and 4 operations
00044  */
00045 #define NUMBER_OF_SUBLEVELS 3 // 3
00046 #define NUMBER_OF_LEVELS 4 // 4
00047 #define MAX_NUMBER 5
00048 
00049 #define TEXT_COLOR_FRONT "yellow"
00050 #define TEXT_COLOR_BACK "black"
00051 
00052 #define TEXT_RESULT_COLOR_FRONT "red"
00053 #define TEXT_RESULT_COLOR_BACK "orange"
00054 
00055 #define BLANK "___"
00056 
00057 #define NO_RESULT -1
00058 
00059 #define BUTTON_WIDTH 81
00060 #define BUTTON_HEIGHT 64
00061 #define HORIZONTAL_SEPARATION 20
00062 #define VERTICAL_SEPARATION 20
00063 
00064 static char* background_images[] = {"gcompris/animals/tiger1_by_Ralf_Schmode",
00065                                 "gcompris/animals/tigerdrink001.jpg",
00066                                 "gcompris/animals/tigercub003.jpg",
00067                                 "gcompris/animals/tigerplay001.jpg"};
00068 static const char  oper_values[] = {'+', '-', 'x', ':', '='};
00069 static const char *oper_images[] = {"plus", "minus", "by", "div", "equal"};
00070 static const int   num_values[] = {1,2,3,4,5,6,7,8,9,10,25,50,100};
00071 #define NUM_VALUES 13
00072 #define Y_OPE 20
00073 #define Y_NUM 100
00074 #define Y_ANS 200
00075 
00076 #define X_NUM1 300
00077 #define X_OPE 400
00078 #define X_NUM2 500
00079 #define X_EQUAL 600
00080 #define X_RESULT 700
00081 
00082 typedef struct _token token;
00083 struct _token {
00084   gboolean isNumber;
00085   gboolean isMoved;
00086   char oper;
00087   int num;
00088   int xOffset_original;
00089   int signal_id;
00090   GnomeCanvasItem * item;
00091 };
00092 
00093 // contains the values, NUM OPER NUM OPER NUM etc.
00094 token token_value[MAX_NUMBER*2-1];
00095 token * ptr_token_selected[MAX_NUMBER*2-1];
00096 
00097 static const int y_equal_offset[] = {Y_ANS,Y_ANS+BUTTON_HEIGHT+VERTICAL_SEPARATION,
00098                                  Y_ANS+2*BUTTON_HEIGHT+2*VERTICAL_SEPARATION,Y_ANS+3*BUTTON_HEIGHT+3*VERTICAL_SEPARATION};
00099 
00100 static const int x_token_offset[] = {X_NUM1,X_OPE,X_NUM2,X_OPE,X_NUM2,X_OPE,X_NUM2,X_OPE,X_NUM2};
00101 static const int y_token_offset[] = {Y_ANS, Y_ANS,Y_ANS,
00102                                  Y_ANS+BUTTON_HEIGHT+VERTICAL_SEPARATION, Y_ANS+BUTTON_HEIGHT+VERTICAL_SEPARATION,
00103                                  Y_ANS+2*BUTTON_HEIGHT+2*VERTICAL_SEPARATION,Y_ANS+2*BUTTON_HEIGHT+2*VERTICAL_SEPARATION,
00104                                  Y_ANS+3*BUTTON_HEIGHT+3*VERTICAL_SEPARATION, Y_ANS+3*BUTTON_HEIGHT+3*VERTICAL_SEPARATION};
00105 
00106 static char answer_oper[MAX_NUMBER-1];
00107 static int answer_num_index[MAX_NUMBER];
00108 static int token_count;
00109 static int result_to_find;
00110 
00111 /* ================================================================ */
00112 static GnomeCanvasGroup *boardRootItem = NULL;
00113 
00114 static GdkPixbuf * num_pixmap[NUM_VALUES];
00115 static GdkPixbuf * oper_pixmap[5];
00116 static GdkPixbuf *button_pixmap = NULL;
00117 
00118 static GnomeCanvasItem *oper_item[4];
00119 static GnomeCanvasItem *num_item[MAX_NUMBER];
00120 static GnomeCanvasItem *equal_item[NUMBER_OF_LEVELS];
00121 static GnomeCanvasItem *calcul_line_item[NUMBER_OF_LEVELS*2];
00122 static GnomeCanvasItem *calcul_line_item_back[NUMBER_OF_LEVELS*2];
00123 static GnomeCanvasItem *result_item_front, *result_item_back;
00124 
00125 static GnomeCanvasItem *algebra_guesscount_create_item(GnomeCanvasGroup *parent);
00126 static void algebra_guesscount_destroy_all_items(void);
00127 static void algebra_guesscount_next_level(void);
00128 static gint item_event_num(GnomeCanvasItem *item, GdkEvent *event, gpointer data);
00129 static gint item_event_oper(GnomeCanvasItem *item, GdkEvent *event, gpointer data);
00130 static gint item_event_oper_moved(GnomeCanvasItem *item, GdkEvent *event, gpointer data);
00131 
00132 static int generate_numbers();
00133 static int token_result();
00134 
00135 /* Description of this plugin */
00136 static BoardPlugin menu_bp =
00137   {
00138     NULL,
00139     NULL,
00140     "Guess operations",
00141     "Guess operations",
00142     "Pascal Georges pascal.georges1@free.fr>",
00143     NULL,
00144     NULL,
00145     NULL,
00146     NULL,
00147     start_board,
00148     pause_board,
00149     end_board,
00150     is_our_board,
00151     NULL,
00152     process_ok,
00153     set_level,
00154     NULL,
00155     NULL,
00156     NULL,
00157     NULL
00158   };
00159 
00160 /* ==================================== */
00161 /*
00162  * Main entry point mandatory for each Gcompris's game
00163  * ---------------------------------------------------
00164  */
00165 GET_BPLUGIN_INFO(algebra_guesscount)
00166 
00167 /* ==================================== */
00168 // in : boolean TRUE = PAUSE : FALSE = CONTINUE
00169 static void pause_board (gboolean pause){
00170   if(gcomprisBoard==NULL)
00171     return;
00172 
00173   if(gamewon == TRUE && pause == FALSE) {
00174     game_won();
00175   }
00176 
00177   board_paused = pause;
00178 }
00179 
00180 /* ==================================== */
00181 static void start_board (GcomprisBoard *agcomprisBoard) {
00182   int i;
00183   gchar *str;
00184 
00185   if(agcomprisBoard!=NULL){
00186     gcomprisBoard=agcomprisBoard;
00187 
00188     // load pixmap files
00189     g_warning("loading pixmaps in start_board\n");
00190     for (i=0; i<NUM_VALUES; i++) {
00191       str = g_strdup_printf("%s/%d.png", gcomprisBoard->boarddir,num_values[i]);
00192       num_pixmap[i] = gc_pixmap_load(str);
00193       g_free(str);
00194     }
00195     for (i=0; i<5; i++) {
00196       str = g_strdup_printf("%s/%s.png", gcomprisBoard->boarddir,oper_images[i]);
00197       oper_pixmap[i] = gc_pixmap_load(str);
00198       g_free(str);
00199     }
00200 
00201     str = g_strdup_printf("%s/%s", gcomprisBoard->boarddir,"button.png");
00202     button_pixmap = gc_pixmap_load(str);
00203     g_free(str);
00204 
00205     gc_set_background(gnome_canvas_root(gcomprisBoard->canvas),"gcompris/animals/tiger1_by_Ralf_Schmode.jpg");
00206     gcomprisBoard->level=1;
00207     gcomprisBoard->maxlevel=NUMBER_OF_LEVELS;
00208     gcomprisBoard->sublevel=1;
00209     gcomprisBoard->number_of_sublevel=NUMBER_OF_SUBLEVELS; /* Go to next level after this number of 'play' */
00210     gc_score_start(SCORESTYLE_NOTE,
00211                       50,
00212                       gcomprisBoard->height - 50,
00213                       gcomprisBoard->number_of_sublevel);
00214     gc_bar_set(GC_BAR_LEVEL|GC_BAR_OK);
00215 
00216     algebra_guesscount_next_level();
00217 
00218     gamewon = FALSE;
00219 
00220     pause_board(FALSE);
00221   }
00222 }
00223 
00224 /* ==================================== */
00225 static void end_board () {
00226   if(gcomprisBoard!=NULL) {
00227     pause_board(TRUE);
00228     gc_score_end();
00229     destroy_board();
00230     algebra_guesscount_destroy_all_items();
00231   }
00232   gcomprisBoard = NULL;
00233 }
00234 
00235 /* ==================================== */
00236 static void set_level (guint level) {
00237   if(gcomprisBoard!=NULL) {
00238     gcomprisBoard->level=level;
00239     gcomprisBoard->sublevel=1;
00240     algebra_guesscount_next_level();
00241   }
00242 }
00243 
00244 /* ==================================== */
00245 static gboolean is_our_board (GcomprisBoard *gcomprisBoard) {
00246   if (gcomprisBoard) {
00247     if(g_strcasecmp(gcomprisBoard->type, "algebra_guesscount")==0) {
00248       /* Set the plugin entry */
00249       gcomprisBoard->plugin=&menu_bp;
00250       return TRUE;
00251     }
00252   }
00253   return FALSE;
00254 }
00255 
00256 /* ==================================== */
00257 /* set initial values for the next level */
00258 static void algebra_guesscount_next_level() {
00259   gc_bar_set_level(gcomprisBoard);
00260 
00261   algebra_guesscount_destroy_all_items();
00262   gamewon = FALSE;
00263   token_count = 0;
00264 
00265   gc_score_set(gcomprisBoard->sublevel);
00266 
00267   /* Try the next level */
00268   algebra_guesscount_create_item(gnome_canvas_root(gcomprisBoard->canvas));
00269 }
00270 /* ==================================== */
00271 /* Destroy all the items */
00272 static void algebra_guesscount_destroy_all_items() {
00273   if(boardRootItem!=NULL)
00274     gtk_object_destroy (GTK_OBJECT(boardRootItem));
00275 
00276   boardRootItem = NULL;
00277 }
00278 /* ==================================== */
00279 static int token_result() {
00280   int result, i;
00281 
00282   if (token_count < 2)
00283     return NO_RESULT;
00284 
00285   g_assert(ptr_token_selected[0]->isNumber);
00286   result = num_values[ptr_token_selected[0]->num];
00287 
00288   for (i=2; i<token_count; i+=2) {
00289     g_assert(!ptr_token_selected[i-1]->isNumber);
00290     switch (ptr_token_selected[i-1]->oper) {
00291     case '+' :       result += num_values[ptr_token_selected[i]->num];
00292       break;
00293     case '-' :              if (result - num_values[ptr_token_selected[i]->num] < 0)
00294       return NO_RESULT;
00295       result -= num_values[ptr_token_selected[i]->num];
00296       break;
00297     case 'x' :       result *= num_values[ptr_token_selected[i]->num];
00298       break;
00299     case ':' :              if (result%num_values[ptr_token_selected[i]->num] != 0)
00300       return NO_RESULT;
00301       result /= num_values[ptr_token_selected[i]->num];
00302       break;
00303     default : g_warning("bug in token_result()\n"); break;
00304     }
00305   }
00306   return result;
00307 }
00308 /* ==================================== */
00309 static void update_line_calcul() {
00310   int line;
00311   char str[12];
00312 
00313   // finds which line has to be zeroed.
00314   if (token_count%2 == 0)
00315     line = (int)(token_count/2-1);
00316   else
00317     line = (int)(token_count/2);
00318 
00319   if(line==-1)
00320     return;
00321 
00322   sprintf(str, "%d",token_result());
00323   gnome_canvas_item_set(calcul_line_item[line*2],      "text", BLANK, NULL);
00324   gnome_canvas_item_set(calcul_line_item_back[line*2], "text", BLANK, NULL);
00325 
00326   if(line < gcomprisBoard->level-1) {                   /* No next line to update on last line */
00327     gnome_canvas_item_set(calcul_line_item[line*2+1],      "text", BLANK, NULL);
00328     gnome_canvas_item_set(calcul_line_item_back[line*2+1], "text", BLANK, NULL);
00329   }
00330 }
00331 /* ==================================== */
00332 static int generate_numbers() {
00333   int i, r, j, result;
00334   gboolean minus, divide;
00335 
00336   for (i=0; i<gcomprisBoard->level+1; i++) {
00337     j = RAND(0,NUM_VALUES-1);
00338     answer_num_index[i] = j;
00339   }
00340 
00341   result = num_values[answer_num_index[0]];
00342   for (i=0; i<gcomprisBoard->level; i++) {
00343     // + and x can always be chosen, but we must ensure - and / are valid
00344     minus = (result - num_values[answer_num_index[i+1]] >= 0);
00345 
00346     if(gcomprisBoard->level > 2 && num_values[answer_num_index[i+1]] <= 5) {       /* Avoid div operator at lower level */
00347       divide = (result % num_values[answer_num_index[i+1]] == 0);
00348     } else {
00349       divide = 0;
00350     }
00351     r = 2 + minus + divide;
00352 
00353     switch (RAND(1,r)) {
00354     case 1 :
00355       answer_oper[i] = '+';
00356       result += num_values[answer_num_index[i+1]];
00357       break;
00358     case 2 :         // prevent result from getting too big and accept only < 10 bor the by operator
00359       if ( (result*num_values[answer_num_index[i+1]] < 1000 ) &&
00360           ( num_values[answer_num_index[i+1]] < 10) ) {
00361        answer_oper[i] = 'x';
00362        result *= num_values[answer_num_index[i+1]];
00363       } else {
00364        answer_oper[i] = '+';
00365        result += num_values[answer_num_index[i+1]];
00366       }
00367       break;
00368     case 3 :
00369       if (minus) {
00370        answer_oper[i] = '-';
00371        result -= num_values[answer_num_index[i+1]];
00372        g_assert(result >= 0);
00373       } else {
00374        answer_oper[i] = ':';
00375        g_assert(result%num_values[answer_num_index[i+1]] == 0);
00376        result /= num_values[answer_num_index[i+1]];
00377       }
00378       break;
00379     case 4 :
00380       if ( RAND(0,1) == 0) {
00381        answer_oper[i] = '-';
00382        result -= num_values[answer_num_index[i+1]];
00383        g_assert(result >= 0);
00384       } else {
00385        answer_oper[i] = ':';
00386        g_assert(result%num_values[answer_num_index[i+1]] == 0);
00387        result /= num_values[answer_num_index[i+1]];
00388       }
00389       break;
00390     default : g_warning("Bug in guesscount\n"); break;
00391     }
00392   }
00393   return result;
00394 }
00395 /* ==================================== */
00396 static GnomeCanvasItem *algebra_guesscount_create_item(GnomeCanvasGroup *parent) {
00397   int i, xOffset, sid;
00398   char str[10];
00399 
00400   result_to_find = generate_numbers();
00401 
00402   boardRootItem = GNOME_CANVAS_GROUP(
00403                                  gnome_canvas_item_new (gnome_canvas_root(gcomprisBoard->canvas),
00404                                                      gnome_canvas_group_get_type (),
00405                                                      "x", (double) 0,
00406                                                      "y", (double) 0,
00407                                                      NULL));
00408 
00409   // the intermediate result, line by line, when empty is BLANK
00410   for (i=0; i<gcomprisBoard->level; i++) {
00411     calcul_line_item_back[i*2] = gnome_canvas_item_new (boardRootItem,
00412                                                  gnome_canvas_text_get_type (),
00413                                                  "text", BLANK,
00414                                                  "font", gc_skin_font_board_title_bold,
00415                                                  "x", (double) X_EQUAL+BUTTON_WIDTH*1.5 + 1,
00416                                                  "y", (double) y_equal_offset[i]+BUTTON_HEIGHT/2 + 1,
00417                                                  "anchor", GTK_ANCHOR_CENTER,
00418                                                  "fill_color", TEXT_COLOR_BACK,
00419                                                  NULL);
00420     calcul_line_item[i*2] = gnome_canvas_item_new (boardRootItem,
00421                                              gnome_canvas_text_get_type (),
00422                                              "text", BLANK,
00423                                              "font", gc_skin_font_board_title_bold,
00424                                              "x", (double) X_EQUAL+BUTTON_WIDTH*1.5,
00425                                              "y", (double) y_equal_offset[i]+BUTTON_HEIGHT/2,
00426                                              "anchor", GTK_ANCHOR_CENTER,
00427                                              "fill_color", TEXT_COLOR_FRONT,
00428                                              NULL);
00429   }
00430 
00431   for (i=0; i<gcomprisBoard->level-1; i++) {
00432     calcul_line_item_back[i*2+1] = gnome_canvas_item_new (boardRootItem,
00433                                                    gnome_canvas_text_get_type (),
00434                                                    "text", BLANK,
00435                                                    "font", gc_skin_font_board_title_bold,
00436                                                    "x", (double) X_NUM1+BUTTON_WIDTH/2 + 1,
00437                                                    "y", (double) y_equal_offset[i+1]+BUTTON_HEIGHT/2 + 1,
00438                                                    "anchor", GTK_ANCHOR_CENTER,
00439                                                    "fill_color", TEXT_COLOR_BACK,
00440                                                    NULL);
00441     calcul_line_item[i*2+1] = gnome_canvas_item_new (boardRootItem,
00442                                                gnome_canvas_text_get_type (),
00443                                                "text", BLANK,
00444                                                "font", gc_skin_font_board_title_bold,
00445                                                "x", (double) X_NUM1+BUTTON_WIDTH/2,
00446                                                "y", (double) y_equal_offset[i+1]+BUTTON_HEIGHT/2,
00447                                                "anchor", GTK_ANCHOR_CENTER,
00448                                                "fill_color", TEXT_COLOR_FRONT,
00449                                                NULL);
00450   }
00451 
00452   xOffset = (gcomprisBoard->width - 4 * BUTTON_WIDTH - 3 * HORIZONTAL_SEPARATION)/2;
00453   for (i=0; i<4; i++) {
00454     oper_item[i] = gnome_canvas_item_new (boardRootItem,
00455                                      gnome_canvas_pixbuf_get_type (),
00456                                      "pixbuf", oper_pixmap[i],
00457                                      "x", (double) xOffset ,
00458                                      "y", (double) Y_OPE,
00459                                      "width", (double) BUTTON_WIDTH,
00460                                      "height", (double) BUTTON_HEIGHT,
00461                                      "width_set", TRUE,
00462                                      "height_set", TRUE,
00463                                      NULL);
00464     xOffset += BUTTON_WIDTH+HORIZONTAL_SEPARATION;
00465     gtk_signal_connect(GTK_OBJECT(oper_item[i]), "event", (GtkSignalFunc) item_event_oper,
00466                      GINT_TO_POINTER(&(token_value[i*2+1])) );
00467     token_value[i*2+1].isNumber = FALSE;
00468     token_value[i*2+1].isMoved = FALSE;
00469     token_value[i*2+1].oper = oper_values[i];
00470   }
00471 
00472   // displays the target result
00473   sprintf(str,"%d",result_to_find);
00474   result_item_back = gnome_canvas_item_new (boardRootItem,
00475                                        gnome_canvas_text_get_type (),
00476                                        "text", str,
00477                                        "font", gc_skin_font_board_title_bold,
00478                                        "x", (double) xOffset+BUTTON_WIDTH +1,
00479                                        "y", (double) Y_OPE+BUTTON_HEIGHT/2 +1,
00480                                        "anchor", GTK_ANCHOR_CENTER,
00481                                        "fill_color", TEXT_RESULT_COLOR_BACK,
00482                                        NULL);
00483   result_item_front = gnome_canvas_item_new (boardRootItem,
00484                                         gnome_canvas_text_get_type (),
00485                                         "text", str,
00486                                         "font", gc_skin_font_board_title_bold,
00487                                         "x", (double) xOffset+BUTTON_WIDTH,
00488                                         "y", (double) Y_OPE+BUTTON_HEIGHT/2,
00489                                         "anchor", GTK_ANCHOR_CENTER,
00490                                         "fill_color", TEXT_RESULT_COLOR_FRONT,
00491                                         NULL);
00492 
00493   xOffset = (gcomprisBoard->width - (gcomprisBoard->level+1) * BUTTON_WIDTH - gcomprisBoard->level * HORIZONTAL_SEPARATION)/2;
00494   for (i=0; i<gcomprisBoard->level+1; i++) {
00495     num_item[i] = gnome_canvas_item_new (boardRootItem,
00496                                     gnome_canvas_pixbuf_get_type (),
00497                                     "pixbuf", num_pixmap[answer_num_index[i]],
00498                                     "x", (double) xOffset ,
00499                                     "y", (double) Y_NUM,
00500                                     "width", (double) BUTTON_WIDTH,
00501                                     "height", (double) BUTTON_HEIGHT,
00502                                     "width_set", TRUE,
00503                                     "height_set", TRUE,
00504                                     NULL);
00505     sid = gtk_signal_connect(GTK_OBJECT(num_item[i]), "event", (GtkSignalFunc) item_event_num,
00506                           (void *)&(token_value[i*2]));
00507     token_value[i*2].isNumber = TRUE;
00508     token_value[i*2].num = answer_num_index[i];
00509     token_value[i*2].signal_id = sid;
00510     token_value[i*2].item = num_item[i];
00511     token_value[i*2].isMoved = FALSE;
00512     token_value[i*2].xOffset_original = xOffset;
00513     xOffset += BUTTON_WIDTH+HORIZONTAL_SEPARATION;
00514   }
00515 
00516   // items "="
00517   for (i=0; i<gcomprisBoard->level; i++) {
00518     equal_item[i] = gnome_canvas_item_new (boardRootItem,
00519                                       gnome_canvas_pixbuf_get_type (),
00520                                       "pixbuf", oper_pixmap[4],
00521                                       "x", (double) X_EQUAL ,
00522                                       "y", (double) y_equal_offset[i],
00523                                       "width", (double) BUTTON_WIDTH,
00524                                       "height", (double) BUTTON_HEIGHT,
00525                                       "width_set", TRUE,
00526                                       "height_set", TRUE,
00527                                       NULL);
00528   }
00529 
00530   return NULL;
00531 }
00532 /* ==================================== */
00533 static void game_won() {
00534   gcomprisBoard->sublevel++;
00535 
00536   if(gcomprisBoard->sublevel>gcomprisBoard->number_of_sublevel) {
00537     /* Try the next level */
00538     gcomprisBoard->sublevel=1;
00539     gcomprisBoard->level++;
00540 
00541     if(gcomprisBoard->level>gcomprisBoard->maxlevel) {
00542       gc_bonus_end_display(BOARD_FINISHED_TUXPLANE);
00543       return;
00544     }
00545     gc_set_background(gnome_canvas_root(gcomprisBoard->canvas),background_images[gcomprisBoard->level-1]);
00546   }
00547   algebra_guesscount_next_level();
00548 }
00549 
00550 /* ==================================== */
00551 static void process_ok(){
00552   gamewon = (result_to_find == token_result());
00553   process_time_id = gtk_timeout_add (50, (GtkFunction) process_time, NULL);
00554 }
00555 /* ==================================== */
00556 static void process_time(){
00557   if (process_time_id) {
00558     gtk_timeout_remove (process_time_id);
00559     process_time_id = 0;
00560   }
00561   gc_bonus_display(gamewon, BONUS_RANDOM);
00562 }
00563 /* ==================================== */
00564 static int oper_char_to_pixmap_index(char oper) {
00565   int i;
00566 
00567   g_assert(oper == '+' || oper == '-' || oper == 'x' || oper == ':' || oper == '=');
00568 
00569   for (i=0; i<5; i++)
00570     if (oper_values[i] == oper)
00571       return i;
00572 
00573   return -1;
00574 }
00575 /* ==================================== */
00576 static gint item_event_oper(GnomeCanvasItem *item, GdkEvent *event, gpointer data){
00577   token *t = (       token *)data;
00578 
00579   GnomeCanvasItem * tmp_item;
00580 
00581   if(board_paused)
00582     return FALSE;
00583   // first verify it is oper turn
00584   if (token_count % 2 == 0 || token_count >= 2*gcomprisBoard->level+1)
00585     return FALSE;
00586 
00587   switch (event->type) {
00588   case GDK_BUTTON_PRESS:
00589     ptr_token_selected[token_count] = t;
00590     tmp_item = gnome_canvas_item_new (boardRootItem,
00591                                   gnome_canvas_pixbuf_get_type (),
00592                                   "pixbuf", oper_pixmap[oper_char_to_pixmap_index(t->oper)],
00593                                   "x", (double) x_token_offset[token_count],
00594                                   "y", (double) y_token_offset[token_count],
00595                                   "width", (double) BUTTON_WIDTH,
00596                                   "height", (double) BUTTON_HEIGHT,
00597                                   "width_set", TRUE,
00598                                   "height_set", TRUE,
00599                                   NULL);
00600     token_count++;
00601     gtk_signal_connect(GTK_OBJECT(tmp_item), "event", (GtkSignalFunc) item_event_oper_moved, GINT_TO_POINTER(token_count));
00602     break;
00603   default : break;
00604   }
00605   return FALSE;
00606 }
00607 /* ==================================== */
00608 static gint item_event_oper_moved(GnomeCanvasItem *item, GdkEvent *event, gpointer data){
00609   int count = GPOINTER_TO_INT(data);
00610 
00611   if(board_paused)
00612     return FALSE;
00613   // we only allow the undo of an operation if it is the last element displayed
00614   switch (event->type) {
00615   case GDK_BUTTON_PRESS:
00616     if (count == token_count) {
00617       gtk_object_destroy (GTK_OBJECT(item));
00618       token_count--;
00619       update_line_calcul();
00620     }
00621     break;
00622   default : break;
00623   }
00624   return FALSE;
00625 }
00626 /* ==================================== */
00627 static gint item_event_num(GnomeCanvasItem *item, GdkEvent *event, gpointer data){
00628   token *t = (token *)data;
00629   char str[12];
00630 
00631   if(board_paused)
00632     return FALSE;
00633 
00634   switch (event->type){
00635   case GDK_BUTTON_PRESS:
00636     if (t->isMoved) {
00637       if (item != ptr_token_selected[token_count-1]->item)
00638        return FALSE;
00639       // we put back in its original place a number item
00640       gc_item_absolute_move(item, t->xOffset_original, Y_NUM);
00641       token_count--;
00642       update_line_calcul();
00643       t->isMoved = FALSE;
00644     } else { // the item is at its original place
00645       if (token_count % 2 == 1 || token_count > 2*gcomprisBoard->level+1)
00646        return FALSE;
00647       token_count++;
00648       ptr_token_selected[token_count-1] = t;
00649       // some operations are illegal A - B must be > 0 and A/B an integer
00650       if (token_result() == NO_RESULT && token_count != 1) {
00651        token_count--;
00652        return FALSE;
00653       }
00654 
00655       gc_item_absolute_move(item, x_token_offset[token_count-1], y_token_offset[token_count-1]);
00656       t->isMoved = TRUE;
00657 
00658       // update result text items
00659       if (token_count != 1 && token_count % 2 == 1) {
00660        sprintf(str,"%d",token_result());
00661 
00662        gnome_canvas_item_set(calcul_line_item[token_count-3], "text", str, NULL);
00663        gnome_canvas_item_set(calcul_line_item_back[token_count-3], "text", str, NULL);
00664 
00665        if(token_count < 2*gcomprisBoard->level+1) {                   /* No next line to update on last line */
00666          gnome_canvas_item_set(calcul_line_item[token_count-2], "text", str, NULL);
00667          gnome_canvas_item_set(calcul_line_item_back[token_count-2], "text", str, NULL);
00668        }
00669       }
00670     }
00671     break;
00672   default : break;
00673   }
00674   return FALSE;
00675 }
00676 /* ======================================= */
00677 static void destroy_board() {
00678   int i;
00679 
00680   for (i=0; i<NUM_VALUES; i++)
00681     gdk_pixbuf_unref(num_pixmap[i]);
00682   for (i=0; i<5; i++)
00683     gdk_pixbuf_unref(oper_pixmap[i]);
00684 }