~ubuntu-branches/ubuntu/maverick/gcompris/maverick

« back to all changes in this revision

Viewing changes to src/hanoi-activity/hanoi.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 - hanoi.c
 
2
 *
 
3
 * Copyright (C) 2003, 2008 Bruno Coudoin
 
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
#define SOUNDLISTFILE PACKAGE
 
22
 
 
23
static GcomprisBoard *gcomprisBoard = NULL;
 
24
static gboolean board_paused = TRUE;
 
25
 
 
26
static void      start_board (GcomprisBoard *agcomprisBoard);
 
27
static void      pause_board (gboolean pause);
 
28
static void      end_board (void);
 
29
static gboolean  is_our_board (GcomprisBoard *gcomprisBoard);
 
30
static void      set_level (guint level);
 
31
static int       gamewon;
 
32
static void      game_won(void);
 
33
 
 
34
static GooCanvasItem *boardRootItem = NULL;
 
35
 
 
36
static GooCanvasItem    *hanoi_create_item(GooCanvasItem *parent);
 
37
static void              hanoi_destroy_all_items(void);
 
38
static void              hanoi_next_level(void);
 
39
 
 
40
/*
 
41
 * Contains the piece information
 
42
 */
 
43
typedef struct {
 
44
  GooCanvasItem *group;
 
45
  gint i;
 
46
  gint j;
 
47
  double x;
 
48
  double y;
 
49
  gboolean on_top;
 
50
  gint color;
 
51
} PieceItem;
 
52
 
 
53
static gint item_event(GooCanvasItem *item,
 
54
                       GooCanvasItem *target,
 
55
                       GdkEvent *event, PieceItem *data);
 
56
 
 
57
/* This contains the layout of the pieces */
 
58
#define MAX_NUMBER_X 10
 
59
#define MAX_NUMBER_Y 10
 
60
static PieceItem *position[MAX_NUMBER_X][MAX_NUMBER_Y];
 
61
 
 
62
static int number_of_item = 0;
 
63
static int number_of_item_x = 0;
 
64
static int number_of_item_y = 0;
 
65
static int item_width;
 
66
static int item_height;
 
67
 
 
68
static guint colorlist [] =
 
69
  {
 
70
    0x00C0C0FF,
 
71
    0xA00000FF,
 
72
    0xF00000FF,
 
73
    0x00A000FF,
 
74
    0x00F000FF,
 
75
    0x0000AAFF,
 
76
    0x0000FFFF,
 
77
    0x505000FF,
 
78
    0xA0A000FF,
 
79
    0xC0C080FF,
 
80
    0x005050FF,
 
81
    0x00A0A0FF,
 
82
    0x500050FF,
 
83
    0xA000A0FF,
 
84
    0xF000F0FF
 
85
  };
 
86
#define NUMBER_OF_COLOR G_N_ELEMENTS(colorlist)
 
87
 
 
88
static char symbollist [NUMBER_OF_COLOR] =
 
89
  {
 
90
    '!',
 
91
    '/',
 
92
    '<',
 
93
    '>',
 
94
    '&',
 
95
    '~',
 
96
    '#',
 
97
    '{',
 
98
    '%',
 
99
    '|',
 
100
    '?',
 
101
    '}',
 
102
    '=',
 
103
    '+',
 
104
    '*'
 
105
  };
 
106
 
 
107
/* Description of this plugin */
 
108
static BoardPlugin menu_bp =
 
109
  {
 
110
    NULL,
 
111
    NULL,
 
112
    N_("Simplified Tower of Hanoi"),
 
113
    N_("Reproduce the given tower"),
 
114
    "Bruno Coudoin <bruno.coudoin@free.fr>",
 
115
    NULL,
 
116
    NULL,
 
117
    NULL,
 
118
    NULL,
 
119
    start_board,
 
120
    pause_board,
 
121
    end_board,
 
122
    is_our_board,
 
123
    NULL,
 
124
    NULL,
 
125
    set_level,
 
126
    NULL,
 
127
    NULL,
 
128
    NULL,
 
129
    NULL
 
130
  };
 
131
 
 
132
/*
 
133
 * Main entry point mandatory for each Gcompris's game
 
134
 * ---------------------------------------------------
 
135
 *
 
136
 */
 
137
 
 
138
GET_BPLUGIN_INFO(hanoi)
 
139
 
 
140
/*
 
141
 * in : boolean TRUE = PAUSE : FALSE = CONTINUE
 
142
 *
 
143
 */
 
144
static void
 
145
pause_board (gboolean pause)
 
146
{
 
147
  if(gcomprisBoard==NULL)
 
148
    return;
 
149
 
 
150
  if(gamewon == TRUE && pause == FALSE) /* the game is won */
 
151
    {
 
152
      game_won();
 
153
    }
 
154
 
 
155
  board_paused = pause;
 
156
}
 
157
 
 
158
/*
 
159
 */
 
160
static void
 
161
start_board (GcomprisBoard *agcomprisBoard)
 
162
{
 
163
 
 
164
  if(agcomprisBoard!=NULL)
 
165
    {
 
166
      gcomprisBoard=agcomprisBoard;
 
167
      gcomprisBoard->level=1;
 
168
      gcomprisBoard->maxlevel=6;
 
169
      gcomprisBoard->sublevel=1;
 
170
      gcomprisBoard->number_of_sublevel=1; /* Go to next level after this number of 'play' */
 
171
      gc_bar_set(GC_BAR_LEVEL);
 
172
 
 
173
      gc_set_default_background(goo_canvas_get_root_item(gcomprisBoard->canvas));
 
174
 
 
175
      gc_drag_start(goo_canvas_get_root_item(gcomprisBoard->canvas),
 
176
                    (GcDragFunc)item_event,
 
177
                    GC_DRAG_MODE_DEFAULT);
 
178
 
 
179
      hanoi_next_level();
 
180
 
 
181
      gamewon = FALSE;
 
182
      pause_board(FALSE);
 
183
    }
 
184
}
 
185
/* ======================================= */
 
186
static void
 
187
end_board ()
 
188
{
 
189
  if(gcomprisBoard!=NULL)
 
190
    {
 
191
      gc_drag_stop(goo_canvas_get_root_item(gcomprisBoard->canvas));
 
192
      pause_board(TRUE);
 
193
      hanoi_destroy_all_items();
 
194
    }
 
195
  gcomprisBoard = NULL;
 
196
}
 
197
 
 
198
/* ======================================= */
 
199
static void set_level (guint level)
 
200
{
 
201
 
 
202
  if(gcomprisBoard!=NULL)
 
203
    {
 
204
      gcomprisBoard->level=level;
 
205
      gcomprisBoard->sublevel=1;
 
206
      hanoi_next_level();
 
207
    }
 
208
}
 
209
/* ======================================= */
 
210
static gboolean is_our_board (GcomprisBoard *gcomprisBoard)
 
211
{
 
212
  if (gcomprisBoard)
 
213
    {
 
214
      if(g_strcasecmp(gcomprisBoard->type, "hanoi")==0)
 
215
        {
 
216
          /* Set the plugin entry */
 
217
          gcomprisBoard->plugin=&menu_bp;
 
218
 
 
219
          return TRUE;
 
220
        }
 
221
    }
 
222
  return FALSE;
 
223
}
 
224
 
 
225
/*-------------------------------------------------------------------------------*/
 
226
/*-------------------------------------------------------------------------------*/
 
227
/* set initial values for the next level */
 
228
static void hanoi_next_level()
 
229
{
 
230
 
 
231
  gc_bar_set_level(gcomprisBoard);
 
232
 
 
233
  hanoi_destroy_all_items();
 
234
  gamewon = FALSE;
 
235
 
 
236
  /* Select level difficulty */
 
237
  switch(gcomprisBoard->level)
 
238
    {
 
239
    case 1:
 
240
      number_of_item_x = 3;
 
241
      number_of_item_y = 5;
 
242
      break;
 
243
    case 2:
 
244
      number_of_item_x = 4;
 
245
      number_of_item_y = 5;
 
246
      break;
 
247
    case 3:
 
248
      number_of_item_x = 5;
 
249
      number_of_item_y = 6;
 
250
    case 4:
 
251
      number_of_item_x = 6;
 
252
      number_of_item_y = 7;
 
253
      break;
 
254
    case 5:
 
255
      number_of_item_x = 6;
 
256
      number_of_item_y = 8;
 
257
      break;
 
258
    case 6:
 
259
      number_of_item_x = 5;
 
260
      number_of_item_y = 9;
 
261
      break;
 
262
    default:
 
263
      number_of_item_x = 5;
 
264
      number_of_item_y = 7;
 
265
    }
 
266
 
 
267
 
 
268
  /* Try the next level */
 
269
  hanoi_create_item(goo_canvas_get_root_item(gcomprisBoard->canvas));
 
270
}
 
271
/* ==================================== */
 
272
/* Destroy all the items */
 
273
static void hanoi_destroy_all_items()
 
274
{
 
275
  guint i,j;
 
276
 
 
277
  if(boardRootItem!=NULL)
 
278
    {
 
279
      goo_canvas_item_remove(boardRootItem);
 
280
 
 
281
      /* Cleanup our memory structure */
 
282
      for(i=0; i<(number_of_item_x+2); i++)
 
283
        {
 
284
          for(j=0; j<number_of_item_y; j++)
 
285
            {
 
286
              g_free(position[i][j]);
 
287
            }
 
288
        }
 
289
    }
 
290
  boardRootItem = NULL;
 
291
 
 
292
}
 
293
 
 
294
#if 0
 
295
static void dump_solution()
 
296
{
 
297
  guint i, j;
 
298
 
 
299
  g_warning("Dumping solution\n");
 
300
  for(i=0; i<(number_of_item_x+2); i++)
 
301
    {
 
302
      for(j=0; j<number_of_item_y; j++)
 
303
        {
 
304
          g_warning("(%d,%d=%2d/%d) ",  position[i][j]->i,  position[i][j]->j, position[i][j]->color,
 
305
                 position[i][j]->on_top);
 
306
        }
 
307
      g_warning("\n");
 
308
    }
 
309
 
 
310
}
 
311
 
 
312
static void print_piece(PieceItem *piece)
 
313
{
 
314
  g_warning("Piece: (%d,%d=%2d/%d)\n",
 
315
            piece->i,  piece->j,
 
316
            piece->color, piece->on_top);
 
317
}
 
318
#endif
 
319
 
 
320
/* ==================================== */
 
321
static GooCanvasItem *
 
322
hanoi_create_item(GooCanvasItem *parent)
 
323
{
 
324
  int i,j;
 
325
  double gap_x, gap_y;
 
326
  double baseline;
 
327
  GooCanvasItem *item = NULL;
 
328
  guint color_to_place;
 
329
  guint used_colors[NUMBER_OF_COLOR];
 
330
  guint w;
 
331
 
 
332
  boardRootItem = \
 
333
    goo_canvas_group_new (parent,
 
334
                          NULL);
 
335
 
 
336
 
 
337
  if (gcomprisBoard->level == 1)
 
338
    {
 
339
      item = goo_canvas_svg_new (boardRootItem,
 
340
                                 gc_skin_rsvg_get(),
 
341
                                 "svg-id", "#BAR_BG",
 
342
                                 NULL);
 
343
      SET_ITEM_LOCATION_CENTER(item,
 
344
                               BOARDWIDTH/2,
 
345
                               50);
 
346
 
 
347
      goo_canvas_text_new (boardRootItem,
 
348
                           _("Build the same tower in the empty area as the one you see on the right-hand side."),
 
349
                           BOARDWIDTH/2,
 
350
                           50,
 
351
                           -1,
 
352
                           GTK_ANCHOR_CENTER,
 
353
                           "font", gc_skin_font_board_medium,
 
354
                           "fill_color_rgba", gc_skin_color_text_button,
 
355
                           NULL);
 
356
    }
 
357
 
 
358
  /*----------------------------------------*/
 
359
  /* Empty the solution */
 
360
  for(i=0; i<(number_of_item_x+2); i++)
 
361
    {
 
362
      for(j=0; j<number_of_item_y; j++)
 
363
        {
 
364
          position[i][j] = g_malloc(sizeof(PieceItem));
 
365
          position[i][j]->color  = -1;
 
366
          position[i][j]->i      = i;
 
367
          position[i][j]->j      = j;
 
368
          position[i][j]->on_top = FALSE;
 
369
        }
 
370
    }
 
371
 
 
372
  /* Clear the used colors list */
 
373
  for(i=0; i<NUMBER_OF_COLOR; i++)
 
374
    used_colors[i] = FALSE;
 
375
 
 
376
  /* Initialize a random goal and store the color index
 
377
     in position[number_of_item_x] */
 
378
  for(i=0; i<(number_of_item_y); i++)
 
379
    {
 
380
      guint color = (guint)g_random_int_range(0, NUMBER_OF_COLOR-1);
 
381
      position[number_of_item_x+1][i]->color = color;
 
382
      used_colors[color] = TRUE;
 
383
 
 
384
    }
 
385
 
 
386
  /* Randomly place the solution */
 
387
  for (color_to_place=0; color_to_place<number_of_item_y; color_to_place++)
 
388
    {
 
389
      gboolean done;
 
390
 
 
391
      do
 
392
        {
 
393
          done = FALSE;
 
394
 
 
395
          i = (guint)g_random_int_range(0, number_of_item_x);
 
396
 
 
397
          /* Restrict the goal to lowest items */
 
398
          j = (guint)g_random_int_range(0, 2);
 
399
 
 
400
          if(position[i][j]->color == -1)
 
401
            {
 
402
              done = TRUE;
 
403
              position[i][j]->color = position[number_of_item_x+1][color_to_place]->color;
 
404
            }
 
405
        }
 
406
      while(!done);
 
407
    }
 
408
 
 
409
  /* Initialize the left open positions */
 
410
  for(i=0; i<(number_of_item_x); i++)
 
411
    {
 
412
      for(j=0; j<number_of_item_y-1; j++)
 
413
        {
 
414
          if(position[i][j]->color == -1)
 
415
            {
 
416
              /* Take only a color that is not part of the goal */
 
417
              guint color = (guint)g_random_int_range(0, NUMBER_OF_COLOR-1);
 
418
              while(used_colors[color])
 
419
                {
 
420
                  color++;
 
421
                  if(color >= NUMBER_OF_COLOR)
 
422
                    color = 0;
 
423
                }
 
424
 
 
425
              position[i][j]->color = color;
 
426
            }
 
427
        }
 
428
    }
 
429
  //dump_solution();
 
430
 
 
431
  /* Mark the top pieces */
 
432
  for(i=0; i<(number_of_item_x); i++)
 
433
    {
 
434
      position[i][number_of_item_y-2]->on_top = TRUE;
 
435
    }
 
436
 
 
437
  /*----------------------------------------*/
 
438
  /* Display it now */
 
439
 
 
440
  item_width  = BOARDWIDTH / (number_of_item_x + 2);
 
441
  item_height = 30;
 
442
 
 
443
  gap_x = item_width  * 0.1;
 
444
  gap_y = item_height * 0.25;
 
445
 
 
446
  baseline = BOARDHEIGHT/2 + item_height * number_of_item_y/2;
 
447
 
 
448
  number_of_item = 0;
 
449
 
 
450
  for(i=0; i<(number_of_item_x+2); i++)
 
451
    {
 
452
      if(i == number_of_item_x+1)
 
453
        {
 
454
          /* Create the backgound for the target */
 
455
          goo_canvas_rect_new (boardRootItem,
 
456
                               item_width * i + gap_x/2,
 
457
                               baseline - item_height * number_of_item_y - gap_y - 50,
 
458
                               item_width - gap_x,
 
459
                               item_height * number_of_item_y + gap_y*2 + 100,
 
460
                               "fill_color_rgba", 0x036ED8FF,
 
461
                               "stroke-color", "black",
 
462
                               "line-width", (double)1,
 
463
                               NULL);
 
464
        }
 
465
      else if (i == number_of_item_x)
 
466
        {
 
467
          /* Create the backgound for the empty area */
 
468
          goo_canvas_rect_new (boardRootItem,
 
469
                               item_width * i + gap_x/2,
 
470
                               baseline - item_height * number_of_item_y - gap_y - 50,
 
471
                               item_width - gap_x,
 
472
                               item_height * number_of_item_y + gap_y*2 + 100,
 
473
                               "fill_color_rgba", 0x48AAF1FF,
 
474
                               "stroke-color", "black",
 
475
                               "line-width", (double)1,
 
476
                               NULL);
 
477
        }
 
478
 
 
479
      /* Create the vertical line */
 
480
      w = 10;
 
481
      goo_canvas_rect_new (boardRootItem,
 
482
                           item_width * i + item_width/2 - w,
 
483
                           baseline - item_height * number_of_item_y - gap_y,
 
484
                           w*2,
 
485
                           (item_height + gap_y/2 - 2) * number_of_item_y,
 
486
                           "fill_color_rgba", 0xFF1030FF,
 
487
                           "stroke-color", "black",
 
488
                           "line-width", (double)1,
 
489
                           NULL);
 
490
 
 
491
      /* And the base line */
 
492
      item = goo_canvas_path_new (boardRootItem,
 
493
                                  "M 43,19 A 22,20 0 1 1 -1,19 L 20,19 z",
 
494
                                  "fill_color_rgba", 0xFF1030FF,
 
495
                                  "stroke-color", "black",
 
496
                                  "line-width", 1.0,
 
497
                                  NULL);
 
498
      goo_canvas_item_translate(item,
 
499
                                item_width * i + item_width/2 - 20,
 
500
                                baseline - 25);
 
501
 
 
502
      for(j=0; j<number_of_item_y; j++)
 
503
        {
 
504
 
 
505
          position[i][j]->x = item_width * i + gap_x;
 
506
          position[i][j]->y = baseline - item_height * j - item_height + gap_y;
 
507
 
 
508
          if(position[i][j]->color != -1)
 
509
            {
 
510
              char car[2];
 
511
 
 
512
              GooCanvasItem *group = goo_canvas_group_new(boardRootItem,
 
513
                                                          NULL);
 
514
              goo_canvas_item_translate(group,
 
515
                                        position[i][j]->x,
 
516
                                        position[i][j]->y);
 
517
 
 
518
              position[i][j]->group = group;
 
519
 
 
520
              item = goo_canvas_rect_new (group,
 
521
                                          0,
 
522
                                          0,
 
523
                                          item_width - gap_x * 2,
 
524
                                          item_height - gap_y,
 
525
                                          "fill_color_rgba",
 
526
                                          colorlist[position[i][j]->color],
 
527
                                          "stroke-color", "black",
 
528
                                          "line-width", (double)1,
 
529
                                          NULL);
 
530
 
 
531
              car[0] = symbollist[position[i][j]->color];
 
532
              car[1] = '\0';
 
533
 
 
534
              goo_canvas_text_new (group,
 
535
                                   (char *)car,
 
536
                                   20,
 
537
                                   0,
 
538
                                   -1,
 
539
                                   GTK_ANCHOR_NORTH,
 
540
                                   "font", "sans bold 14",
 
541
                                   "fill-color", "white",
 
542
                                   NULL);
 
543
 
 
544
              if(i != number_of_item_x+1)
 
545
                {
 
546
                  g_signal_connect(item, "button_press_event",
 
547
                                   (GtkSignalFunc)gc_drag_event,
 
548
                                   position[i][j]);
 
549
                  g_signal_connect(item, "button_release_event",
 
550
                                   (GtkSignalFunc)gc_drag_event,
 
551
                                   position[i][j]);
 
552
 
 
553
                  g_signal_connect(item, "enter_notify_event",
 
554
                                   (GtkSignalFunc) item_event,
 
555
                                   position[i][j]);
 
556
                  g_signal_connect(item, "leave_notify_event",
 
557
                                   (GtkSignalFunc) item_event,
 
558
                                   position[i][j]);
 
559
                }
 
560
            }
 
561
 
 
562
        }
 
563
    }
 
564
 
 
565
  return NULL;
 
566
}
 
567
/* ==================================== */
 
568
static void
 
569
game_won()
 
570
{
 
571
  gcomprisBoard->sublevel++;
 
572
 
 
573
  if(gcomprisBoard->sublevel>gcomprisBoard->number_of_sublevel) {
 
574
    /* Try the next level */
 
575
    gcomprisBoard->sublevel=1;
 
576
    gcomprisBoard->level++;
 
577
    if(gcomprisBoard->level>gcomprisBoard->maxlevel)
 
578
      gcomprisBoard->level = gcomprisBoard->maxlevel;
 
579
 
 
580
    gc_sound_play_ogg ("sounds/bonus.wav", NULL);
 
581
  }
 
582
  hanoi_next_level();
 
583
}
 
584
 
 
585
/*
 
586
 * Returns TRUE is the goal is reached
 
587
 */
 
588
static gboolean
 
589
is_completed()
 
590
{
 
591
  gint j;
 
592
  gboolean done = TRUE;
 
593
 
 
594
  for(j=0; j<number_of_item_y; j++)
 
595
    {
 
596
      if(position[number_of_item_x+1][j]->color != position[number_of_item_x][j]->color)
 
597
        done = FALSE;
 
598
    }
 
599
 
 
600
  return done;
 
601
}
 
602
 
 
603
/* ==================================== */
 
604
static gint
 
605
item_event(GooCanvasItem *item,
 
606
           GooCanvasItem *target,
 
607
           GdkEvent *event,
 
608
           PieceItem *data)
 
609
{
 
610
  double item_x, item_y;
 
611
 
 
612
  if(!gcomprisBoard)
 
613
    return FALSE;
 
614
 
 
615
  if(board_paused)
 
616
    return FALSE;
 
617
 
 
618
  if(data && !data->on_top)
 
619
    return FALSE;
 
620
 
 
621
  switch (event->type)
 
622
    {
 
623
    case GDK_ENTER_NOTIFY:
 
624
      g_object_set(item,
 
625
                   "stroke-color", "white",
 
626
                   "line-width", (double)3,
 
627
                   NULL);
 
628
      break;
 
629
    case GDK_LEAVE_NOTIFY:
 
630
      g_object_set(item,
 
631
                   "stroke-color", "black",
 
632
                   "line-width", (double)1,
 
633
                   NULL);
 
634
      break;
 
635
    case GDK_BUTTON_PRESS:
 
636
      switch(event->button.button)
 
637
        {
 
638
        case 1:
 
639
          gc_sound_play_ogg ("sounds/bleep.wav", NULL);
 
640
          gc_drag_offset_save(event);
 
641
          goo_canvas_item_raise(data->group, NULL);
 
642
          break;
 
643
        }
 
644
      break;
 
645
 
 
646
    case GDK_MOTION_NOTIFY:
 
647
      gc_drag_item_move(event, data->group);
 
648
      break;
 
649
 
 
650
    case GDK_BUTTON_RELEASE:
 
651
        {
 
652
          gint i;
 
653
          gint tmpi, tmpj;
 
654
          double tmpx, tmpy;
 
655
          PieceItem *piece_src;
 
656
          PieceItem *piece_dst;
 
657
          gint col = 0, line;
 
658
 
 
659
          item_x = event->button.x;
 
660
          item_y = event->button.y;
 
661
          goo_canvas_convert_from_item_space(goo_canvas_item_get_canvas(item),
 
662
                                             item,
 
663
                                             &item_x, &item_y);
 
664
 
 
665
          /* Search the column (x) where this item is ungrabbed */
 
666
          for(i=0; i<=number_of_item_x; i++)
 
667
            if(position[i][0]->x   < item_x &&
 
668
               position[i+1][0]->x > item_x)
 
669
              col = i;
 
670
 
 
671
          /* Bad drop / Outside of column area */
 
672
          /* Bad drop / On the same column */
 
673
          if(col<0 || col > number_of_item_x || col == data->i)
 
674
            {
 
675
              gc_sound_play_ogg ("sounds/eraser2.wav", NULL);
 
676
 
 
677
              /* Return to the original position */
 
678
              gc_item_absolute_move (data->group, data->x , data->y);
 
679
              return FALSE;
 
680
            }
 
681
 
 
682
 
 
683
          /* Now search the free line (y) */
 
684
          line = number_of_item_y;
 
685
          for(i=number_of_item_y-1; i>=0; i--)
 
686
            if(position[col][i]->color == -1)
 
687
              line = i;
 
688
 
 
689
          /* Bad drop / Too many pieces here */
 
690
          if(line >= number_of_item_y)
 
691
            {
 
692
              gc_sound_play_ogg ("sounds/eraser2.wav", NULL);
 
693
 
 
694
              /* Return to the original position */
 
695
              gc_item_absolute_move (data->group, data->x , data->y);
 
696
 
 
697
              return FALSE;
 
698
            }
 
699
 
 
700
          /* Update ontop values for the piece under the grabbed one */
 
701
          if(data->j>0)
 
702
            position[data->i][data->j-1]->on_top = TRUE;
 
703
 
 
704
          /* Update ontop values for the piece under the ungrabbed one */
 
705
          if(line>0)
 
706
            position[col][line-1]->on_top = FALSE;
 
707
 
 
708
          /* Move the piece */
 
709
          piece_dst = position[col][line];
 
710
          piece_src = data;
 
711
          gc_item_absolute_move (data->group, piece_dst->x , piece_dst->y);
 
712
 
 
713
          gc_sound_play_ogg ("sounds/scroll.wav", NULL);
 
714
 
 
715
          /* Swap values in the pieces */
 
716
          tmpx    = data->x;
 
717
          tmpy    = data->y;
 
718
          piece_src->x = piece_dst->x;
 
719
          piece_src->y = piece_dst->y;
 
720
          piece_dst->x = tmpx;
 
721
          piece_dst->y = tmpy;
 
722
 
 
723
          tmpi    = data->i;
 
724
          tmpj    = data->j;
 
725
          position[tmpi][tmpj]->i = piece_dst->i;
 
726
          position[tmpi][tmpj]->j = piece_dst->j;
 
727
          piece_dst->i  = tmpi;
 
728
          piece_dst->j  = tmpj;
 
729
 
 
730
          position[piece_src->i][piece_src->j] = piece_src;
 
731
          position[piece_dst->i][piece_dst->j] = piece_dst;
 
732
 
 
733
          //      dump_solution();
 
734
          if(is_completed())
 
735
            {
 
736
              gamewon = TRUE;
 
737
              hanoi_destroy_all_items();
 
738
              gc_bonus_display(gamewon, GC_BONUS_SMILEY);
 
739
            }
 
740
        }
 
741
      break;
 
742
 
 
743
    default:
 
744
      break;
 
745
    }
 
746
 
 
747
 
 
748
  return FALSE;
 
749
}
 
750