~ml-launchpad/ubuntu/natty/gcompris/fix-for-777349

« back to all changes in this revision

Viewing changes to src/boards/algebra_guesscount.c

  • Committer: Bazaar Package Importer
  • Author(s): Marc Gariepy, Marc Gariepy, Stephane Graber
  • Date: 2010-01-04 17:42:49 UTC
  • mfrom: (1.1.14 upstream)
  • Revision ID: james.westby@ubuntu.com-20100104174249-7bupatd9dtxyhvs4
Tags: 9.0-0ubuntu1
[Marc Gariepy]
* New upstream release (9.0).
* Remove cache.c from POTFILES to avoid FTBFS
* Remove unneeded rm in debian/rules (file no longer exists upstream)

[Stephane Graber]
* Bump Debian standards to 3.8.3
* Add patch system (dpatch)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* gcompris - algebra_guesscount.c
2
 
 *
3
 
 * Copyright (C) 2001 Pascal Georges
4
 
 *
5
 
 *   This program is free software; you can redistribute it and/or modify
6
 
 *   it under the terms of the GNU General Public License as published by
7
 
 *   the Free Software Foundation; either version 3 of the License, or
8
 
 *   (at your option) any later version.
9
 
 *
10
 
 *   This program is distributed in the hope that it will be useful,
11
 
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 
 *   GNU General Public License for more details.
14
 
 *
15
 
 *   You should have received a copy of the GNU General Public License
16
 
 *   along with this program; if not, see <http://www.gnu.org/licenses/>.
17
 
 */
18
 
 
19
 
#include "gcompris/gcompris.h"
20
 
 
21
 
static GcomprisBoard *gcomprisBoard = NULL;
22
 
static gboolean board_paused = TRUE;
23
 
 
24
 
static void              start_board (GcomprisBoard *agcomprisBoard);
25
 
static void              pause_board (gboolean pause);
26
 
static void              end_board (void);
27
 
static gboolean          is_our_board (GcomprisBoard *gcomprisBoard);
28
 
static void              set_level (guint level);
29
 
 
30
 
static int gamewon;
31
 
static gint process_time_id = 0;
32
 
 
33
 
static void              process_time(void);
34
 
static void              game_won(void);
35
 
static void              destroy_board(void);
36
 
 
37
 
/* 4 levels :
38
 
 * 1evel 1 : 2 numbers and 1 operation
39
 
 * 1evel 2 : 3 numbers and 2 operations
40
 
 * 1evel 3 : 4 numbers and 3 operations
41
 
 * 1evel 4 : 5 numbers and 4 operations
42
 
 */
43
 
#define NUMBER_OF_SUBLEVELS 3 // 3
44
 
#define NUMBER_OF_LEVELS 4 // 4
45
 
#define MAX_NUMBER 5
46
 
 
47
 
#define TEXT_COLOR_FRONT "yellow"
48
 
#define TEXT_COLOR_BACK "black"
49
 
 
50
 
#define TEXT_RESULT_COLOR_FRONT "red"
51
 
#define TEXT_RESULT_COLOR_BACK "orange"
52
 
 
53
 
#define BLANK "___"
54
 
 
55
 
#define NO_RESULT -1
56
 
 
57
 
#define BUTTON_WIDTH 81
58
 
#define BUTTON_HEIGHT 64
59
 
#define HORIZONTAL_SEPARATION 20
60
 
#define VERTICAL_SEPARATION 20
61
 
 
62
 
static char* background_images[] = {"opt/animals/tiger1_by_Ralf_Schmode",
63
 
                                    "opt/animals/tigerdrink001.jpg",
64
 
                                    "opt/animals/tigercub003.jpg",
65
 
                                    "opt/animals/tigerplay001.jpg"};
66
 
static const char  oper_values[] = {'+', '-', 'x', ':', '='};
67
 
static const char *oper_images[] = {"plus", "minus", "by", "div", "equal"};
68
 
static const int   num_values[] = {1,2,3,4,5,6,7,8,9,10,25,50,100};
69
 
#define NUM_VALUES 13
70
 
#define Y_OPE 20
71
 
#define Y_NUM 100
72
 
#define Y_ANS 200
73
 
 
74
 
#define X_NUM1 300
75
 
#define X_OPE 400
76
 
#define X_NUM2 500
77
 
#define X_EQUAL 600
78
 
#define X_RESULT 700
79
 
 
80
 
typedef struct _token token;
81
 
struct _token {
82
 
  gboolean isNumber;
83
 
  gboolean isMoved;
84
 
  char oper;
85
 
  int num;
86
 
  int xOffset_original;
87
 
  int signal_id;
88
 
  GnomeCanvasItem * item;
89
 
};
90
 
 
91
 
// contains the values, NUM OPER NUM OPER NUM etc.
92
 
token token_value[MAX_NUMBER*2-1];
93
 
token * ptr_token_selected[MAX_NUMBER*2-1];
94
 
 
95
 
static const int y_equal_offset[] = {Y_ANS,Y_ANS+BUTTON_HEIGHT+VERTICAL_SEPARATION,
96
 
                                     Y_ANS+2*BUTTON_HEIGHT+2*VERTICAL_SEPARATION,Y_ANS+3*BUTTON_HEIGHT+3*VERTICAL_SEPARATION};
97
 
 
98
 
static const int x_token_offset[] = {X_NUM1,X_OPE,X_NUM2,X_OPE,X_NUM2,X_OPE,X_NUM2,X_OPE,X_NUM2};
99
 
static const int y_token_offset[] = {Y_ANS, Y_ANS,Y_ANS,
100
 
                                     Y_ANS+BUTTON_HEIGHT+VERTICAL_SEPARATION, Y_ANS+BUTTON_HEIGHT+VERTICAL_SEPARATION,
101
 
                                     Y_ANS+2*BUTTON_HEIGHT+2*VERTICAL_SEPARATION,Y_ANS+2*BUTTON_HEIGHT+2*VERTICAL_SEPARATION,
102
 
                                     Y_ANS+3*BUTTON_HEIGHT+3*VERTICAL_SEPARATION, Y_ANS+3*BUTTON_HEIGHT+3*VERTICAL_SEPARATION};
103
 
 
104
 
static char answer_oper[MAX_NUMBER-1];
105
 
static int answer_num_index[MAX_NUMBER];
106
 
static int token_count;
107
 
static int result_to_find;
108
 
 
109
 
/* ================================================================ */
110
 
static GnomeCanvasGroup *boardRootItem = NULL;
111
 
 
112
 
static GdkPixbuf * num_pixmap[NUM_VALUES];
113
 
static GdkPixbuf * oper_pixmap[5];
114
 
static GdkPixbuf *button_pixmap = NULL;
115
 
 
116
 
static GnomeCanvasItem *oper_item[4];
117
 
static GnomeCanvasItem *num_item[MAX_NUMBER];
118
 
static GnomeCanvasItem *equal_item[NUMBER_OF_LEVELS];
119
 
static GnomeCanvasItem *calcul_line_item[NUMBER_OF_LEVELS*2];
120
 
static GnomeCanvasItem *calcul_line_item_back[NUMBER_OF_LEVELS*2];
121
 
static GnomeCanvasItem *result_item_front, *result_item_back;
122
 
 
123
 
static GnomeCanvasItem *algebra_guesscount_create_item(GnomeCanvasGroup *parent);
124
 
static void algebra_guesscount_destroy_all_items(void);
125
 
static void algebra_guesscount_next_level(void);
126
 
static gint item_event_num(GnomeCanvasItem *item, GdkEvent *event, gpointer data);
127
 
static gint item_event_oper(GnomeCanvasItem *item, GdkEvent *event, gpointer data);
128
 
static gint item_event_oper_moved(GnomeCanvasItem *item, GdkEvent *event, gpointer data);
129
 
 
130
 
static int generate_numbers();
131
 
static int token_result();
132
 
 
133
 
/* Description of this plugin */
134
 
static BoardPlugin menu_bp =
135
 
  {
136
 
    NULL,
137
 
    NULL,
138
 
    "Guess operations",
139
 
    "Guess operations",
140
 
    "Pascal Georges pascal.georges1@free.fr>",
141
 
    NULL,
142
 
    NULL,
143
 
    NULL,
144
 
    NULL,
145
 
    start_board,
146
 
    pause_board,
147
 
    end_board,
148
 
    is_our_board,
149
 
    NULL,
150
 
    NULL,
151
 
    set_level,
152
 
    NULL,
153
 
    NULL,
154
 
    NULL,
155
 
    NULL
156
 
  };
157
 
 
158
 
/* ==================================== */
159
 
/*
160
 
 * Main entry point mandatory for each Gcompris's game
161
 
 * ---------------------------------------------------
162
 
 */
163
 
GET_BPLUGIN_INFO(algebra_guesscount)
164
 
 
165
 
/* ==================================== */
166
 
// in : boolean TRUE = PAUSE : FALSE = CONTINUE
167
 
static void pause_board (gboolean pause){
168
 
  if(gcomprisBoard==NULL)
169
 
    return;
170
 
 
171
 
  if(gamewon == TRUE && pause == FALSE) {
172
 
    game_won();
173
 
  }
174
 
 
175
 
  board_paused = pause;
176
 
}
177
 
 
178
 
/* ==================================== */
179
 
static void start_board (GcomprisBoard *agcomprisBoard) {
180
 
  int i;
181
 
  gchar *str;
182
 
 
183
 
  if(agcomprisBoard!=NULL){
184
 
    gcomprisBoard=agcomprisBoard;
185
 
 
186
 
    // load pixmap files
187
 
    g_warning("loading pixmaps in start_board\n");
188
 
    for (i=0; i<NUM_VALUES; i++) {
189
 
      str = g_strdup_printf("%s/%d.png", gcomprisBoard->boarddir,num_values[i]);
190
 
      num_pixmap[i] = gc_pixmap_load(str);
191
 
      g_free(str);
192
 
    }
193
 
    for (i=0; i<5; i++) {
194
 
      str = g_strdup_printf("%s/%s.png", gcomprisBoard->boarddir,oper_images[i]);
195
 
      oper_pixmap[i] = gc_pixmap_load(str);
196
 
      g_free(str);
197
 
    }
198
 
 
199
 
    str = g_strdup_printf("%s/%s", gcomprisBoard->boarddir,"button.png");
200
 
    button_pixmap = gc_pixmap_load(str);
201
 
    g_free(str);
202
 
 
203
 
    gc_set_background(gnome_canvas_root(gcomprisBoard->canvas),"opt/animals/tiger1_by_Ralf_Schmode.jpg");
204
 
    gcomprisBoard->level=1;
205
 
    gcomprisBoard->maxlevel=NUMBER_OF_LEVELS;
206
 
    gcomprisBoard->sublevel=1;
207
 
    gcomprisBoard->number_of_sublevel=NUMBER_OF_SUBLEVELS; /* Go to next level after this number of 'play' */
208
 
    gc_score_start(SCORESTYLE_NOTE,
209
 
                         50,
210
 
                         gcomprisBoard->height - 50,
211
 
                         gcomprisBoard->number_of_sublevel);
212
 
    gc_bar_set(GC_BAR_LEVEL);
213
 
 
214
 
    algebra_guesscount_next_level();
215
 
 
216
 
    gamewon = FALSE;
217
 
 
218
 
    pause_board(FALSE);
219
 
  }
220
 
}
221
 
 
222
 
/* ==================================== */
223
 
static void end_board () {
224
 
  if(gcomprisBoard!=NULL) {
225
 
    pause_board(TRUE);
226
 
    gc_score_end();
227
 
    destroy_board();
228
 
    algebra_guesscount_destroy_all_items();
229
 
  }
230
 
  gcomprisBoard = NULL;
231
 
}
232
 
 
233
 
/* ==================================== */
234
 
static void set_level (guint level) {
235
 
  if(gcomprisBoard!=NULL) {
236
 
    gcomprisBoard->level=level;
237
 
    gcomprisBoard->sublevel=1;
238
 
    algebra_guesscount_next_level();
239
 
  }
240
 
}
241
 
 
242
 
/* ==================================== */
243
 
static gboolean is_our_board (GcomprisBoard *gcomprisBoard) {
244
 
  if (gcomprisBoard) {
245
 
    if(g_strcasecmp(gcomprisBoard->type, "algebra_guesscount")==0) {
246
 
      /* Set the plugin entry */
247
 
      gcomprisBoard->plugin=&menu_bp;
248
 
      return TRUE;
249
 
    }
250
 
  }
251
 
  return FALSE;
252
 
}
253
 
 
254
 
/* ==================================== */
255
 
/* set initial values for the next level */
256
 
static void algebra_guesscount_next_level() {
257
 
  gc_bar_set_level(gcomprisBoard);
258
 
 
259
 
  algebra_guesscount_destroy_all_items();
260
 
  gamewon = FALSE;
261
 
  token_count = 0;
262
 
 
263
 
  gc_score_set(gcomprisBoard->sublevel);
264
 
 
265
 
  /* Try the next level */
266
 
  algebra_guesscount_create_item(gnome_canvas_root(gcomprisBoard->canvas));
267
 
}
268
 
/* ==================================== */
269
 
/* Destroy all the items */
270
 
static void algebra_guesscount_destroy_all_items() {
271
 
  if(boardRootItem!=NULL)
272
 
    gtk_object_destroy (GTK_OBJECT(boardRootItem));
273
 
 
274
 
  boardRootItem = NULL;
275
 
}
276
 
/* ==================================== */
277
 
static int token_result() {
278
 
  int result, i;
279
 
 
280
 
  if (token_count < 2)
281
 
    return NO_RESULT;
282
 
 
283
 
  g_assert(ptr_token_selected[0]->isNumber);
284
 
  result = num_values[ptr_token_selected[0]->num];
285
 
 
286
 
  for (i=2; i<token_count; i+=2) {
287
 
    g_assert(!ptr_token_selected[i-1]->isNumber);
288
 
    switch (ptr_token_selected[i-1]->oper) {
289
 
    case '+' :  result += num_values[ptr_token_selected[i]->num];
290
 
      break;
291
 
    case '-' :          if (result - num_values[ptr_token_selected[i]->num] < 0)
292
 
      return NO_RESULT;
293
 
      result -= num_values[ptr_token_selected[i]->num];
294
 
      break;
295
 
    case 'x' :  result *= num_values[ptr_token_selected[i]->num];
296
 
      break;
297
 
    case ':' :          if (result%num_values[ptr_token_selected[i]->num] != 0)
298
 
      return NO_RESULT;
299
 
      result /= num_values[ptr_token_selected[i]->num];
300
 
      break;
301
 
    default : g_warning("bug in token_result()\n"); break;
302
 
    }
303
 
  }
304
 
  return result;
305
 
}
306
 
/* ==================================== */
307
 
static void update_line_calcul() {
308
 
  int line;
309
 
  char str[12];
310
 
 
311
 
  // finds which line has to be zeroed.
312
 
  if (token_count%2 == 0)
313
 
    line = (int)(token_count/2-1);
314
 
  else
315
 
    line = (int)(token_count/2);
316
 
 
317
 
  if(line==-1)
318
 
    return;
319
 
 
320
 
  sprintf(str, "%d",token_result());
321
 
  gnome_canvas_item_set(calcul_line_item[line*2],      "text", BLANK, NULL);
322
 
  gnome_canvas_item_set(calcul_line_item_back[line*2], "text", BLANK, NULL);
323
 
 
324
 
  if(line < gcomprisBoard->level-1) {                   /* No next line to update on last line */
325
 
    gnome_canvas_item_set(calcul_line_item[line*2+1],      "text", BLANK, NULL);
326
 
    gnome_canvas_item_set(calcul_line_item_back[line*2+1], "text", BLANK, NULL);
327
 
  }
328
 
 
329
 
}
330
 
/* ==================================== */
331
 
static int generate_numbers() {
332
 
  int i, r, j, result;
333
 
  gboolean minus, divide;
334
 
 
335
 
  for (i=0; i<gcomprisBoard->level+1; i++) {
336
 
    j = g_random_int_range(0,NUM_VALUES-1);
337
 
    answer_num_index[i] = j;
338
 
  }
339
 
 
340
 
  result = num_values[answer_num_index[0]];
341
 
  for (i=0; i<gcomprisBoard->level; i++) {
342
 
    // + and x can always be chosen, but we must ensure - and / are valid
343
 
    minus = (result - num_values[answer_num_index[i+1]] >= 0);
344
 
 
345
 
    if(gcomprisBoard->level > 2 && num_values[answer_num_index[i+1]] <= 5) {       /* Avoid div operator at lower level */
346
 
      divide = (result % num_values[answer_num_index[i+1]] == 0);
347
 
    } else {
348
 
      divide = 0;
349
 
    }
350
 
    r = 2 + minus + divide;
351
 
 
352
 
    switch (g_random_int_range(1,r)) {
353
 
    case 1 :
354
 
      answer_oper[i] = '+';
355
 
      result += num_values[answer_num_index[i+1]];
356
 
      break;
357
 
    case 2 :            // prevent result from getting too big and accept only < 10 bor the by operator
358
 
      if ( (result*num_values[answer_num_index[i+1]] < 1000 ) &&
359
 
           ( num_values[answer_num_index[i+1]] < 10) ) {
360
 
        answer_oper[i] = 'x';
361
 
        result *= num_values[answer_num_index[i+1]];
362
 
      } else {
363
 
        answer_oper[i] = '+';
364
 
        result += num_values[answer_num_index[i+1]];
365
 
      }
366
 
      break;
367
 
    case 3 :
368
 
      if (minus) {
369
 
        answer_oper[i] = '-';
370
 
        result -= num_values[answer_num_index[i+1]];
371
 
        g_assert(result >= 0);
372
 
      } else {
373
 
        answer_oper[i] = ':';
374
 
        g_assert(result%num_values[answer_num_index[i+1]] == 0);
375
 
        result /= num_values[answer_num_index[i+1]];
376
 
      }
377
 
      break;
378
 
    case 4 :
379
 
      if ( g_random_int_range(0,1) == 0) {
380
 
        answer_oper[i] = '-';
381
 
        result -= num_values[answer_num_index[i+1]];
382
 
        g_assert(result >= 0);
383
 
      } else {
384
 
        answer_oper[i] = ':';
385
 
        g_assert(result%num_values[answer_num_index[i+1]] == 0);
386
 
        result /= num_values[answer_num_index[i+1]];
387
 
      }
388
 
      break;
389
 
    default : g_warning("Bug in guesscount\n"); break;
390
 
    }
391
 
  }
392
 
  return result;
393
 
}
394
 
/* ==================================== */
395
 
static GnomeCanvasItem *algebra_guesscount_create_item(GnomeCanvasGroup *parent) {
396
 
  int i, xOffset, sid;
397
 
  char str[10];
398
 
 
399
 
  result_to_find = generate_numbers();
400
 
 
401
 
  boardRootItem = GNOME_CANVAS_GROUP(
402
 
                                     gnome_canvas_item_new (gnome_canvas_root(gcomprisBoard->canvas),
403
 
                                                            gnome_canvas_group_get_type (),
404
 
                                                            "x", (double) 0,
405
 
                                                            "y", (double) 0,
406
 
                                                            NULL));
407
 
 
408
 
  // the intermediate result, line by line, when empty is BLANK
409
 
  for (i=0; i<gcomprisBoard->level; i++) {
410
 
    calcul_line_item_back[i*2] = gnome_canvas_item_new (boardRootItem,
411
 
                                                        gnome_canvas_text_get_type (),
412
 
                                                        "text", BLANK,
413
 
                                                        "font", gc_skin_font_board_title_bold,
414
 
                                                        "x", (double) X_EQUAL+BUTTON_WIDTH*1.5 + 1,
415
 
                                                        "y", (double) y_equal_offset[i]+BUTTON_HEIGHT/2 + 1,
416
 
                                                        "anchor", GTK_ANCHOR_CENTER,
417
 
                                                        "fill_color", TEXT_COLOR_BACK,
418
 
                                                        NULL);
419
 
    calcul_line_item[i*2] = gnome_canvas_item_new (boardRootItem,
420
 
                                                   gnome_canvas_text_get_type (),
421
 
                                                   "text", BLANK,
422
 
                                                   "font", gc_skin_font_board_title_bold,
423
 
                                                   "x", (double) X_EQUAL+BUTTON_WIDTH*1.5,
424
 
                                                   "y", (double) y_equal_offset[i]+BUTTON_HEIGHT/2,
425
 
                                                   "anchor", GTK_ANCHOR_CENTER,
426
 
                                                   "fill_color", TEXT_COLOR_FRONT,
427
 
                                                   NULL);
428
 
  }
429
 
 
430
 
  for (i=0; i<gcomprisBoard->level-1; i++) {
431
 
    calcul_line_item_back[i*2+1] = gnome_canvas_item_new (boardRootItem,
432
 
                                                          gnome_canvas_text_get_type (),
433
 
                                                          "text", BLANK,
434
 
                                                          "font", gc_skin_font_board_title_bold,
435
 
                                                          "x", (double) X_NUM1+BUTTON_WIDTH/2 + 1,
436
 
                                                          "y", (double) y_equal_offset[i+1]+BUTTON_HEIGHT/2 + 1,
437
 
                                                          "anchor", GTK_ANCHOR_CENTER,
438
 
                                                          "fill_color", TEXT_COLOR_BACK,
439
 
                                                          NULL);
440
 
    calcul_line_item[i*2+1] = gnome_canvas_item_new (boardRootItem,
441
 
                                                     gnome_canvas_text_get_type (),
442
 
                                                     "text", BLANK,
443
 
                                                     "font", gc_skin_font_board_title_bold,
444
 
                                                     "x", (double) X_NUM1+BUTTON_WIDTH/2,
445
 
                                                     "y", (double) y_equal_offset[i+1]+BUTTON_HEIGHT/2,
446
 
                                                     "anchor", GTK_ANCHOR_CENTER,
447
 
                                                     "fill_color", TEXT_COLOR_FRONT,
448
 
                                                     NULL);
449
 
  }
450
 
 
451
 
  xOffset = (gcomprisBoard->width - 4 * BUTTON_WIDTH - 3 * HORIZONTAL_SEPARATION)/2;
452
 
  for (i=0; i<4; i++) {
453
 
    oper_item[i] = gnome_canvas_item_new (boardRootItem,
454
 
                                          gnome_canvas_pixbuf_get_type (),
455
 
                                          "pixbuf", oper_pixmap[i],
456
 
                                          "x", (double) xOffset ,
457
 
                                          "y", (double) Y_OPE,
458
 
                                          "width", (double) BUTTON_WIDTH,
459
 
                                          "height", (double) BUTTON_HEIGHT,
460
 
                                          "width_set", TRUE,
461
 
                                          "height_set", TRUE,
462
 
                                          NULL);
463
 
    xOffset += BUTTON_WIDTH+HORIZONTAL_SEPARATION;
464
 
    gtk_signal_connect(GTK_OBJECT(oper_item[i]), "event", (GtkSignalFunc) item_event_oper,
465
 
                       GINT_TO_POINTER(&(token_value[i*2+1])) );
466
 
    token_value[i*2+1].isNumber = FALSE;
467
 
    token_value[i*2+1].isMoved = FALSE;
468
 
    token_value[i*2+1].oper = oper_values[i];
469
 
  }
470
 
 
471
 
  // displays the target result
472
 
  sprintf(str,"%d",result_to_find);
473
 
  result_item_back = gnome_canvas_item_new (boardRootItem,
474
 
                                            gnome_canvas_text_get_type (),
475
 
                                            "text", str,
476
 
                                            "font", gc_skin_font_board_title_bold,
477
 
                                            "x", (double) xOffset+BUTTON_WIDTH +1,
478
 
                                            "y", (double) Y_OPE+BUTTON_HEIGHT/2 +1,
479
 
                                            "anchor", GTK_ANCHOR_CENTER,
480
 
                                            "fill_color", TEXT_RESULT_COLOR_BACK,
481
 
                                            NULL);
482
 
  result_item_front = gnome_canvas_item_new (boardRootItem,
483
 
                                             gnome_canvas_text_get_type (),
484
 
                                             "text", str,
485
 
                                             "font", gc_skin_font_board_title_bold,
486
 
                                             "x", (double) xOffset+BUTTON_WIDTH,
487
 
                                             "y", (double) Y_OPE+BUTTON_HEIGHT/2,
488
 
                                             "anchor", GTK_ANCHOR_CENTER,
489
 
                                             "fill_color", TEXT_RESULT_COLOR_FRONT,
490
 
                                             NULL);
491
 
 
492
 
  xOffset = (gcomprisBoard->width - (gcomprisBoard->level+1) * BUTTON_WIDTH - gcomprisBoard->level * HORIZONTAL_SEPARATION)/2;
493
 
  for (i=0; i<gcomprisBoard->level+1; i++) {
494
 
    num_item[i] = gnome_canvas_item_new (boardRootItem,
495
 
                                         gnome_canvas_pixbuf_get_type (),
496
 
                                         "pixbuf", num_pixmap[answer_num_index[i]],
497
 
                                         "x", (double) xOffset ,
498
 
                                         "y", (double) Y_NUM,
499
 
                                         "width", (double) BUTTON_WIDTH,
500
 
                                         "height", (double) BUTTON_HEIGHT,
501
 
                                         "width_set", TRUE,
502
 
                                         "height_set", TRUE,
503
 
                                         NULL);
504
 
    sid = gtk_signal_connect(GTK_OBJECT(num_item[i]), "event", (GtkSignalFunc) item_event_num,
505
 
                             (void *)&(token_value[i*2]));
506
 
    token_value[i*2].isNumber = TRUE;
507
 
    token_value[i*2].num = answer_num_index[i];
508
 
    token_value[i*2].signal_id = sid;
509
 
    token_value[i*2].item = num_item[i];
510
 
    token_value[i*2].isMoved = FALSE;
511
 
    token_value[i*2].xOffset_original = xOffset;
512
 
    xOffset += BUTTON_WIDTH+HORIZONTAL_SEPARATION;
513
 
  }
514
 
 
515
 
  // items "="
516
 
  for (i=0; i<gcomprisBoard->level; i++) {
517
 
    equal_item[i] = gnome_canvas_item_new (boardRootItem,
518
 
                                           gnome_canvas_pixbuf_get_type (),
519
 
                                           "pixbuf", oper_pixmap[4],
520
 
                                           "x", (double) X_EQUAL ,
521
 
                                           "y", (double) y_equal_offset[i],
522
 
                                           "width", (double) BUTTON_WIDTH,
523
 
                                           "height", (double) BUTTON_HEIGHT,
524
 
                                           "width_set", TRUE,
525
 
                                           "height_set", TRUE,
526
 
                                           NULL);
527
 
  }
528
 
 
529
 
  return NULL;
530
 
}
531
 
/* ==================================== */
532
 
static void game_won() {
533
 
  gcomprisBoard->sublevel++;
534
 
 
535
 
  if(gcomprisBoard->sublevel>gcomprisBoard->number_of_sublevel) {
536
 
    /* Try the next level */
537
 
    gcomprisBoard->sublevel=1;
538
 
    gcomprisBoard->level++;
539
 
 
540
 
    if(gcomprisBoard->level>gcomprisBoard->maxlevel) {
541
 
      gc_bonus_end_display(GC_BOARD_FINISHED_TUXPLANE);
542
 
      return;
543
 
    }
544
 
    gc_set_background(gnome_canvas_root(gcomprisBoard->canvas),background_images[gcomprisBoard->level-1]);
545
 
  }
546
 
  algebra_guesscount_next_level();
547
 
}
548
 
 
549
 
/* ==================================== */
550
 
static void process_time(){
551
 
  if (process_time_id) {
552
 
    gtk_timeout_remove (process_time_id);
553
 
    process_time_id = 0;
554
 
  }
555
 
  gc_bonus_display(gamewon, GC_BONUS_RANDOM);
556
 
}
557
 
/* ==================================== */
558
 
static int oper_char_to_pixmap_index(char oper) {
559
 
  int i;
560
 
 
561
 
  g_assert(oper == '+' || oper == '-' || oper == 'x' || oper == ':' || oper == '=');
562
 
 
563
 
  for (i=0; i<5; i++)
564
 
    if (oper_values[i] == oper)
565
 
      return i;
566
 
 
567
 
  return -1;
568
 
}
569
 
/* ==================================== */
570
 
static gint item_event_oper(GnomeCanvasItem *item, GdkEvent *event, gpointer data){
571
 
  token *t = (  token *)data;
572
 
 
573
 
  GnomeCanvasItem * tmp_item;
574
 
 
575
 
  if(board_paused)
576
 
    return FALSE;
577
 
  // first verify it is oper turn
578
 
  if (token_count % 2 == 0 || token_count >= 2*gcomprisBoard->level+1)
579
 
    return FALSE;
580
 
 
581
 
  switch (event->type) {
582
 
  case GDK_BUTTON_PRESS:
583
 
    gc_sound_play_ogg ("sounds/flip.wav", NULL);
584
 
    ptr_token_selected[token_count] = t;
585
 
    tmp_item = gnome_canvas_item_new (boardRootItem,
586
 
                                      gnome_canvas_pixbuf_get_type (),
587
 
                                      "pixbuf", oper_pixmap[oper_char_to_pixmap_index(t->oper)],
588
 
                                      "x", (double) x_token_offset[token_count],
589
 
                                      "y", (double) y_token_offset[token_count],
590
 
                                      "width", (double) BUTTON_WIDTH,
591
 
                                      "height", (double) BUTTON_HEIGHT,
592
 
                                      "width_set", TRUE,
593
 
                                      "height_set", TRUE,
594
 
                                      NULL);
595
 
    token_count++;
596
 
    gtk_signal_connect(GTK_OBJECT(tmp_item), "event", (GtkSignalFunc) item_event_oper_moved, GINT_TO_POINTER(token_count));
597
 
    break;
598
 
  default : break;
599
 
  }
600
 
  return FALSE;
601
 
}
602
 
/* ==================================== */
603
 
static gint item_event_oper_moved(GnomeCanvasItem *item, GdkEvent *event, gpointer data){
604
 
  int count = GPOINTER_TO_INT(data);
605
 
 
606
 
  if(board_paused)
607
 
    return FALSE;
608
 
  // we only allow the undo of an operation if it is the last element displayed
609
 
  switch (event->type) {
610
 
  case GDK_BUTTON_PRESS:
611
 
    gc_sound_play_ogg ("sounds/flip.wav", NULL);
612
 
    if (count == token_count) {
613
 
      gtk_object_destroy (GTK_OBJECT(item));
614
 
      token_count--;
615
 
      update_line_calcul();
616
 
    }
617
 
    break;
618
 
  default : break;
619
 
  }
620
 
  return FALSE;
621
 
}
622
 
/* ==================================== */
623
 
static gint item_event_num(GnomeCanvasItem *item, GdkEvent *event, gpointer data){
624
 
  token *t = (token *)data;
625
 
  char str[12];
626
 
 
627
 
  if(board_paused)
628
 
    return FALSE;
629
 
 
630
 
  switch (event->type){
631
 
  case GDK_BUTTON_PRESS:
632
 
    gc_sound_play_ogg ("sounds/bleep.wav", NULL);
633
 
    if (t->isMoved) {
634
 
      if (item != ptr_token_selected[token_count-1]->item)
635
 
        return FALSE;
636
 
      // we put back in its original place a number item
637
 
      gc_item_absolute_move(item, t->xOffset_original, Y_NUM);
638
 
      token_count--;
639
 
      update_line_calcul();
640
 
      t->isMoved = FALSE;
641
 
    } else { // the item is at its original place
642
 
      if (token_count % 2 == 1 || token_count > 2*gcomprisBoard->level+1)
643
 
        return FALSE;
644
 
      token_count++;
645
 
      ptr_token_selected[token_count-1] = t;
646
 
      // some operations are illegal A - B must be > 0 and A/B an integer
647
 
      if (token_result() == NO_RESULT && token_count != 1) {
648
 
        token_count--;
649
 
        return FALSE;
650
 
      }
651
 
 
652
 
      gc_item_absolute_move(item, x_token_offset[token_count-1], y_token_offset[token_count-1]);
653
 
      t->isMoved = TRUE;
654
 
 
655
 
      // update result text items
656
 
      if (token_count != 1 && token_count % 2 == 1) {
657
 
        sprintf(str,"%d",token_result());
658
 
 
659
 
        gnome_canvas_item_set(calcul_line_item[token_count-3], "text", str, NULL);
660
 
        gnome_canvas_item_set(calcul_line_item_back[token_count-3], "text", str, NULL);
661
 
 
662
 
        if(token_count < 2*gcomprisBoard->level+1) {                    /* No next line to update on last line */
663
 
          gnome_canvas_item_set(calcul_line_item[token_count-2], "text", str, NULL);
664
 
          gnome_canvas_item_set(calcul_line_item_back[token_count-2], "text", str, NULL);
665
 
        }
666
 
 
667
 
        gamewon = (result_to_find == token_result());
668
 
        if(gamewon)
669
 
          process_time_id = gtk_timeout_add (2000, (GtkFunction) process_time, NULL);
670
 
 
671
 
 
672
 
      }
673
 
    }
674
 
    break;
675
 
  default : break;
676
 
  }
677
 
  return FALSE;
678
 
}
679
 
/* ======================================= */
680
 
static void destroy_board() {
681
 
  int i;
682
 
 
683
 
  for (i=0; i<NUM_VALUES; i++)
684
 
    gdk_pixbuf_unref(num_pixmap[i]);
685
 
  for (i=0; i<5; i++)
686
 
    gdk_pixbuf_unref(oper_pixmap[i]);
687
 
}