1
/* gcompris - superbrain.c
3
* Copyright (C) 2002 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"
21
#define SOUNDLISTFILE PACKAGE
23
static GcomprisBoard *gcomprisBoard = NULL;
24
static gboolean board_paused = TRUE;
27
* Contains the points that represents the anchors
30
GnomeCanvasGroup *rootitem;
33
GnomeCanvasItem *good;
34
GnomeCanvasItem *misplaced;
38
static GList * listPieces = NULL;
40
static guint colors[] =
56
#define PIECE_WIDTH 20
57
#define PIECE_HEIGHT 20
59
#define PIECE_GAP_GOOD 5
60
#define SCROLL_LIMIT 160
61
#define PLAYING_AREA_X 190
62
#define PLAYING_HELP_X (BOARDWIDTH-80)
64
#define COLOR_GOOD 0x00000080
65
#define COLOR_MISPLACED 0xFFFFFF80
67
#define PIECE_DISPLAY_X 40
68
#define PIECE_DISPLAY_Y 35
70
static void process_ok(void);
71
static void start_board (GcomprisBoard *agcomprisBoard);
72
static void pause_board (gboolean pause);
73
static void end_board (void);
74
static gboolean is_our_board (GcomprisBoard *gcomprisBoard);
75
static void set_level (guint level);
77
static void game_won(void);
79
static GnomeCanvasGroup *boardRootItem = NULL;
80
static GnomeCanvasGroup *boardLogoItem = NULL;
83
static GnomeCanvasItem *superbrain_create_item(GnomeCanvasGroup *parent);
84
static void superbrain_destroy_all_items(void);
85
static void superbrain_next_level(void);
86
static gint item_event(GnomeCanvasItem *item, GdkEvent *event, Piece *piece);
87
static void mark_pieces(void);
89
static guint number_of_color = 0;
90
static guint number_of_piece = 0;
91
static gint current_y_position = 0;
94
static guint solution[MAX_PIECES];
96
#define LEVEL_MAX_FOR_HELP 4
98
#define Y_STEP (PIECE_HEIGHT+PIECE_GAP)
100
/* Description of this plugin */
101
static BoardPlugin menu_bp =
106
N_("Tux has hidden several items. Find them again in the correct order"),
107
"Bruno Coudoin <bruno.coudoin@free.fr>",
126
* Main entry point mandatory for each Gcompris's game
127
* ---------------------------------------------------
131
GET_BPLUGIN_INFO(superbrain)
134
* in : boolean TRUE = PAUSE : FALSE = CONTINUE
137
static void pause_board (gboolean pause)
139
if(gcomprisBoard==NULL)
142
if(gamewon == TRUE && pause == FALSE) /* the game is won */
147
board_paused = pause;
152
static void start_board (GcomprisBoard *agcomprisBoard)
155
if(agcomprisBoard!=NULL)
157
gcomprisBoard=agcomprisBoard;
158
gcomprisBoard->level=1;
159
gcomprisBoard->maxlevel=6;
160
gcomprisBoard->sublevel=1;
161
gcomprisBoard->number_of_sublevel=1; /* Go to next level after this number of 'play' */
162
gc_bar_set(GC_BAR_OK|GC_BAR_LEVEL);
164
superbrain_next_level();
170
/* ======================================= */
171
static void end_board ()
173
if(gcomprisBoard!=NULL)
176
superbrain_destroy_all_items();
178
gcomprisBoard = NULL;
181
/* ======================================= */
182
static void set_level (guint level)
185
if(gcomprisBoard!=NULL)
187
gcomprisBoard->level=level;
188
gcomprisBoard->sublevel=1;
189
superbrain_next_level();
192
/* ======================================= */
193
static gboolean is_our_board (GcomprisBoard *gcomprisBoard)
197
if(g_strcasecmp(gcomprisBoard->type, "superbrain")==0)
199
/* Set the plugin entry */
200
gcomprisBoard->plugin=&menu_bp;
208
/* ======================================= */
209
static void process_ok() {
214
gc_bonus_display(gamewon, GC_BONUS_SMILEY);
217
/*-------------------------------------------------------------------------------*/
218
/*-------------------------------------------------------------------------------*/
219
/* set initial values for the next level */
220
static void superbrain_next_level()
223
gboolean selected_color[MAX_COLORS];
225
gc_set_background(gnome_canvas_root(gcomprisBoard->canvas),
226
"opt/superbrain_background.jpg");
228
gc_bar_set_level(gcomprisBoard);
230
superbrain_destroy_all_items();
233
/* Select level difficulty : should not go above MAX_PIECES */
234
/* number_of_color must be upper than number_of_piece to allow unicity */
236
if(gcomprisBoard->level < LEVEL_MAX_FOR_HELP)
238
number_of_piece = gcomprisBoard->level + 2;
239
number_of_color = gcomprisBoard->level + 4;
243
number_of_piece = gcomprisBoard->level - LEVEL_MAX_FOR_HELP + 3;
244
number_of_color = gcomprisBoard->level - LEVEL_MAX_FOR_HELP + 5;
248
current_y_position = BOARDHEIGHT - 50;
250
/* Init a random solution : colors choosen are uniquely choosen */
251
for(i=0; i<number_of_color; i++)
253
selected_color[i] = FALSE;
256
for(i=0; i<number_of_piece; i++)
260
j = (guint)g_random_int_range(1, number_of_color);
261
while(selected_color[j])
262
j = (guint)g_random_int_range(1, number_of_color);
265
selected_color[j] = TRUE;
270
boardRootItem = GNOME_CANVAS_GROUP(
271
gnome_canvas_item_new (gnome_canvas_root(gcomprisBoard->canvas),
272
gnome_canvas_group_get_type (),
277
boardLogoItem = GNOME_CANVAS_GROUP(
278
gnome_canvas_item_new (gnome_canvas_root(gcomprisBoard->canvas),
279
gnome_canvas_group_get_type (),
284
/* The list of the pieces */
285
for(i=0; i<number_of_color; i++)
287
gnome_canvas_item_new (boardLogoItem,
288
gnome_canvas_ellipse_get_type(),
289
"x1", (double) PIECE_DISPLAY_X,
290
"y1", (double) PIECE_DISPLAY_Y + i*PIECE_WIDTH*1.2 + (i*PIECE_GAP*1.2),
291
"x2", (double) PIECE_DISPLAY_X + PIECE_WIDTH*1.2,
292
"y2", (double) PIECE_DISPLAY_Y + i*PIECE_WIDTH*1.2 + PIECE_HEIGHT*1.2 + (i*PIECE_GAP*1.2),
293
"fill_color_rgba", colors[i],
294
"outline_color", "white",
295
"width_units", (double)1,
300
superbrain_create_item(boardRootItem);
302
/* ==================================== */
303
/* Destroy all the items */
304
static void superbrain_destroy_all_items()
306
if(boardRootItem!=NULL)
307
gtk_object_destroy (GTK_OBJECT(boardRootItem));
309
boardRootItem = NULL;
311
if(boardLogoItem!=NULL)
312
gtk_object_destroy (GTK_OBJECT(boardLogoItem));
314
boardLogoItem = NULL;
316
/* ==================================== */
317
static GnomeCanvasItem *superbrain_create_item(GnomeCanvasGroup *parent)
321
GnomeCanvasItem *item = NULL;
323
GnomeCanvasPoints *points;
325
if(current_y_position < SCROLL_LIMIT)
327
gnome_canvas_item_move(GNOME_CANVAS_ITEM(boardRootItem), 0.0, (double)Y_STEP);
330
x = (BOARDWIDTH - number_of_piece*(PIECE_WIDTH+PIECE_GAP))/2 + PLAYING_AREA_X;
332
/* Draw a line to separate cleanly */
333
x1 = x + PIECE_WIDTH/2;
334
x2 = (BOARDWIDTH + (number_of_piece-1)*(PIECE_WIDTH+PIECE_GAP))/2 - PIECE_WIDTH/2 + PLAYING_AREA_X;
336
points = gnome_canvas_points_new(2);
337
points->coords[0] = (double) x1;
338
points->coords[1] = (double) current_y_position + PIECE_HEIGHT + PIECE_GAP/2;
339
points->coords[2] = (double) x2;
340
points->coords[3] = (double) current_y_position + PIECE_HEIGHT + PIECE_GAP/2;
342
gnome_canvas_item_new (boardRootItem,
343
gnome_canvas_line_get_type (),
345
"fill_color", "white",
349
points->coords[0] = (double) x1 + 2;
350
points->coords[1] = (double) current_y_position + PIECE_HEIGHT + PIECE_GAP/2 + 1;
351
points->coords[2] = (double) x2 + 2;
352
points->coords[3] = (double) current_y_position + PIECE_HEIGHT + PIECE_GAP/2 + 1;
354
gnome_canvas_item_new (boardRootItem,
355
gnome_canvas_line_get_type (),
357
"fill_color", "black",
361
/* Continuing the line */
362
// x1 = (BOARDWIDTH + (number_of_piece+2)*(PIECE_WIDTH+PIECE_GAP))/2 + PLAYING_AREA_X;
364
x2 = x1 + number_of_piece*PIECE_WIDTH/2;
366
points->coords[0] = (double) x1;
367
points->coords[1] = (double) current_y_position + PIECE_HEIGHT + PIECE_GAP/2;
368
points->coords[2] = (double) x2;
369
points->coords[3] = (double) current_y_position + PIECE_HEIGHT + PIECE_GAP/2;
371
gnome_canvas_item_new (boardRootItem,
372
gnome_canvas_line_get_type (),
374
"fill_color", "white",
378
points->coords[0] = (double) x1 + 2;
379
points->coords[1] = (double) current_y_position + PIECE_HEIGHT + PIECE_GAP/2 + 1;
380
points->coords[2] = (double) x2 + 2;
381
points->coords[3] = (double) current_y_position + PIECE_HEIGHT + PIECE_GAP/2 + 1;
383
gnome_canvas_item_new (boardRootItem,
384
gnome_canvas_line_get_type (),
386
"fill_color", "black",
390
gnome_canvas_points_unref(points);
392
/* Draw the pieces */
393
listPieces = g_list_alloc();
395
for(i=0; i<number_of_piece; i++)
398
piece = g_new(Piece, 1);
399
piece->listitem = g_list_alloc();
400
piece->completed = FALSE;
401
listPieces = g_list_append(listPieces, piece);
403
piece->rootitem = GNOME_CANVAS_GROUP(
404
gnome_canvas_item_new (parent,
405
gnome_canvas_group_get_type (),
413
piece->good = gnome_canvas_item_new (piece->rootitem,
414
gnome_canvas_rect_get_type (),
415
"x1", (double) x + i*PIECE_WIDTH + (i*PIECE_GAP) - PIECE_GAP_GOOD,
416
"y1", (double) current_y_position - PIECE_GAP_GOOD,
417
"x2", (double) x + i*PIECE_WIDTH + PIECE_WIDTH + (i*PIECE_GAP) + PIECE_GAP_GOOD,
418
"y2", (double) current_y_position + PIECE_HEIGHT + PIECE_GAP_GOOD,
419
"fill_color_rgba", COLOR_GOOD,
420
"outline_color", "white",
421
"width_units", (double)1,
423
gnome_canvas_item_hide(piece->good);
426
piece->misplaced = gnome_canvas_item_new (piece->rootitem,
427
gnome_canvas_rect_get_type (),
428
"x1", (double) x + i*PIECE_WIDTH + (i*PIECE_GAP) - PIECE_GAP_GOOD,
429
"y1", (double) current_y_position - PIECE_GAP_GOOD,
430
"x2", (double) x + i*PIECE_WIDTH + PIECE_WIDTH + (i*PIECE_GAP) + PIECE_GAP_GOOD,
431
"y2", (double) current_y_position + PIECE_HEIGHT + PIECE_GAP_GOOD,
432
"fill_color_rgba", COLOR_MISPLACED,
433
"outline_color", "white",
434
"width_units", (double)1,
436
gnome_canvas_item_hide(piece->misplaced);
438
for(j=0; j<number_of_color; j++)
440
item = gnome_canvas_item_new (piece->rootitem,
441
gnome_canvas_ellipse_get_type(),
442
"x1", (double) x + i*PIECE_WIDTH + (i*PIECE_GAP),
443
"y1", (double) current_y_position,
444
"x2", (double) x + i*PIECE_WIDTH + PIECE_WIDTH + (i*PIECE_GAP),
445
"y2", (double) current_y_position + PIECE_HEIGHT,
446
"fill_color_rgba", colors[j],
447
"outline_color", "white",
448
"width_units", (double)1,
451
gnome_canvas_item_hide(item);
452
piece->listitem = g_list_append(piece->listitem, item);
454
gtk_signal_connect(GTK_OBJECT(item), "event", (GtkSignalFunc) item_event, piece);
457
piece->selecteditem = 1;
458
item = g_list_nth_data(piece->listitem,
459
piece->selecteditem);
460
gnome_canvas_item_show(item);
466
/* ==================================== */
467
static void game_won()
469
gcomprisBoard->sublevel++;
471
if(gcomprisBoard->sublevel>gcomprisBoard->number_of_sublevel) {
472
/* Try the next level */
473
gcomprisBoard->sublevel=1;
474
gcomprisBoard->level++;
475
if(gcomprisBoard->level>gcomprisBoard->maxlevel) { // the current board is finished : bail out
476
gc_bonus_end_display(GC_BOARD_FINISHED_RANDOM);
479
gc_sound_play_ogg ("sounds/bonus.wav", NULL);
481
superbrain_next_level();
484
/* ==================================== */
486
item_event(GnomeCanvasItem *item, GdkEvent *event, Piece *piece)
488
GnomeCanvasItem *newitem;
495
case GDK_BUTTON_PRESS:
496
if(!piece->completed)
498
gnome_canvas_item_hide(item);
500
switch(event->button.button)
504
piece->selecteditem++;
505
if(piece->selecteditem>=g_list_length(piece->listitem))
506
piece->selecteditem = 1;
511
piece->selecteditem--;
512
if(piece->selecteditem<=0)
513
piece->selecteditem = g_list_length(piece->listitem)-1;
517
newitem = g_list_nth_data(piece->listitem,
518
piece->selecteditem);
519
gnome_canvas_item_show(newitem);
529
static void mark_pieces()
535
guint nbmisplaced = 0;
536
guint solution_tmp[MAX_PIECES];
538
for(i=0; i<number_of_piece; i++)
540
solution_tmp[i] = solution[i];
545
/* Mark good placed */
546
for(i=1; i<g_list_length(listPieces); i++)
548
piece = g_list_nth_data(listPieces, i);
549
if(piece->selecteditem == solution_tmp[i-1])
551
if(gcomprisBoard->level<LEVEL_MAX_FOR_HELP)
552
gnome_canvas_item_show(piece->good);
554
solution_tmp[i-1] = G_MAXINT;
561
piece->completed = TRUE;
565
for(i=1; i<=number_of_piece; i++)
569
piece = g_list_nth_data(listPieces, i);
571
/* Search if this color is elsewhere */
575
if(piece->selecteditem != solution[i-1] &&
576
piece->selecteditem == solution_tmp[j-1])
579
solution_tmp[j-1] = G_MAXINT;
580
if(gcomprisBoard->level<LEVEL_MAX_FOR_HELP)
581
gnome_canvas_item_show(piece->misplaced);
584
} while (!done && j++!=number_of_piece);
587
/* Display the matermind information to the user */
588
// x = (BOARDWIDTH + (number_of_piece+2)*(PIECE_WIDTH+PIECE_GAP))/2;
590
for(i=0; i<nbgood; i++)
592
gnome_canvas_item_new (boardRootItem,
593
gnome_canvas_ellipse_get_type(),
594
"x1", (double) x + i*PIECE_WIDTH/2 + (i*PIECE_GAP/2),
595
"y1", (double) current_y_position,
596
"x2", (double) x + i*PIECE_WIDTH/2 + PIECE_WIDTH/2 + (i*PIECE_GAP/2),
597
"y2", (double) current_y_position + PIECE_HEIGHT/2,
598
"fill_color", "black",
599
"outline_color", "white",
600
"width_units", (double)1,
604
for(i=0; i<nbmisplaced; i++)
606
gnome_canvas_item_new (boardRootItem,
607
gnome_canvas_ellipse_get_type(),
608
"x1", (double) x + i*PIECE_WIDTH/2 + (i*PIECE_GAP/2),
609
"y1", (double) current_y_position + PIECE_HEIGHT/2 + PIECE_GAP/3,
610
"x2", (double) x + i*PIECE_WIDTH/2 + PIECE_WIDTH/2 + (i*PIECE_GAP/2),
611
"y2", (double) current_y_position + PIECE_HEIGHT + PIECE_GAP/3,
612
"fill_color", "white",
613
"outline_color", "black",
614
"width_units", (double)1,
618
current_y_position -= Y_STEP;
621
for(l=listPieces; l; l= l->next)
624
g_list_free(listPieces);
626
superbrain_create_item(boardRootItem);