Back to index

gcompris  8.2.2
hanoi.c
Go to the documentation of this file.
00001 /* gcompris - hanoi.c
00002  *
00003  * Copyright (C) 2003 Bruno Coudoin
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    game_won(void);
00034 
00035 static GnomeCanvasGroup *boardRootItem = NULL;
00036 
00037 static GnomeCanvasItem      *hanoi_create_item(GnomeCanvasGroup *parent);
00038 static void           hanoi_destroy_all_items(void);
00039 static void           hanoi_next_level(void);
00040 
00041 /*
00042  * Contains the piece information
00043  */
00044 typedef struct {
00045   GnomeCanvasItem *item;
00046   GnomeCanvasItem *item_text;
00047   gint i;
00048   gint j;
00049   double x;
00050   double y;
00051   double xt;
00052   double yt;
00053   gboolean on_top;
00054   gint color;
00055 } PieceItem;
00056 
00057 static gint           item_event(GnomeCanvasItem *item, GdkEvent *event, PieceItem *data);
00058 
00059 /* This contains the layout of the pieces */
00060 #define MAX_NUMBER_X 10
00061 #define MAX_NUMBER_Y 10
00062 static PieceItem *position[MAX_NUMBER_X][MAX_NUMBER_Y];
00063 
00064 static int number_of_item = 0;
00065 static int number_of_item_x = 0;
00066 static int number_of_item_y = 0;
00067 static int item_width;
00068 static int item_height;
00069 
00070 static guint colorlist [] =
00071   {
00072     0x00FFFFFF,
00073     0xA00000FF,
00074     0xF00000FF,
00075     0x00A000FF,
00076     0x00F000FF,
00077     0x0000AAFF,
00078     0x0000FFFF,
00079     0x505000FF,
00080     0xA0A000FF,
00081     0xF0F000FF,
00082     0x005050FF,
00083     0x00A0A0FF,
00084     0x500050FF,
00085     0xA000A0FF,
00086     0xF000F0FF
00087   };
00088 #define NUMBER_OF_COLOR G_N_ELEMENTS(colorlist)
00089 
00090 
00091 /* Description of this plugin */
00092 static BoardPlugin menu_bp =
00093   {
00094     NULL,
00095     NULL,
00096     N_("Simplified Tower of Hanoi"),
00097     N_("Reproduce the given tower"),
00098     "Bruno Coudoin <bruno.coudoin@free.fr>",
00099     NULL,
00100     NULL,
00101     NULL,
00102     NULL,
00103     start_board,
00104     pause_board,
00105     end_board,
00106     is_our_board,
00107     NULL,
00108     NULL,
00109     set_level,
00110     NULL,
00111     NULL,
00112     NULL,
00113     NULL
00114   };
00115 
00116 /*
00117  * Main entry point mandatory for each Gcompris's game
00118  * ---------------------------------------------------
00119  *
00120  */
00121 
00122 GET_BPLUGIN_INFO(hanoi)
00123 
00124 /*
00125  * in : boolean TRUE = PAUSE : FALSE = CONTINUE
00126  *
00127  */
00128 static void pause_board (gboolean pause)
00129 {
00130   if(gcomprisBoard==NULL)
00131     return;
00132 
00133   if(gamewon == TRUE && pause == FALSE) /* the game is won */
00134     {
00135       game_won();
00136     }
00137 
00138   board_paused = pause;
00139 }
00140 
00141 /*
00142  */
00143 static void start_board (GcomprisBoard *agcomprisBoard)
00144 {
00145     gchar *img;
00146 
00147   if(agcomprisBoard!=NULL)
00148     {
00149       gcomprisBoard=agcomprisBoard;
00150       gcomprisBoard->level=1;
00151       gcomprisBoard->maxlevel=6;
00152       gcomprisBoard->sublevel=1;
00153       gcomprisBoard->number_of_sublevel=1; /* Go to next level after this number of 'play' */
00154       gc_bar_set(GC_BAR_LEVEL);
00155 
00156       gc_set_background(gnome_canvas_root(gcomprisBoard->canvas),
00157                            img = gc_skin_image_get("gcompris-bg.jpg"));
00158       g_free(img);
00159       hanoi_next_level();
00160 
00161       gamewon = FALSE;
00162       pause_board(FALSE);
00163     }
00164 }
00165 /* ======================================= */
00166 static void end_board ()
00167 {
00168   if(gcomprisBoard!=NULL)
00169     {
00170       pause_board(TRUE);
00171       hanoi_destroy_all_items();
00172     }
00173   gcomprisBoard = NULL;
00174 }
00175 
00176 /* ======================================= */
00177 static void set_level (guint level)
00178 {
00179 
00180   if(gcomprisBoard!=NULL)
00181     {
00182       gcomprisBoard->level=level;
00183       gcomprisBoard->sublevel=1;
00184       hanoi_next_level();
00185     }
00186 }
00187 /* ======================================= */
00188 static gboolean is_our_board (GcomprisBoard *gcomprisBoard)
00189 {
00190   if (gcomprisBoard)
00191     {
00192       if(g_strcasecmp(gcomprisBoard->type, "hanoi")==0)
00193        {
00194          /* Set the plugin entry */
00195          gcomprisBoard->plugin=&menu_bp;
00196 
00197          return TRUE;
00198        }
00199     }
00200   return FALSE;
00201 }
00202 
00203 /*-------------------------------------------------------------------------------*/
00204 /*-------------------------------------------------------------------------------*/
00205 /* set initial values for the next level */
00206 static void hanoi_next_level()
00207 {
00208 
00209   gc_bar_set_level(gcomprisBoard);
00210 
00211   hanoi_destroy_all_items();
00212   gamewon = FALSE;
00213 
00214   /* Select level difficulty */
00215   switch(gcomprisBoard->level)
00216     {
00217     case 1:
00218       number_of_item_x = 3;
00219       number_of_item_y = 5;
00220       break;
00221     case 2:
00222       number_of_item_x = 4;
00223       number_of_item_y = 5;
00224       break;
00225     case 3:
00226       number_of_item_x = 5;
00227       number_of_item_y = 6;
00228     case 4:
00229       number_of_item_x = 6;
00230       number_of_item_y = 7;
00231       break;
00232     case 5:
00233       number_of_item_x = 6;
00234       number_of_item_y = 8;
00235       break;
00236     case 6:
00237       number_of_item_x = 5;
00238       number_of_item_y = 9;
00239       break;
00240     default:
00241       number_of_item_x = 5;
00242       number_of_item_y = 7;
00243     }
00244 
00245 
00246   /* Try the next level */
00247   hanoi_create_item(gnome_canvas_root(gcomprisBoard->canvas));
00248 }
00249 /* ==================================== */
00250 /* Destroy all the items */
00251 static void hanoi_destroy_all_items()
00252 {
00253   guint i,j;
00254 
00255   if(boardRootItem!=NULL)
00256     {
00257       gtk_object_destroy (GTK_OBJECT(boardRootItem));
00258 
00259       /* Cleanup our memory structure */
00260       for(i=0; i<(number_of_item_x+2); i++)
00261        {
00262          for(j=0; j<number_of_item_y; j++)
00263            {
00264              g_free(position[i][j]);
00265            }
00266        }
00267     }
00268   boardRootItem = NULL;
00269 
00270 }
00271 
00272 #if 0
00273 static void dump_solution()
00274 {
00275   guint i, j;
00276 
00277   g_warning("Dumping solution\n");
00278   for(i=0; i<(number_of_item_x+2); i++)
00279     {
00280       for(j=0; j<number_of_item_y; j++)
00281        {
00282          g_warning("(%d,%d=%2d/%d) ",  position[i][j]->i,  position[i][j]->j, position[i][j]->color,
00283                position[i][j]->on_top);
00284        }
00285       g_warning("\n");
00286     }
00287 
00288 }
00289 
00290 static void print_piece(PieceItem *piece)
00291 {
00292   g_warning("Piece: (%d,%d=%2d/%d)\n",  piece->i,  piece->j, piece->color, piece->on_top);
00293 }
00294 #endif
00295 
00296 /* ==================================== */
00297 static GnomeCanvasItem *hanoi_create_item(GnomeCanvasGroup *parent)
00298 {
00299   int i,j;
00300   double gap_x, gap_y;
00301   double baseline;
00302   GnomeCanvasItem *item = NULL;
00303   guint color_to_place;
00304   guint used_colors[NUMBER_OF_COLOR];
00305   GnomeCanvasPathDef *path;
00306   guint w;
00307   GdkPixbuf *pixmap = NULL;
00308 
00309   boardRootItem = GNOME_CANVAS_GROUP(
00310                                  gnome_canvas_item_new (gnome_canvas_root(gcomprisBoard->canvas),
00311                                                      gnome_canvas_group_get_type (),
00312                                                      "x", (double) 0,
00313                                                      "y", (double) 0,
00314                                                      NULL));
00315 
00316   pixmap = gc_skin_pixmap_load("gcompris-shapelabel.png");
00317   if(pixmap) {
00318     gnome_canvas_item_new (boardRootItem,
00319                         gnome_canvas_pixbuf_get_type (),
00320                         "pixbuf", pixmap,
00321                         "x",       (double)BOARDWIDTH/2,
00322                         "y",       (double)BOARDHEIGHT - 35,
00323                         "width", (double) BOARDWIDTH - 20,
00324                         "width_set", TRUE,
00325                         "anchor", GTK_ANCHOR_CENTER,
00326                         NULL);
00327     gdk_pixbuf_unref(pixmap);
00328   }
00329 
00330   gnome_canvas_item_new (boardRootItem,
00331                       gnome_canvas_text_get_type (),
00332                       "text", _("Build the same tower in the empty area as the one you see on the right-hand side."),
00333                       "font", gc_skin_font_board_medium,
00334                       "x", (double) BOARDWIDTH/2 +1,
00335                       "y", (double) BOARDHEIGHT - 50 +1,
00336                       "anchor", GTK_ANCHOR_NORTH,
00337                       "fill_color", "black",
00338                       "justification", GTK_JUSTIFY_CENTER,
00339                       NULL);
00340 
00341   gnome_canvas_item_new (boardRootItem,
00342                       gnome_canvas_text_get_type (),
00343                       "text", _("Build the same tower in the empty area as the one you see on the right-hand side."),
00344                       "font", gc_skin_font_board_medium,
00345                       "x", (double) BOARDWIDTH/2,
00346                       "y", (double) BOARDHEIGHT - 50,
00347                       "anchor", GTK_ANCHOR_NORTH,
00348                       "fill_color_rgba", gc_skin_color_text_button,
00349                       "justification", GTK_JUSTIFY_CENTER,
00350                       NULL);
00351 
00352 
00353   /*----------------------------------------*/
00354   /* Empty the solution */
00355   for(i=0; i<(number_of_item_x+2); i++)
00356     {
00357       for(j=0; j<number_of_item_y; j++)
00358        {
00359          position[i][j] = g_malloc(sizeof(PieceItem));
00360          position[i][j]->color  = -1;
00361          position[i][j]->i      = i;
00362          position[i][j]->j      = j;
00363          position[i][j]->on_top = FALSE;
00364        }
00365     }
00366 
00367   /* Clear the used colors list */
00368   for(i=0; i<NUMBER_OF_COLOR; i++)
00369     used_colors[i] = FALSE;
00370 
00371   /* Initialize a random goal and store the color index in position[number_of_item_x] */
00372   for(i=0; i<(number_of_item_y); i++)
00373     {
00374       guint color = (guint)RAND(0, NUMBER_OF_COLOR-1);
00375       position[number_of_item_x+1][i]->color = color;
00376       used_colors[color] = TRUE;
00377 
00378     }
00379 
00380   /* Randomly place the solution */
00381   for (color_to_place=0; color_to_place<number_of_item_y; color_to_place++)
00382     {
00383       gboolean done;
00384 
00385       do
00386        {
00387          done = FALSE;
00388 
00389          i = (guint)RAND(0, number_of_item_x-2);
00390 
00391          /* Restrict the goal to lowest items */
00392          j = (guint)RAND(0, 2);
00393 
00394          if(position[i][j]->color == -1)
00395            {
00396              done = TRUE;
00397              position[i][j]->color = position[number_of_item_x+1][color_to_place]->color;
00398            }
00399        }
00400       while(!done);
00401     }
00402 
00403   /* Initialize the left open positions */
00404   for(i=0; i<(number_of_item_x); i++)
00405     {
00406       for(j=0; j<number_of_item_y-1; j++)
00407        {
00408          if(position[i][j]->color == -1)
00409            {
00410              /* Take only a color that is not part of the goal */
00411              guint color = (guint)RAND(0, NUMBER_OF_COLOR-1);
00412              //printf(" i,j=%d,%d random color = %d used_colors[color]=%d\n", i,j,color, used_colors[color]);
00413              while(used_colors[color])
00414               {
00415                 //printf("  used_colors[%d]=%d\n", color, used_colors[color]);
00416         color++;
00417               if(color >= NUMBER_OF_COLOR)
00418                 color = 0;
00419               }
00420 
00421              position[i][j]->color = color;
00422            }
00423        }
00424     }
00425   //dump_solution();
00426 
00427   /* Mark the top pieces */
00428   for(i=0; i<(number_of_item_x); i++)
00429     {
00430       position[i][number_of_item_y-2]->on_top = TRUE;
00431     }
00432 
00433   /*----------------------------------------*/
00434   /* Display it now */
00435 
00436   item_width  = BOARDWIDTH / (number_of_item_x + 2);
00437   item_height = 30;
00438 
00439   gap_x = item_width  * 0.1;
00440   gap_y = item_height * 0.25;
00441 
00442   baseline = BOARDHEIGHT/2 + item_height * number_of_item_y/2;
00443 
00444   number_of_item = 0;
00445 
00446   for(i=0; i<(number_of_item_x+2); i++)
00447     {
00448       if(i==number_of_item_x+1)
00449        {
00450          /* Create the backgound for the target */
00451          gnome_canvas_item_new (boardRootItem,
00452                              gnome_canvas_rect_get_type (),
00453                              "x1", (double) item_width * i + gap_x/2,
00454                              "y1", (double) baseline - item_height * number_of_item_y - gap_y - 50,
00455                              "x2", (double) item_width * (i+1) - gap_x/2,
00456                              "y2", (double) baseline + 50,
00457                              "fill_color_rgba", 0x036ED8FF,
00458                              "outline_color", "black",
00459                              "width_units", (double)1,
00460                              NULL);
00461        }
00462       else if (i==number_of_item_x)
00463        {
00464          /* Create the backgound for the empty area */
00465          gnome_canvas_item_new (boardRootItem,
00466                              gnome_canvas_rect_get_type (),
00467                              "x1", (double) item_width * i + gap_x/2,
00468                              "y1", (double) baseline - item_height * number_of_item_y - gap_y - 50,
00469                              "x2", (double) item_width * (i+1) - gap_x/2,
00470                              "y2", (double) baseline + 50,
00471                              "fill_color_rgba", 0x48AAF1FF,
00472                              "outline_color", "black",
00473                              "width_units", (double)1,
00474                              NULL);
00475        }
00476 
00477       /* Create the vertical line */
00478       w = 10;
00479       gnome_canvas_item_new (boardRootItem,
00480                           gnome_canvas_rect_get_type (),
00481                           "x1", (double) item_width * i + item_width/2 - w,
00482                           "y1", (double) baseline - item_height * number_of_item_y - gap_y,
00483                           "x2", (double) item_width * i + item_width/2 + w,
00484                           "y2", (double) baseline,
00485                           "fill_color_rgba", 0xFF1030FF,
00486                           "outline_color", "black",
00487                           "width_units", (double)1,
00488                           NULL);
00489 
00490       /* And the base line */
00491       w = 40;
00492       path = gnome_canvas_path_def_new();
00493       gnome_canvas_path_def_moveto (path, item_width * i + item_width/2 - w, baseline);
00494       gnome_canvas_path_def_lineto (path, item_width * i + item_width/2 + w, baseline);
00495       gnome_canvas_path_def_curveto (path,
00496                                  item_width * i + item_width/2 + w , baseline,
00497                                  item_width * i + item_width/2, baseline + w + 10,
00498                                  item_width * i + item_width/2 - w, baseline);
00499       gnome_canvas_path_def_closepath_current (path);
00500 
00501       item = gnome_canvas_item_new (boardRootItem,
00502                                 GNOME_TYPE_CANVAS_SHAPE,
00503                                 "fill_color_rgba", 0x20FF30FF,
00504                                 "outline_color", "black",
00505                                 NULL);
00506       gnome_canvas_shape_set_path_def (GNOME_CANVAS_SHAPE (item), path);
00507       gnome_canvas_item_show (item);
00508       gnome_canvas_path_def_unref (path);
00509 
00510       for(j=0; j<number_of_item_y; j++)
00511        {
00512 
00513          position[i][j]->x = item_width * i + gap_x;
00514          position[i][j]->y = baseline - item_height * j - item_height + gap_y;
00515 
00516          position[i][j]->xt = position[i][j]->x + 20;
00517          position[i][j]->yt = position[i][j]->y + 2;
00518 
00519 
00520          if(position[i][j]->color != -1)
00521            {
00522              char car[2];
00523 
00524              item = gnome_canvas_item_new (boardRootItem,
00525                                        gnome_canvas_rect_get_type (),
00526                                        "x1", (double) position[i][j]->x,
00527                                        "y1", (double) position[i][j]->y,
00528                                        "x2", (double) item_width * i + item_width - gap_x,
00529                                        "y2", (double) baseline - item_height * j,
00530                                        "fill_color_rgba", colorlist[position[i][j]->color],
00531                                        "outline_color", "black",
00532                                        "width_units", (double)1,
00533                                        NULL);
00534 
00535              car[0] = 'a' + position[i][j]->color;
00536              car[1] = '\0';
00537 
00538               position[i][j]->item_text = \
00539                gnome_canvas_item_new (boardRootItem,
00540                                    gnome_canvas_text_get_type (),
00541                                    "text", &car,
00542                                    "font", gc_skin_font_board_tiny,
00543                                    "x", (double) position[i][j]->xt,
00544                                    "y", (double) position[i][j]->yt,
00545                                    "anchor", GTK_ANCHOR_NORTH,
00546                                    "fill_color", "white",
00547                                    "justification", GTK_JUSTIFY_CENTER,
00548                                    NULL);
00549 
00550              position[i][j]->item = item;
00551 
00552              if(i!=number_of_item_x+1)
00553               gtk_signal_connect(GTK_OBJECT(item), "event", (GtkSignalFunc) item_event,  position[i][j]);
00554 
00555            }
00556 
00557        }
00558     }
00559 
00560   return NULL;
00561 }
00562 /* ==================================== */
00563 static void game_won()
00564 {
00565   gcomprisBoard->sublevel++;
00566 
00567   if(gcomprisBoard->sublevel>gcomprisBoard->number_of_sublevel) {
00568     /* Try the next level */
00569     gcomprisBoard->sublevel=1;
00570     gcomprisBoard->level++;
00571     if(gcomprisBoard->level>gcomprisBoard->maxlevel) { // the current board is finished : bail out
00572       gc_bonus_end_display(BOARD_FINISHED_RANDOM);
00573       return;
00574     }
00575     gc_sound_play_ogg ("sounds/bonus.ogg", NULL);
00576   }
00577   hanoi_next_level();
00578 }
00579 
00580 /*
00581  * Returns TRUE is the goal is reached
00582  */
00583 static gboolean is_completed()
00584 {
00585   gint j;
00586   gboolean done = TRUE;
00587 
00588   for(j=0; j<number_of_item_y; j++)
00589     {
00590       if(position[number_of_item_x+1][j]->color != position[number_of_item_x][j]->color)
00591        done = FALSE;
00592     }
00593 
00594   return done;
00595 }
00596 
00597 /* ==================================== */
00598 static gint
00599 item_event(GnomeCanvasItem *item, GdkEvent *event, PieceItem *data)
00600 {
00601    static double x, y;
00602    double new_x, new_y;
00603    GdkCursor *fleur;
00604    static int dragging;
00605    double item_x, item_y;
00606 
00607    if(!gcomprisBoard)
00608      return FALSE;
00609 
00610   if(board_paused)
00611     return FALSE;
00612 
00613   if(!data->on_top)
00614     return FALSE;
00615 
00616   item_x = event->button.x;
00617   item_y = event->button.y;
00618   gnome_canvas_item_w2i(item->parent, &item_x, &item_y);
00619 
00620   switch (event->type)
00621     {
00622     case GDK_ENTER_NOTIFY:
00623       gnome_canvas_item_set(item,
00624                          "outline_color", "white",
00625                          "width_units", (double)3,
00626                          NULL);
00627       break;
00628     case GDK_LEAVE_NOTIFY:
00629       gnome_canvas_item_set(item,
00630                          "outline_color", "black",
00631                          "width_units", (double)1,
00632                          NULL);
00633       break;
00634     case GDK_BUTTON_PRESS:
00635       switch(event->button.button)
00636        {
00637        case 1:
00638 
00639          x = item_x;
00640          y = item_y;
00641 
00642          gnome_canvas_item_raise_to_top(data->item);
00643          gnome_canvas_item_raise_to_top(data->item_text);
00644 
00645          fleur = gdk_cursor_new(GDK_FLEUR);
00646          gc_canvas_item_grab(data->item,
00647                              GDK_POINTER_MOTION_MASK |
00648                              GDK_BUTTON_RELEASE_MASK,
00649                              fleur,
00650                              event->button.time);
00651          gdk_cursor_destroy(fleur);
00652          dragging = TRUE;
00653          break;
00654        }
00655       break;
00656 
00657     case GDK_MOTION_NOTIFY:
00658       if (dragging && (event->motion.state & GDK_BUTTON1_MASK))
00659        {
00660          new_x = item_x;
00661          new_y = item_y;
00662 
00663          gnome_canvas_item_move(data->item     , new_x - x, new_y - y);
00664          gnome_canvas_item_move(data->item_text, new_x - x, new_y - y);
00665          x = new_x;
00666          y = new_y;
00667        }
00668       break;
00669 
00670     case GDK_BUTTON_RELEASE:
00671       if(dragging)
00672        {
00673          gint i;
00674          gint tmpi, tmpj;
00675          double tmpx, tmpy;
00676          PieceItem *piece_src;
00677          PieceItem *piece_dst;
00678          gint col = 0, line;
00679 
00680          gc_canvas_item_ungrab(data->item, event->button.time);
00681          dragging = FALSE;
00682 
00683          /* Search the column (x) where this item is ungrabbed */
00684          for(i=0; i<=number_of_item_x; i++)
00685            if(position[i][0]->x   < item_x &&
00686               position[i+1][0]->x > item_x)
00687              col = i;
00688 
00689          /* Bad drop / Outside of column area */
00690          /* Bad drop / On the same column */
00691          if(col<0 || col > number_of_item_x || col == data->i)
00692            {
00693              /* Return to the original position */
00694              gc_item_absolute_move (data->item     , data->x , data->y);
00695              gc_item_absolute_move (data->item_text, data->xt, data->yt);
00696 
00697              /* FIXME : Workaround for bugged canvas */
00698              gnome_canvas_update_now(gcomprisBoard->canvas);
00699 
00700              return FALSE;
00701            }
00702 
00703 
00704          /* Now search the free line (y) */
00705          line = number_of_item_y;
00706          for(i=number_of_item_y-1; i>=0; i--)
00707            if(position[col][i]->color == -1)
00708              line = i;
00709 
00710          /* Bad drop / Too many pieces here */
00711          if(line >= number_of_item_y)
00712            {
00713              /* Return to the original position */
00714              gc_item_absolute_move (data->item     , data->x , data->y);
00715              gc_item_absolute_move (data->item_text, data->xt, data->yt);
00716 
00717              /* FIXME : Workaround for bugged canvas */
00718              gnome_canvas_update_now(gcomprisBoard->canvas);
00719 
00720              return FALSE;
00721            }
00722 
00723          /* Update ontop values for the piece under the grabbed one */
00724          if(data->j>0)
00725            position[data->i][data->j-1]->on_top = TRUE;
00726 
00727          /* Update ontop values for the piece under the ungrabbed one */
00728          if(line>0)
00729            position[col][line-1]->on_top = FALSE;
00730 
00731          /* Move the piece */
00732          piece_dst = position[col][line];
00733          piece_src = data;
00734          gc_item_absolute_move (data->item     , piece_dst->x , piece_dst->y);
00735          gc_item_absolute_move (data->item_text, piece_dst->xt, piece_dst->yt);
00736 
00737          /* FIXME : Workaround for bugged canvas */
00738          gnome_canvas_update_now(gcomprisBoard->canvas);
00739 
00740          /* Swap values in the pieces */
00741          tmpx    = data->x;
00742          tmpy    = data->y;
00743          piece_src->x = piece_dst->x;
00744          piece_src->y = piece_dst->y;
00745          piece_dst->x = tmpx;
00746          piece_dst->y = tmpy;
00747 
00748          tmpx    = data->xt;
00749          tmpy    = data->yt;
00750          piece_src->xt = piece_dst->xt;
00751          piece_src->yt = piece_dst->yt;
00752          piece_dst->xt = tmpx;
00753          piece_dst->yt = tmpy;
00754 
00755          tmpi    = data->i;
00756          tmpj    = data->j;
00757          position[tmpi][tmpj]->i = piece_dst->i;
00758          position[tmpi][tmpj]->j = piece_dst->j;
00759          piece_dst->i  = tmpi;
00760          piece_dst->j  = tmpj;
00761 
00762          position[piece_src->i][piece_src->j] = piece_src;
00763          position[piece_dst->i][piece_dst->j] = piece_dst;
00764 
00765          //     dump_solution();
00766          if(is_completed())
00767            {
00768              gamewon = TRUE;
00769              hanoi_destroy_all_items();
00770              gc_bonus_display(gamewon, BONUS_SMILEY);
00771            }
00772        }
00773       break;
00774 
00775     default:
00776       break;
00777     }
00778 
00779 
00780   return FALSE;
00781 }
00782