Back to index

gcompris  8.2.2
railroad.c
Go to the documentation of this file.
00001 /* gcompris - railroad.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 #define SOUNDLISTFILE PACKAGE
00023 
00024 static GcomprisBoard *gcomprisBoard = NULL;
00025 static gboolean board_paused = TRUE;
00026 
00027 static void           start_board (GcomprisBoard *agcomprisBoard);
00028 static void           pause_board (gboolean pause);
00029 static void           end_board (void);
00030 static gboolean              is_our_board (GcomprisBoard *gcomprisBoard);
00031 static void           set_level (guint level);
00032 static int gamewon;
00033 static void           process_ok(void);
00034 static void           game_won(void);
00035 static void           repeat(void);
00036 static void           animate_model(void);
00037 static gboolean              animate_step(void);
00038 
00039 #define ENGINES 9
00040 #define WAGONS 13
00041 #define NUMBER_OF_SUBLEVELS 3
00042 #define NUMBER_OF_LEVELS 3
00043 #define MODEL_MAX_SIZE NUMBER_OF_LEVELS+1
00044 
00045 static const int line[] = { 100,180,260,340, 420, 500};
00046 static gboolean animation_pending;
00047 static gint animation_count = 0;
00048 
00049 static GnomeCanvasGroup *boardRootItem = NULL;
00050 
00051 static GnomeCanvasGroup *allwagonsRootItem = NULL;
00052 static GnomeCanvasGroup *modelRootItem = NULL;
00053 static GnomeCanvasGroup *answerRootItem = NULL;
00054 
00055 static GList * listPixmapEngines = NULL;
00056 static GList * listPixmapWagons = NULL;
00057 
00058 // ==========================================
00059 // In all the lists below, 0 is the LEFTmost vehicle|
00060 // ==========================================
00061 // contains the list of vehicles to be found.
00062 static GnomeCanvasItem *item_model[MODEL_MAX_SIZE];
00063 // contains the list of vehicles proposed by child.
00064 static GList *item_answer_list = NULL;
00065 // contains the list of vehicles proposed by child.
00066 static GList *int_answer_list = NULL;
00067 // contains the list of vehicles to be found
00068 static GList *int_model_list = NULL;
00069 
00070 static int model_size = 0;
00071 static gint timer_id;
00072 
00073 static GnomeCanvasItem *railroad_create_item(GnomeCanvasGroup *parent);
00074 static void railroad_destroy_all_items(void);
00075 static void railroad_next_level(void);
00076 static gint item_event(GnomeCanvasItem *item, GdkEvent *event, gpointer data);
00077 static gint answer_event(GnomeCanvasItem *item, GdkEvent *event, gpointer data);
00078 
00079 static void reposition_model(void);
00080 static void reposition_answer(void);
00081 
00082 // helper function because g_list_free does not actually reset a list
00083 static GList * reset_list(GList * list);
00084 static void reset_all_lists(void);
00085 
00086 /* Description of this plugin */
00087 static BoardPlugin menu_bp =
00088   {
00089     NULL,
00090     NULL,
00091     N_("Memory game"),
00092     N_("Build a train according to the model"),
00093     "Pascal Georges pascal.georges1@free.fr>",
00094     NULL,
00095     NULL,
00096     NULL,
00097     NULL,
00098     start_board,
00099     pause_board,
00100     end_board,
00101     is_our_board,
00102     NULL,
00103     process_ok,
00104     set_level,
00105     NULL,
00106     repeat,
00107     NULL,
00108     NULL
00109   };
00110 
00111 /*
00112  * Main entry point mandatory for each Gcompris's game
00113  * ---------------------------------------------------
00114  *
00115  */
00116 
00117 GET_BPLUGIN_INFO(railroad)
00118 
00119 /*
00120  * in : boolean TRUE = PAUSE : FALSE = CONTINUE
00121  *
00122  */
00123 static void pause_board (gboolean pause)
00124 {
00125   if(gcomprisBoard==NULL)
00126     return;
00127 
00128   if(gamewon == TRUE && pause == FALSE) /* the game is won */
00129     {
00130       game_won();
00131     }
00132 
00133   board_paused = pause;
00134 }
00135 
00136 /* ======================================= */
00137 static void start_board (GcomprisBoard *agcomprisBoard)
00138 {
00139   int i;
00140   char *str;
00141   GdkPixbuf *pixmap = NULL;
00142 
00143   if(agcomprisBoard!=NULL)
00144     {
00145       gcomprisBoard=agcomprisBoard;
00146       gc_set_background(gnome_canvas_root(gcomprisBoard->canvas),
00147                            "railroad/railroad-bg.png");
00148 
00149       for (i=0; i<ENGINES; i++) {
00150        str = g_strdup_printf("railroad/loco%d.png", i+1);
00151        pixmap = gc_pixmap_load(str);
00152        listPixmapEngines = g_list_append(listPixmapEngines, pixmap);
00153        g_free(str);
00154       }
00155 
00156       for (i=0; i<WAGONS; i++) {
00157        str = g_strdup_printf("railroad/wagon%d.png", i+1);
00158        pixmap = gc_pixmap_load(str);
00159        listPixmapWagons = g_list_append(listPixmapWagons, pixmap);
00160        g_free(str);
00161       }
00162 
00163       animation_pending = FALSE;
00164       gcomprisBoard->level=1;
00165       gcomprisBoard->maxlevel=NUMBER_OF_LEVELS;
00166       gcomprisBoard->sublevel=1;
00167       gcomprisBoard->number_of_sublevel=NUMBER_OF_SUBLEVELS; /* 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 
00173 
00174       str = gc_skin_image_get("button_reload.png");
00175       pixmap = gc_pixmap_load(str);
00176       g_free(str);
00177       if(pixmap) {
00178        gc_bar_set_repeat_icon(pixmap);
00179        gdk_pixbuf_unref(pixmap);
00180        gc_bar_set(GC_BAR_LEVEL|GC_BAR_OK|GC_BAR_REPEAT_ICON);
00181       } else {
00182        gc_bar_set(GC_BAR_LEVEL|GC_BAR_OK|GC_BAR_REPEAT);
00183       }
00184 
00185       railroad_next_level();
00186 
00187       gamewon = FALSE;
00188       pause_board(FALSE);
00189     }
00190 }
00191 /* ======================================= */
00192 static void end_board ()
00193 {
00194   GdkPixbuf * pixmap = NULL;
00195   // If we don't end animation, there may be a segfault if leaving while the animation is pending
00196   if (timer_id) {
00197     gtk_timeout_remove (timer_id);
00198     timer_id = 0;
00199   }
00200 
00201   if(gcomprisBoard!=NULL)
00202     {
00203       pause_board(TRUE);
00204       gc_score_end();
00205       railroad_destroy_all_items();
00206 
00207       while(g_list_length(listPixmapEngines)>0) {
00208        pixmap = g_list_nth_data(listPixmapEngines, 0);
00209        listPixmapEngines = g_list_remove (listPixmapEngines, pixmap);
00210        gdk_pixbuf_unref(pixmap);
00211       }
00212 
00213       while(g_list_length(listPixmapWagons)>0) {
00214        pixmap = g_list_nth_data(listPixmapWagons, 0);
00215        listPixmapWagons = g_list_remove (listPixmapWagons, pixmap);
00216        gdk_pixbuf_unref(pixmap);
00217       }
00218 
00219     }
00220   gcomprisBoard = NULL;
00221 }
00222 
00223 /* ======================================= */
00224 static void set_level (guint level)
00225 {
00226 
00227   if(gcomprisBoard!=NULL)
00228     {
00229       gcomprisBoard->level=level;
00230       gcomprisBoard->sublevel=1;
00231       railroad_next_level();
00232     }
00233 }
00234 /* ======================================= */
00235 gboolean is_our_board (GcomprisBoard *gcomprisBoard)
00236 {
00237   if (gcomprisBoard)
00238     {
00239       if(g_strcasecmp(gcomprisBoard->type, "railroad")==0)
00240        {
00241          /* Set the plugin entry */
00242          gcomprisBoard->plugin=&menu_bp;
00243 
00244          return TRUE;
00245        }
00246     }
00247   return FALSE;
00248 }
00249 
00250 /* ======================================= */
00251 static void repeat ()
00252 {
00253   if(gcomprisBoard!=NULL && !animation_pending) {
00254     gnome_canvas_item_hide(GNOME_CANVAS_ITEM(answerRootItem));
00255     gnome_canvas_item_show(GNOME_CANVAS_ITEM(modelRootItem));
00256     gnome_canvas_item_hide(GNOME_CANVAS_ITEM(allwagonsRootItem));
00257     reposition_model();
00258     animate_model();
00259   }
00260 }
00261 
00262 /* ==================================== */
00263 /* set initial values for the next level */
00264 static void railroad_next_level()
00265 {
00266   gc_bar_set_level(gcomprisBoard);
00267 
00268   reset_all_lists();
00269   // I have big troubles with the GList API : the worst I have ever seen !
00270   g_assert(g_list_length(item_answer_list) == 0 && g_list_length(int_answer_list) == 0 && g_list_length(int_model_list) == 0);
00271 
00272   model_size = 0;
00273 
00274   railroad_destroy_all_items();
00275   gamewon = FALSE;
00276   gc_score_set(gcomprisBoard->sublevel);
00277 
00278   /* Try the next level */
00279   railroad_create_item(gnome_canvas_root(gcomprisBoard->canvas));
00280 }
00281 /* ==================================== */
00282 /* Destroy all the items */
00283 static void railroad_destroy_all_items()
00284 {
00285   if(boardRootItem!=NULL)
00286     gtk_object_destroy (GTK_OBJECT(boardRootItem));
00287 
00288   boardRootItem = NULL;
00289 }
00290 /* ==================================== */
00291 static GnomeCanvasItem *railroad_create_item(GnomeCanvasGroup *parent)
00292 {
00293   int xOffset = 0, yOffset = 0;
00294   int i, r, l = 1;
00295   GdkPixbuf * pixmap = NULL;
00296   GnomeCanvasItem *item;
00297 
00298   boardRootItem = GNOME_CANVAS_GROUP(
00299                                  gnome_canvas_item_new (parent,
00300                                                      gnome_canvas_group_get_type (),
00301                                                      "x", (double) 0,
00302                                                      "y", (double) 0,
00303                                                      NULL));
00304   /* Create a root group for the answer */
00305   answerRootItem = GNOME_CANVAS_GROUP(
00306                                   gnome_canvas_item_new (boardRootItem,
00307                                                       gnome_canvas_group_get_type (),
00308                                                       "x", (double) 0,
00309                                                       "y", (double) 0,
00310                                                       NULL));
00311 
00312   // Create the vehicules
00313   allwagonsRootItem = GNOME_CANVAS_GROUP(
00314                                     gnome_canvas_item_new (boardRootItem,
00315                                                         gnome_canvas_group_get_type (),
00316                                                         "x", (double) 0,
00317                                                         "y", (double) 0,
00318                                                         NULL));
00319 
00320   for (i=0; i<ENGINES+WAGONS; i++) {
00321     if (i<ENGINES)
00322       pixmap = g_list_nth_data(listPixmapEngines, i);
00323     else
00324       pixmap = g_list_nth_data(listPixmapWagons, i-ENGINES);
00325 
00326     if ( (xOffset + gdk_pixbuf_get_width(pixmap)) >= gcomprisBoard->width) {
00327       xOffset = 0;
00328       l++;
00329     }
00330     yOffset = line[l] - gdk_pixbuf_get_height(pixmap);
00331 
00332     item = gnome_canvas_item_new (allwagonsRootItem,
00333                               gnome_canvas_pixbuf_get_type (),
00334                               "pixbuf",  pixmap,
00335                               "x",  (double) xOffset,
00336                               "y",  (double) yOffset,
00337                               NULL);
00338     xOffset += gdk_pixbuf_get_width(pixmap);
00339 
00340     gtk_signal_connect(GTK_OBJECT(item), "event", (GtkSignalFunc) item_event,
00341                      GINT_TO_POINTER(i));
00342 
00343   }
00344   // hide them
00345   gnome_canvas_item_hide(GNOME_CANVAS_ITEM(allwagonsRootItem));
00346 
00347   // construct the model to be recognized
00348   modelRootItem = GNOME_CANVAS_GROUP(
00349                                  gnome_canvas_item_new (boardRootItem,
00350                                                      gnome_canvas_group_get_type (),
00351                                                      "x", (double) 0,
00352                                                      "y", (double) 0,
00353                                                      NULL));
00354 
00355   yOffset = line[0];
00356   xOffset = 0;
00357   model_size = gcomprisBoard->level +1; // engine + cars
00358   // First the cars, depending of the level
00359   for (i=0; i<model_size-1; i++) {
00360     r = (int)(((float) WAGONS)*rand()/(RAND_MAX+1.0));
00361     g_assert( r >=0 && r < WAGONS);
00362     // keep track of the answer
00363     int_model_list = g_list_append(int_model_list, GINT_TO_POINTER(r+ENGINES));
00364     pixmap = g_list_nth_data(listPixmapWagons, r);
00365     g_assert(i >= 0 && i<MODEL_MAX_SIZE);
00366     item_model[i] =gnome_canvas_item_new (modelRootItem,
00367                                      gnome_canvas_pixbuf_get_type (),
00368                                      "pixbuf",  pixmap,
00369                                      "x",  (double) xOffset,
00370                                      "y",  (double) yOffset - gdk_pixbuf_get_height(pixmap),
00371                                      NULL);
00372     xOffset  += gdk_pixbuf_get_width(pixmap);
00373   }
00374 
00375   // Then the engine
00376   r = (int)(((float) ENGINES)*rand()/(RAND_MAX+1.0));
00377   g_assert( r >=0 && r < ENGINES);
00378   // keep track of the answer
00379   int_model_list = g_list_append(int_model_list, GINT_TO_POINTER(r));
00380   pixmap = g_list_nth_data(listPixmapEngines, r);
00381   item_model[model_size-1] =gnome_canvas_item_new (modelRootItem,
00382                                              gnome_canvas_pixbuf_get_type (),
00383                                              "pixbuf",  pixmap,
00384                                              "x",  (double) xOffset,
00385                                              "y",  (double) yOffset  - gdk_pixbuf_get_height(pixmap),
00386                                              NULL);
00387 
00388   animate_model();
00389 
00390   return NULL;
00391 }
00392 /* ==================================== */
00393 static void game_won()
00394 {
00395   gcomprisBoard->sublevel++;
00396 
00397   if(gcomprisBoard->sublevel>gcomprisBoard->number_of_sublevel) {
00398     /* Try the next level */
00399     gcomprisBoard->sublevel=1;
00400     gcomprisBoard->level++;
00401     if(gcomprisBoard->level>gcomprisBoard->maxlevel) { // the current board is finished : bail out
00402       gc_bonus_end_display(BOARD_FINISHED_RANDOM);
00403       return;
00404     }
00405     gc_sound_play_ogg ("sounds/bonus.ogg", NULL);
00406   }
00407   railroad_next_level();
00408 }
00409 
00410 /* ==================================== */
00411 static void process_ok()
00412 {
00413   int i;
00414 
00415   gamewon = TRUE;
00416 
00417   // DEBUG
00418   g_warning("l answer = %d\tl model = %d\n", g_list_length(int_answer_list), g_list_length(int_model_list));
00419   if (g_list_length(int_answer_list) != g_list_length(int_model_list))
00420     gamewon = FALSE;
00421   else
00422     for (i=0; i<g_list_length(int_answer_list); i++) {
00423       if ( GPOINTER_TO_INT(g_list_nth_data(int_answer_list,i)) != GPOINTER_TO_INT(g_list_nth_data(int_model_list,i))) {
00424        printf("pour i= %d --> différent\n", i);
00425        gamewon = FALSE;
00426        break;
00427       }
00428     }
00429   // DUMP lists
00430   g_warning("answer:\n");
00431   for (i=0; i<g_list_length(int_answer_list); i++)
00432     g_warning(" i = \t%d val = \t%d\n", i, GPOINTER_TO_INT(g_list_nth_data(int_answer_list,i)) );
00433   g_warning("model:\n");
00434   for (i=0; i<g_list_length(int_model_list); i++)
00435     g_warning(" i = \t%d val = \t%d\n", i, GPOINTER_TO_INT(g_list_nth_data(int_model_list,i)) );
00436 
00437   gc_bonus_display(gamewon, BONUS_FLOWER);
00438 }
00439 /* ==================================== */
00440 static gint item_event(GnomeCanvasItem *item, GdkEvent *event, gpointer data) {
00441   double item_x, item_y;
00442   int item_number;
00443   GdkPixbuf * pixmap = NULL;
00444   int i, xOffset = 0;
00445   GnomeCanvasItem * local_item;
00446   double dx1, dy1, dx2, dy2;
00447   item_number = GPOINTER_TO_INT(data);
00448 
00449   // we don't allow any input until train is gone
00450   if (animation_pending)
00451     return FALSE;
00452 
00453   item_x = event->button.x;
00454   item_y = event->button.y;
00455   gnome_canvas_item_w2i(item->parent, &item_x, &item_y);
00456 
00457   if(board_paused)
00458     return FALSE;
00459 
00460   switch (event->type)
00461     {
00462     case GDK_BUTTON_PRESS:
00463       g_warning("GDK_BUTTON_PRESS item %d\tlength answer = %d\n",item_number,g_list_length(item_answer_list));
00464       xOffset = 0;
00465       for (i=0; i<g_list_length(item_answer_list); i++) {
00466        gnome_canvas_item_get_bounds(g_list_nth_data(item_answer_list,i), &dx1, &dy1, &dx2, &dy2);
00467        xOffset += dx2-dx1;
00468       }
00469       if (item_number < ENGINES)
00470        pixmap = g_list_nth_data(listPixmapEngines, item_number);
00471       else
00472        pixmap = g_list_nth_data(listPixmapWagons, item_number-ENGINES);
00473 
00474       local_item =gnome_canvas_item_new (answerRootItem,
00475                                     gnome_canvas_pixbuf_get_type (),
00476                                     "pixbuf",  pixmap,
00477                                     "x",  (double) xOffset,
00478                                     "y",  (double) line[0] - gdk_pixbuf_get_height(pixmap),
00479                                     NULL);
00480       item_answer_list = g_list_append(item_answer_list, local_item);
00481       int_answer_list = g_list_append(int_answer_list,GINT_TO_POINTER(item_number));
00482       //      printf("added %d to int_answer_list\n", item_number);
00483       gtk_signal_connect(GTK_OBJECT(local_item), "event", (GtkSignalFunc) answer_event, GINT_TO_POINTER( g_list_length(item_answer_list)-1 ));
00484       break;
00485 
00486     default:
00487       break;
00488     }
00489   return FALSE;
00490 }
00491 /* ==================================== */
00492 /* Used to delete a vehicule at the top (the proposed answer) */
00493 static gint answer_event(GnomeCanvasItem *item, GdkEvent *event, gpointer data) {
00494   double item_x, item_y;
00495   int item_number, i;
00496   GnomeCanvasItem *local_item;
00497   item_number = GPOINTER_TO_INT(data);
00498   // we don't allow any input until train is gone
00499   if (animation_pending)
00500     return FALSE;
00501 
00502   item_x = event->button.x;
00503   item_y = event->button.y;
00504   gnome_canvas_item_w2i(item->parent, &item_x, &item_y);
00505 
00506   if(board_paused)
00507     return FALSE;
00508 
00509   switch (event->type)
00510     {
00511     case GDK_BUTTON_PRESS:
00512       g_warning("Deleting %d\n",item_number);
00513       local_item = g_list_nth_data(item_answer_list,item_number);
00514       item_answer_list = g_list_remove( item_answer_list, local_item );
00515       //      gtk_signal_disconnect(GTK_OBJECT(local_item), (GtkSignalFunc) answer_event, NULL);
00516       gtk_object_destroy (GTK_OBJECT(local_item));
00517       int_answer_list = g_list_remove(int_answer_list, g_list_nth_data(int_answer_list, item_number) );
00518       reposition_answer();
00519       // setup the signals for the cars at the right side of the deleted object
00520       for (i=item_number; i<g_list_length(item_answer_list); i++) {
00521        local_item = g_list_nth_data(item_answer_list, i);
00522        gtk_signal_disconnect_by_func(GTK_OBJECT(local_item), (GtkSignalFunc) answer_event, GINT_TO_POINTER( i+1 ));
00523         gtk_signal_connect(GTK_OBJECT(local_item),"event", (GtkSignalFunc) answer_event, GINT_TO_POINTER( i ));
00524       }
00525       break;
00526 
00527     default:
00528       break;
00529     }
00530   return FALSE;
00531 }
00532 /* ==================================== */
00533 static void reposition_answer() {
00534   double dx1, dy1, dx2, dy2;
00535   int i;
00536   int xOffset = 0;
00537   GnomeCanvasItem * item = NULL;
00538 
00539   if(!gcomprisBoard)
00540     return;
00541 
00542   g_warning("+++ reposition_answer\n");
00543   for (i=0; i<g_list_length(item_answer_list); i++) {
00544     item = g_list_nth_data(item_answer_list,i);
00545     gnome_canvas_item_get_bounds(item, &dx1, &dy1, &dx2, &dy2);
00546     gnome_canvas_item_move(item, xOffset-dx1, line[0]-dy2);
00547     xOffset += dx2-dx1;
00548   }
00549 }
00550 /* ==================================== */
00551 static void reposition_model() {
00552   double dx1, dy1, dx2, dy2;
00553   int i;
00554   int xOffset = 0;
00555   GnomeCanvasItem * item = NULL;
00556 
00557   if(!gcomprisBoard)
00558     return;
00559 
00560   g_warning("+++ reposition_model\n");
00561   gnome_canvas_item_move(GNOME_CANVAS_ITEM(modelRootItem), 0, 0);
00562   for (i=0; i<model_size; i++) {
00563     item = item_model[i];
00564     gnome_canvas_item_get_bounds(item, &dx1, &dy1, &dx2, &dy2);
00565     gnome_canvas_item_move(item, xOffset-dx1, line[0]-dy2);
00566     xOffset += dx2-dx1;
00567   }
00568 }
00569 
00570 /* ==================================== */
00571 static gboolean animate_step() {
00572   double step = 0;
00573 
00574   // this defines how the train waits before start
00575 #define MODEL_PAUSE 30
00576   //   printf("+++animate_step %d \n",animation_count);
00577 
00578   if(board_paused)
00579     return TRUE;
00580 
00581   if(!gcomprisBoard)
00582     return FALSE;
00583 
00584   animation_count++;
00585 
00586   if (animation_count < MODEL_PAUSE)
00587     return TRUE;
00588 
00589   if (animation_count >= 160+MODEL_PAUSE) {
00590     if (timer_id) {
00591       gtk_timeout_remove (timer_id);
00592       timer_id = 0;
00593     }
00594     animation_pending = FALSE;
00595     gnome_canvas_item_hide(GNOME_CANVAS_ITEM(modelRootItem));
00596     /* Move back the model to its 0 position */
00597     gnome_canvas_item_set(GNOME_CANVAS_ITEM(modelRootItem),
00598                        "x", 0.0,
00599                        NULL);
00600 
00601     gnome_canvas_item_show(GNOME_CANVAS_ITEM(allwagonsRootItem));
00602     gnome_canvas_item_show(GNOME_CANVAS_ITEM(answerRootItem));
00603     return FALSE;
00604   }
00605 
00606   step = (double) (animation_count-MODEL_PAUSE) / 50.0;
00607   step *= step;
00608 
00609   gnome_canvas_item_move(GNOME_CANVAS_ITEM(modelRootItem), step, 0.0);
00610 
00611   return TRUE;
00612 }
00613 /* ==================================== */
00614 static void animate_model() {
00615   animation_pending = TRUE;
00616   animation_count = 0;
00617 
00618   gc_sound_play_ogg( "sounds/train.ogg", NULL );
00619 
00620   // warning : if timeout is too low, the model will not be displayed
00621   timer_id = gtk_timeout_add (100, (GtkFunction) animate_step, NULL);
00622 }
00623 /* ==================================== */
00624 static void reset_all_lists(void) {
00625   GnomeCanvasItem *item;
00626 
00627   int_model_list = reset_list(int_model_list);
00628   int_answer_list = reset_list(int_answer_list);
00629 
00630   while(g_list_length(item_answer_list)>0) {
00631     item = g_list_nth_data(item_answer_list, 0);
00632     item_answer_list = g_list_remove (item_answer_list, item);
00633     // causes segfaults
00634     //        gtk_object_destroy (GTK_OBJECT(item));
00635   }
00636 
00637 }
00638 /* ==================================== */
00639 static GList * reset_list(GList * list) {
00640   while (g_list_length(list) > 0)
00641     list = g_list_remove(list, g_list_nth_data(list,0));
00642 
00643   return list;
00644 }