1
/* gcompris - fifteen.c
3
* Copyright (C) 2003, 2008 Bruno Coudoin
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.
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.
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/>.
19
#include "gcompris/gcompris.h"
24
#define SOUNDLISTFILE PACKAGE
26
static GcomprisBoard *gcomprisBoard = NULL;
27
static gboolean board_paused = TRUE;
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);
35
static void game_won(void);
37
static GooCanvasItem *boardRootItem = NULL;
39
static GooCanvasItem *fifteen_create_item(GooCanvasItem *parent);
40
static void fifteen_destroy_all_items(void);
41
static void fifteen_next_level(void);
43
static gboolean piece_event (GooCanvasItem *item,
44
GooCanvasItem *target,
45
GdkEventButton *event,
47
static void scramble (GooCanvasItem **board, guint number_of_scrambles);
48
static char *get_piece_color (int piece);
50
/* Description of this plugin */
51
static BoardPlugin menu_bp =
56
"Move the items one by one, to rearrange them in increasing order",
57
"Bruno Coudoin <bruno.coudoin@free.fr>",
76
* Main entry point mandatory for each Gcompris's game
77
* ---------------------------------------------------
81
GET_BPLUGIN_INFO(fifteen)
84
* in : boolean TRUE = PAUSE : FALSE = CONTINUE
87
static void pause_board (gboolean pause)
89
if(gcomprisBoard==NULL)
92
if(gamewon == TRUE && pause == FALSE) /* the game is won */
102
static void start_board (GcomprisBoard *agcomprisBoard)
105
if(agcomprisBoard!=NULL)
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);
114
fifteen_next_level();
120
/* ======================================= */
121
static void end_board ()
123
if(gcomprisBoard!=NULL)
126
fifteen_destroy_all_items();
128
gcomprisBoard = NULL;
131
/* ======================================= */
132
static void set_level (guint level)
135
if(gcomprisBoard!=NULL)
137
gcomprisBoard->level=level;
138
gcomprisBoard->sublevel=1;
139
fifteen_next_level();
142
/* ======================================= */
143
static gboolean is_our_board (GcomprisBoard *gcomprisBoard)
147
if(g_strcasecmp(gcomprisBoard->type, "fifteen")==0)
149
/* Set the plugin entry */
150
gcomprisBoard->plugin=&menu_bp;
158
/*-------------------------------------------------------------------------------*/
159
/*-------------------------------------------------------------------------------*/
160
/* set initial values for the next level */
161
static void fifteen_next_level()
163
gc_set_default_background(goo_canvas_get_root_item(gcomprisBoard->canvas));
165
gc_bar_set_level(gcomprisBoard);
167
fifteen_destroy_all_items();
170
/* Create the level */
171
fifteen_create_item(goo_canvas_get_root_item(gcomprisBoard->canvas));
175
/* ==================================== */
176
/* Destroy all the items */
177
static void fifteen_destroy_all_items()
179
if(boardRootItem!=NULL)
181
GooCanvasItem **board;
182
board = g_object_get_data (G_OBJECT (boardRootItem), "board");
184
goo_canvas_item_remove(boardRootItem);
186
boardRootItem = NULL;
188
/* ==================================== */
189
static GooCanvasItem *fifteen_create_item(GooCanvasItem *parent)
193
GooCanvasItem **board;
196
GdkPixbuf *pixmap = NULL;
198
boardRootItem = goo_canvas_group_new (goo_canvas_get_root_item(gcomprisBoard->canvas),
201
goo_canvas_item_translate(boardRootItem,
202
(BOARDWIDTH-(4*PIECE_SIZE))/2,
203
(BOARDHEIGHT-(4*PIECE_SIZE))/2);
205
/* Load the cute frame */
206
pixmap = gc_pixmap_load("fifteen/fifteen_frame.png");
208
goo_canvas_image_new (boardRootItem,
210
-1*((gdk_pixbuf_get_width(pixmap)-(4*PIECE_SIZE))/2),
211
-1*((gdk_pixbuf_get_height(pixmap)-(4*PIECE_SIZE))/2)-2,
213
gdk_pixbuf_unref(pixmap);
216
board = g_new (GooCanvasItem *, 16);
217
g_object_set_data (G_OBJECT (boardRootItem), "board", board);
219
for (i = 0; i < 15; i++) {
223
board[i] = goo_canvas_group_new (boardRootItem, NULL);
225
goo_canvas_item_translate(board[i],
229
goo_canvas_rect_new (board[i],
234
"fill-color", get_piece_color (i),
235
"stroke-color", "black",
238
sprintf (buf, "%d", i + 1);
240
text = goo_canvas_text_new (board[i],
242
(double) PIECE_SIZE / 2.0,
243
(double) PIECE_SIZE / 2.0,
246
"font", gc_skin_font_board_medium,
247
"fill-color", "black",
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),
260
/* Select level difficulty */
261
switch(gcomprisBoard->level)
271
scramble(board, 100);
274
scramble(board, 150);
277
scramble(board, 256);
282
/* ==================================== */
283
static void game_won()
285
gcomprisBoard->sublevel++;
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;
294
gc_sound_play_ogg ("sounds/bonus.wav", NULL);
296
fifteen_next_level();
299
/*==================================================*/
300
/* Code taken from libgnomecanvas demo fifteen */
303
test_win (GooCanvasItem **board)
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))
313
fifteen_destroy_all_items();
314
gc_bonus_display(gamewon, GC_BONUS_SMILEY);
319
get_piece_color (int piece)
328
r = ((4 - x) * 255) / 4;
329
g = ((4 - y) * 255) / 4;
332
sprintf (buf, "#%02x%02x%02x", r, g, b);
338
piece_event (GooCanvasItem *item,
339
GooCanvasItem *target,
340
GdkEventButton *event,
343
GooCanvasItem **board;
345
int num, pos, newpos;
347
double dx = 0.0, dy = 0.0;
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");
355
switch (event->type) {
356
case GDK_ENTER_NOTIFY:
358
"fill-color", "white",
362
case GDK_LEAVE_NOTIFY:
364
"fill-color", "black",
368
case GDK_BUTTON_PRESS:
374
if ((y > 0) && (board[(y - 1) * 4 + x] == NULL)) {
378
} else if ((y < 3) && (board[(y + 1) * 4 + x] == NULL)) {
382
} else if ((x > 0) && (board[y * 4 + x - 1] == NULL)) {
386
} else if ((x < 3) && (board[y * 4 + x + 1] == 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);
413
scramble (GooCanvasItem **board, guint number_of_scrambles)
420
/* g_random are initialised in gcompris launch */
421
/* srand (time (NULL)); */
423
/* First, find the blank spot */
425
for (pos = 0; pos < 16; pos++)
426
if (board[pos] == NULL)
429
/* "Move the blank spot" around in order to scramble the pieces */
431
for (i = 0; i < number_of_scrambles; i++) {
433
dir = g_random_int () % 4;
437
if ((dir == 0) && (pos > 3)) /* up */
439
else if ((dir == 1) && (pos < 12)) /* down */
441
else if ((dir == 2) && ((pos % 4) != 0)) /* left */
443
else if ((dir == 3) && ((pos % 4) != 3)) /* right */
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);