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

« back to all changes in this revision

Viewing changes to src/fifteen-activity/fifteen.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 - fifteen.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
#include <time.h>
 
21
 
 
22
#define PIECE_SIZE 50
 
23
 
 
24
#define SOUNDLISTFILE PACKAGE
 
25
 
 
26
static GcomprisBoard *gcomprisBoard = NULL;
 
27
static gboolean board_paused = TRUE;
 
28
 
 
29
static void      start_board (GcomprisBoard *agcomprisBoard);
 
30
static void      pause_board (gboolean pause);
 
31
static void      end_board (void);
 
32
static gboolean  is_our_board (GcomprisBoard *gcomprisBoard);
 
33
static void      set_level (guint level);
 
34
static int       gamewon;
 
35
static void      game_won(void);
 
36
 
 
37
static GooCanvasItem *boardRootItem = NULL;
 
38
 
 
39
static GooCanvasItem    *fifteen_create_item(GooCanvasItem *parent);
 
40
static void              fifteen_destroy_all_items(void);
 
41
static void              fifteen_next_level(void);
 
42
 
 
43
static gboolean          piece_event (GooCanvasItem  *item,
 
44
                                      GooCanvasItem  *target,
 
45
                                      GdkEventButton *event,
 
46
                                      gpointer data);
 
47
static void              scramble (GooCanvasItem **board, guint number_of_scrambles);
 
48
static char             *get_piece_color (int piece);
 
49
 
 
50
/* Description of this plugin */
 
51
static BoardPlugin menu_bp =
 
52
  {
 
53
    NULL,
 
54
    NULL,
 
55
    "The fifteen game",
 
56
    "Move the items one by one, to rearrange them in increasing order",
 
57
    "Bruno Coudoin <bruno.coudoin@free.fr>",
 
58
    NULL,
 
59
    NULL,
 
60
    NULL,
 
61
    NULL,
 
62
    start_board,
 
63
    pause_board,
 
64
    end_board,
 
65
    is_our_board,
 
66
    NULL,
 
67
    NULL,
 
68
    set_level,
 
69
    NULL,
 
70
    NULL,
 
71
    NULL,
 
72
    NULL
 
73
  };
 
74
 
 
75
/*
 
76
 * Main entry point mandatory for each Gcompris's game
 
77
 * ---------------------------------------------------
 
78
 *
 
79
 */
 
80
 
 
81
GET_BPLUGIN_INFO(fifteen)
 
82
 
 
83
/*
 
84
 * in : boolean TRUE = PAUSE : FALSE = CONTINUE
 
85
 *
 
86
 */
 
87
static void pause_board (gboolean pause)
 
88
{
 
89
  if(gcomprisBoard==NULL)
 
90
    return;
 
91
 
 
92
  if(gamewon == TRUE && pause == FALSE) /* the game is won */
 
93
    {
 
94
      game_won();
 
95
    }
 
96
 
 
97
  board_paused = pause;
 
98
}
 
99
 
 
100
/*
 
101
 */
 
102
static void start_board (GcomprisBoard *agcomprisBoard)
 
103
{
 
104
 
 
105
  if(agcomprisBoard!=NULL)
 
106
    {
 
107
      gcomprisBoard=agcomprisBoard;
 
108
      gcomprisBoard->level=1;
 
109
      gcomprisBoard->maxlevel=6;
 
110
      gcomprisBoard->sublevel=1;
 
111
      gcomprisBoard->number_of_sublevel=1; /* Go to next level after this number of 'play' */
 
112
      gc_bar_set(GC_BAR_LEVEL);
 
113
 
 
114
      fifteen_next_level();
 
115
 
 
116
      gamewon = FALSE;
 
117
      pause_board(FALSE);
 
118
    }
 
119
}
 
120
/* ======================================= */
 
121
static void end_board ()
 
122
{
 
123
  if(gcomprisBoard!=NULL)
 
124
    {
 
125
      pause_board(TRUE);
 
126
      fifteen_destroy_all_items();
 
127
    }
 
128
  gcomprisBoard = NULL;
 
129
}
 
130
 
 
131
/* ======================================= */
 
132
static void set_level (guint level)
 
133
{
 
134
 
 
135
  if(gcomprisBoard!=NULL)
 
136
    {
 
137
      gcomprisBoard->level=level;
 
138
      gcomprisBoard->sublevel=1;
 
139
      fifteen_next_level();
 
140
    }
 
141
}
 
142
/* ======================================= */
 
143
static gboolean is_our_board (GcomprisBoard *gcomprisBoard)
 
144
{
 
145
  if (gcomprisBoard)
 
146
    {
 
147
      if(g_strcasecmp(gcomprisBoard->type, "fifteen")==0)
 
148
        {
 
149
          /* Set the plugin entry */
 
150
          gcomprisBoard->plugin=&menu_bp;
 
151
 
 
152
          return TRUE;
 
153
        }
 
154
    }
 
155
  return FALSE;
 
156
}
 
157
 
 
158
/*-------------------------------------------------------------------------------*/
 
159
/*-------------------------------------------------------------------------------*/
 
160
/* set initial values for the next level */
 
161
static void fifteen_next_level()
 
162
{
 
163
  gc_set_default_background(goo_canvas_get_root_item(gcomprisBoard->canvas));
 
164
 
 
165
  gc_bar_set_level(gcomprisBoard);
 
166
 
 
167
  fifteen_destroy_all_items();
 
168
  gamewon = FALSE;
 
169
 
 
170
  /* Create the level */
 
171
  fifteen_create_item(goo_canvas_get_root_item(gcomprisBoard->canvas));
 
172
 
 
173
 
 
174
}
 
175
/* ==================================== */
 
176
/* Destroy all the items */
 
177
static void fifteen_destroy_all_items()
 
178
{
 
179
  if(boardRootItem!=NULL)
 
180
    {
 
181
      GooCanvasItem **board;
 
182
      board = g_object_get_data (G_OBJECT (boardRootItem), "board");
 
183
      g_free(board);
 
184
      goo_canvas_item_remove(boardRootItem);
 
185
    }
 
186
  boardRootItem = NULL;
 
187
}
 
188
/* ==================================== */
 
189
static GooCanvasItem *fifteen_create_item(GooCanvasItem *parent)
 
190
{
 
191
  int i;
 
192
  int x, y;
 
193
  GooCanvasItem **board;
 
194
  GooCanvasItem *text;
 
195
  char buf[20];
 
196
  GdkPixbuf *pixmap = NULL;
 
197
 
 
198
  boardRootItem = goo_canvas_group_new (goo_canvas_get_root_item(gcomprisBoard->canvas),
 
199
                                   NULL);
 
200
 
 
201
  goo_canvas_item_translate(boardRootItem,
 
202
                            (BOARDWIDTH-(4*PIECE_SIZE))/2,
 
203
                            (BOARDHEIGHT-(4*PIECE_SIZE))/2);
 
204
 
 
205
  /* Load the cute frame */
 
206
  pixmap = gc_pixmap_load("fifteen/fifteen_frame.png");
 
207
 
 
208
  goo_canvas_image_new (boardRootItem,
 
209
                        pixmap,
 
210
                        -1*((gdk_pixbuf_get_width(pixmap)-(4*PIECE_SIZE))/2),
 
211
                        -1*((gdk_pixbuf_get_height(pixmap)-(4*PIECE_SIZE))/2)-2,
 
212
                        NULL);
 
213
  gdk_pixbuf_unref(pixmap);
 
214
 
 
215
 
 
216
  board = g_new (GooCanvasItem *, 16);
 
217
  g_object_set_data (G_OBJECT (boardRootItem), "board", board);
 
218
 
 
219
  for (i = 0; i < 15; i++) {
 
220
    y = i / 4;
 
221
    x = i % 4;
 
222
 
 
223
    board[i] = goo_canvas_group_new (boardRootItem, NULL);
 
224
 
 
225
    goo_canvas_item_translate(board[i],
 
226
                              (x * PIECE_SIZE),
 
227
                              (y * PIECE_SIZE));
 
228
 
 
229
    goo_canvas_rect_new (board[i],
 
230
                         0.0,
 
231
                         0.0,
 
232
                         PIECE_SIZE,
 
233
                         PIECE_SIZE,
 
234
                         "fill-color", get_piece_color (i),
 
235
                         "stroke-color", "black",
 
236
                         NULL);
 
237
 
 
238
    sprintf (buf, "%d", i + 1);
 
239
 
 
240
    text = goo_canvas_text_new (board[i],
 
241
                                buf,
 
242
                                (double) PIECE_SIZE / 2.0,
 
243
                                (double) PIECE_SIZE / 2.0,
 
244
                                -1,
 
245
                                GTK_ANCHOR_CENTER,
 
246
                                "font", gc_skin_font_board_medium,
 
247
                                "fill-color", "black",
 
248
                                NULL);
 
249
 
 
250
    g_object_set_data (G_OBJECT (board[i]), "piece_num", GINT_TO_POINTER (i));
 
251
    g_object_set_data (G_OBJECT (board[i]), "piece_pos", GINT_TO_POINTER (i));
 
252
    g_object_set_data (G_OBJECT (board[i]), "text", text);
 
253
    g_signal_connect (board[i], "button-press-event",
 
254
                      G_CALLBACK (piece_event),
 
255
                      NULL);
 
256
  }
 
257
 
 
258
  board[15] = NULL;
 
259
 
 
260
  /* Select level difficulty */
 
261
  switch(gcomprisBoard->level)
 
262
    {
 
263
    case 1:
 
264
      scramble(board, 10);
 
265
      break;
 
266
    case 2:
 
267
      scramble(board, 50);
 
268
      break;
 
269
    case 3:
 
270
    case 4:
 
271
      scramble(board, 100);
 
272
      break;
 
273
    case 5:
 
274
      scramble(board, 150);
 
275
      break;
 
276
    default:
 
277
      scramble(board, 256);
 
278
    }
 
279
 
 
280
  return NULL;
 
281
}
 
282
/* ==================================== */
 
283
static void game_won()
 
284
{
 
285
  gcomprisBoard->sublevel++;
 
286
 
 
287
  if(gcomprisBoard->sublevel>gcomprisBoard->number_of_sublevel) {
 
288
    /* Try the next level */
 
289
    gcomprisBoard->sublevel=1;
 
290
    gcomprisBoard->level++;
 
291
    if(gcomprisBoard->level>gcomprisBoard->maxlevel)
 
292
      gcomprisBoard->level = gcomprisBoard->maxlevel;
 
293
 
 
294
    gc_sound_play_ogg ("sounds/bonus.wav", NULL);
 
295
  }
 
296
  fifteen_next_level();
 
297
}
 
298
 
 
299
/*==================================================*/
 
300
/*   Code taken from libgnomecanvas demo fifteen    */
 
301
 
 
302
static void
 
303
test_win (GooCanvasItem **board)
 
304
{
 
305
  int i;
 
306
 
 
307
  for (i = 0; i < 15; i++)
 
308
    if (!board[i] || (GPOINTER_TO_INT (g_object_get_data (G_OBJECT (board[i]), "piece_num")) != i))
 
309
      return;
 
310
 
 
311
 
 
312
  gamewon = TRUE;
 
313
  fifteen_destroy_all_items();
 
314
  gc_bonus_display(gamewon, GC_BONUS_SMILEY);
 
315
 
 
316
}
 
317
 
 
318
static char *
 
319
get_piece_color (int piece)
 
320
{
 
321
  static char buf[50];
 
322
  int x, y;
 
323
  int r, g, b;
 
324
 
 
325
  y = piece / 4;
 
326
  x = piece % 4;
 
327
 
 
328
  r = ((4 - x) * 255) / 4;
 
329
  g = ((4 - y) * 255) / 4;
 
330
  b = 128;
 
331
 
 
332
  sprintf (buf, "#%02x%02x%02x", r, g, b);
 
333
 
 
334
  return buf;
 
335
}
 
336
 
 
337
static gboolean
 
338
piece_event (GooCanvasItem  *item,
 
339
             GooCanvasItem  *target,
 
340
             GdkEventButton *event,
 
341
             gpointer data)
 
342
{
 
343
  GooCanvasItem **board;
 
344
  GooCanvasItem *text;
 
345
  int num, pos, newpos;
 
346
  int x, y;
 
347
  double dx = 0.0, dy = 0.0;
 
348
  int move;
 
349
 
 
350
  board = g_object_get_data (G_OBJECT (goo_canvas_item_get_parent(item)), "board");
 
351
  num = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (item), "piece_num"));
 
352
  pos = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (item), "piece_pos"));
 
353
  text = g_object_get_data (G_OBJECT (item), "text");
 
354
 
 
355
  switch (event->type) {
 
356
  case GDK_ENTER_NOTIFY:
 
357
    g_object_set (text,
 
358
                  "fill-color", "white",
 
359
                  NULL);
 
360
    break;
 
361
 
 
362
  case GDK_LEAVE_NOTIFY:
 
363
    g_object_set (text,
 
364
                  "fill-color", "black",
 
365
                  NULL);
 
366
    break;
 
367
 
 
368
  case GDK_BUTTON_PRESS:
 
369
    y = pos / 4;
 
370
    x = pos % 4;
 
371
 
 
372
    move = TRUE;
 
373
 
 
374
    if ((y > 0) && (board[(y - 1) * 4 + x] == NULL)) {
 
375
      dx = 0.0;
 
376
      dy = -1.0;
 
377
      y--;
 
378
    } else if ((y < 3) && (board[(y + 1) * 4 + x] == NULL)) {
 
379
      dx = 0.0;
 
380
      dy = 1.0;
 
381
      y++;
 
382
    } else if ((x > 0) && (board[y * 4 + x - 1] == NULL)) {
 
383
      dx = -1.0;
 
384
      dy = 0.0;
 
385
      x--;
 
386
    } else if ((x < 3) && (board[y * 4 + x + 1] == NULL)) {
 
387
      dx = 1.0;
 
388
      dy = 0.0;
 
389
      x++;
 
390
    } else
 
391
      move = FALSE;
 
392
 
 
393
    if (move) {
 
394
      newpos = y * 4 + x;
 
395
      board[pos] = NULL;
 
396
      board[newpos] = item;
 
397
      g_object_set_data (G_OBJECT (item), "piece_pos", GINT_TO_POINTER (newpos));
 
398
      goo_canvas_item_translate (item, dx * PIECE_SIZE, dy * PIECE_SIZE);
 
399
 
 
400
      test_win (board);
 
401
    }
 
402
 
 
403
    break;
 
404
 
 
405
  default:
 
406
    break;
 
407
  }
 
408
 
 
409
  return FALSE;
 
410
}
 
411
 
 
412
static void
 
413
scramble (GooCanvasItem **board, guint number_of_scrambles)
 
414
{
 
415
  int i;
 
416
  int pos, oldpos;
 
417
  int dir;
 
418
  int x, y;
 
419
 
 
420
  /* g_random are initialised in gcompris launch */
 
421
  /* srand (time (NULL)); */
 
422
 
 
423
  /* First, find the blank spot */
 
424
 
 
425
  for (pos = 0; pos < 16; pos++)
 
426
    if (board[pos] == NULL)
 
427
      break;
 
428
 
 
429
  /* "Move the blank spot" around in order to scramble the pieces */
 
430
 
 
431
  for (i = 0; i < number_of_scrambles; i++) {
 
432
  retry_scramble:
 
433
    dir = g_random_int () % 4;
 
434
 
 
435
    x = y = 0;
 
436
 
 
437
    if ((dir == 0) && (pos > 3)) /* up */
 
438
      y = -1;
 
439
    else if ((dir == 1) && (pos < 12)) /* down */
 
440
      y = 1;
 
441
    else if ((dir == 2) && ((pos % 4) != 0)) /* left */
 
442
      x = -1;
 
443
    else if ((dir == 3) && ((pos % 4) != 3)) /* right */
 
444
      x = 1;
 
445
    else
 
446
      goto retry_scramble;
 
447
 
 
448
    oldpos = pos + y * 4 + x;
 
449
    board[pos] = board[oldpos];
 
450
    board[oldpos] = NULL;
 
451
    g_object_set_data (G_OBJECT (board[pos]), "piece_pos", GINT_TO_POINTER (pos));
 
452
    goo_canvas_item_translate (board[pos], -x * PIECE_SIZE, -y * PIECE_SIZE);
 
453
    pos = oldpos;
 
454
  }
 
455
}
 
456