/* gcompris - superbrain.c * * Copyright (C) 2002 Bruno Coudoin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . */ #include "gcompris/gcompris.h" #define SOUNDLISTFILE PACKAGE static GcomprisBoard *gcomprisBoard = NULL; static gboolean board_paused = TRUE; /* * Contains the points that represents the anchors */ typedef struct { GnomeCanvasGroup *rootitem; GList *listitem; guint selecteditem; GnomeCanvasItem *good; GnomeCanvasItem *misplaced; gboolean completed; } Piece; static GList * listPieces = NULL; static guint colors[] = { 0x0000FF80, 0x00FF0080, 0xFF000080, 0x00FFFF80, 0xFF00FF80, 0xFFFF0080, 0x00007F80, 0x007F0080, 0x7F000080, 0x7F007F80, }; #define MAX_COLORS 10 #define PIECE_WIDTH 20 #define PIECE_HEIGHT 20 #define PIECE_GAP 18 #define PIECE_GAP_GOOD 5 #define SCROLL_LIMIT 160 #define PLAYING_AREA_X 190 #define PLAYING_HELP_X (BOARDWIDTH-80) #define COLOR_GOOD 0x00000080 #define COLOR_MISPLACED 0xFFFFFF80 #define PIECE_DISPLAY_X 40 #define PIECE_DISPLAY_Y 35 static void process_ok(void); static void start_board (GcomprisBoard *agcomprisBoard); static void pause_board (gboolean pause); static void end_board (void); static gboolean is_our_board (GcomprisBoard *gcomprisBoard); static void set_level (guint level); static int gamewon; static void game_won(void); static GnomeCanvasGroup *boardRootItem = NULL; static GnomeCanvasGroup *boardLogoItem = NULL; static GnomeCanvasItem *superbrain_create_item(GnomeCanvasGroup *parent); static void superbrain_destroy_all_items(void); static void superbrain_next_level(void); static gint item_event(GnomeCanvasItem *item, GdkEvent *event, Piece *piece); static void mark_pieces(void); static guint number_of_color = 0; static guint number_of_piece = 0; static gint current_y_position = 0; #define MAX_PIECES 10 static guint solution[MAX_PIECES]; #define LEVEL_MAX_FOR_HELP 4 #define Y_STEP (PIECE_HEIGHT+PIECE_GAP) /* Description of this plugin */ static BoardPlugin menu_bp = { NULL, NULL, N_("Super Brain"), N_("Tux has hidden several items. Find them again in the correct order"), "Bruno Coudoin ", NULL, NULL, NULL, NULL, start_board, pause_board, end_board, is_our_board, NULL, process_ok, set_level, NULL, NULL, NULL, NULL }; /* * Main entry point mandatory for each Gcompris's game * --------------------------------------------------- * */ GET_BPLUGIN_INFO(superbrain) /* * in : boolean TRUE = PAUSE : FALSE = CONTINUE * */ static void pause_board (gboolean pause) { if(gcomprisBoard==NULL) return; if(gamewon == TRUE && pause == FALSE) /* the game is won */ { game_won(); } board_paused = pause; } /* */ static void start_board (GcomprisBoard *agcomprisBoard) { if(agcomprisBoard!=NULL) { gcomprisBoard=agcomprisBoard; gcomprisBoard->level=1; gcomprisBoard->maxlevel=6; gcomprisBoard->sublevel=1; gcomprisBoard->number_of_sublevel=1; /* Go to next level after this number of 'play' */ gc_bar_set(GC_BAR_OK|GC_BAR_LEVEL); superbrain_next_level(); gamewon = FALSE; pause_board(FALSE); } } /* ======================================= */ static void end_board () { if(gcomprisBoard!=NULL) { pause_board(TRUE); superbrain_destroy_all_items(); } gcomprisBoard = NULL; } /* ======================================= */ static void set_level (guint level) { if(gcomprisBoard!=NULL) { gcomprisBoard->level=level; gcomprisBoard->sublevel=1; superbrain_next_level(); } } /* ======================================= */ static gboolean is_our_board (GcomprisBoard *gcomprisBoard) { if (gcomprisBoard) { if(g_strcasecmp(gcomprisBoard->type, "superbrain")==0) { /* Set the plugin entry */ gcomprisBoard->plugin=&menu_bp; return TRUE; } } return FALSE; } /* ======================================= */ static void process_ok() { mark_pieces(); if(gamewon) gc_bonus_display(gamewon, GC_BONUS_SMILEY); } /*-------------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------------*/ /* set initial values for the next level */ static void superbrain_next_level() { guint i; gboolean selected_color[MAX_COLORS]; gc_set_background(gnome_canvas_root(gcomprisBoard->canvas), "opt/superbrain_background.jpg"); gc_bar_set_level(gcomprisBoard); superbrain_destroy_all_items(); gamewon = FALSE; /* Select level difficulty : should not go above MAX_PIECES */ /* number_of_color must be upper than number_of_piece to allow unicity */ if(gcomprisBoard->level < LEVEL_MAX_FOR_HELP) { number_of_piece = gcomprisBoard->level + 2; number_of_color = gcomprisBoard->level + 4; } else { number_of_piece = gcomprisBoard->level - LEVEL_MAX_FOR_HELP + 3; number_of_color = gcomprisBoard->level - LEVEL_MAX_FOR_HELP + 5; } current_y_position = BOARDHEIGHT - 50; /* Init a random solution : colors choosen are uniquely choosen */ for(i=0; icanvas), gnome_canvas_group_get_type (), "x", (double) 0, "y", (double) 0, NULL)); boardLogoItem = GNOME_CANVAS_GROUP( gnome_canvas_item_new (gnome_canvas_root(gcomprisBoard->canvas), gnome_canvas_group_get_type (), "x", (double) 0, "y", (double) 0, NULL)); /* The list of the pieces */ for(i=0; icoords[0] = (double) x1; points->coords[1] = (double) current_y_position + PIECE_HEIGHT + PIECE_GAP/2; points->coords[2] = (double) x2; points->coords[3] = (double) current_y_position + PIECE_HEIGHT + PIECE_GAP/2; gnome_canvas_item_new (boardRootItem, gnome_canvas_line_get_type (), "points", points, "fill_color", "white", "width_pixels", 1, NULL); points->coords[0] = (double) x1 + 2; points->coords[1] = (double) current_y_position + PIECE_HEIGHT + PIECE_GAP/2 + 1; points->coords[2] = (double) x2 + 2; points->coords[3] = (double) current_y_position + PIECE_HEIGHT + PIECE_GAP/2 + 1; gnome_canvas_item_new (boardRootItem, gnome_canvas_line_get_type (), "points", points, "fill_color", "black", "width_pixels", 1, NULL); /* Continuing the line */ // x1 = (BOARDWIDTH + (number_of_piece+2)*(PIECE_WIDTH+PIECE_GAP))/2 + PLAYING_AREA_X; x1 = PLAYING_HELP_X; x2 = x1 + number_of_piece*PIECE_WIDTH/2; points->coords[0] = (double) x1; points->coords[1] = (double) current_y_position + PIECE_HEIGHT + PIECE_GAP/2; points->coords[2] = (double) x2; points->coords[3] = (double) current_y_position + PIECE_HEIGHT + PIECE_GAP/2; gnome_canvas_item_new (boardRootItem, gnome_canvas_line_get_type (), "points", points, "fill_color", "white", "width_pixels", 1, NULL); points->coords[0] = (double) x1 + 2; points->coords[1] = (double) current_y_position + PIECE_HEIGHT + PIECE_GAP/2 + 1; points->coords[2] = (double) x2 + 2; points->coords[3] = (double) current_y_position + PIECE_HEIGHT + PIECE_GAP/2 + 1; gnome_canvas_item_new (boardRootItem, gnome_canvas_line_get_type (), "points", points, "fill_color", "black", "width_pixels", 1, NULL); gnome_canvas_points_unref(points); /* Draw the pieces */ listPieces = g_list_alloc(); for(i=0; ilistitem = g_list_alloc(); piece->completed = FALSE; listPieces = g_list_append(listPieces, piece); piece->rootitem = GNOME_CANVAS_GROUP( gnome_canvas_item_new (parent, gnome_canvas_group_get_type (), "x", (double) 0, "y", (double) 0, NULL)); // Good piece->good = gnome_canvas_item_new (piece->rootitem, gnome_canvas_rect_get_type (), "x1", (double) x + i*PIECE_WIDTH + (i*PIECE_GAP) - PIECE_GAP_GOOD, "y1", (double) current_y_position - PIECE_GAP_GOOD, "x2", (double) x + i*PIECE_WIDTH + PIECE_WIDTH + (i*PIECE_GAP) + PIECE_GAP_GOOD, "y2", (double) current_y_position + PIECE_HEIGHT + PIECE_GAP_GOOD, "fill_color_rgba", COLOR_GOOD, "outline_color", "white", "width_units", (double)1, NULL); gnome_canvas_item_hide(piece->good); // Misplaced piece->misplaced = gnome_canvas_item_new (piece->rootitem, gnome_canvas_rect_get_type (), "x1", (double) x + i*PIECE_WIDTH + (i*PIECE_GAP) - PIECE_GAP_GOOD, "y1", (double) current_y_position - PIECE_GAP_GOOD, "x2", (double) x + i*PIECE_WIDTH + PIECE_WIDTH + (i*PIECE_GAP) + PIECE_GAP_GOOD, "y2", (double) current_y_position + PIECE_HEIGHT + PIECE_GAP_GOOD, "fill_color_rgba", COLOR_MISPLACED, "outline_color", "white", "width_units", (double)1, NULL); gnome_canvas_item_hide(piece->misplaced); for(j=0; jrootitem, gnome_canvas_ellipse_get_type(), "x1", (double) x + i*PIECE_WIDTH + (i*PIECE_GAP), "y1", (double) current_y_position, "x2", (double) x + i*PIECE_WIDTH + PIECE_WIDTH + (i*PIECE_GAP), "y2", (double) current_y_position + PIECE_HEIGHT, "fill_color_rgba", colors[j], "outline_color", "white", "width_units", (double)1, NULL); gnome_canvas_item_hide(item); piece->listitem = g_list_append(piece->listitem, item); gtk_signal_connect(GTK_OBJECT(item), "event", (GtkSignalFunc) item_event, piece); } piece->selecteditem = 1; item = g_list_nth_data(piece->listitem, piece->selecteditem); gnome_canvas_item_show(item); } return NULL; } /* ==================================== */ static void game_won() { gcomprisBoard->sublevel++; if(gcomprisBoard->sublevel>gcomprisBoard->number_of_sublevel) { /* Try the next level */ gcomprisBoard->sublevel=1; gcomprisBoard->level++; if(gcomprisBoard->level>gcomprisBoard->maxlevel) { // the current board is finished : bail out gc_bonus_end_display(GC_BOARD_FINISHED_RANDOM); return; } gc_sound_play_ogg ("sounds/bonus.wav", NULL); } superbrain_next_level(); } /* ==================================== */ static gint item_event(GnomeCanvasItem *item, GdkEvent *event, Piece *piece) { GnomeCanvasItem *newitem; if(board_paused) return FALSE; switch (event->type) { case GDK_BUTTON_PRESS: if(!piece->completed) { gnome_canvas_item_hide(item); switch(event->button.button) { case 1: case 4: piece->selecteditem++; if(piece->selecteditem>=g_list_length(piece->listitem)) piece->selecteditem = 1; break; case 2: case 3: case 5: piece->selecteditem--; if(piece->selecteditem<=0) piece->selecteditem = g_list_length(piece->listitem)-1; break; } newitem = g_list_nth_data(piece->listitem, piece->selecteditem); gnome_canvas_item_show(newitem); } break; default: break; } return FALSE; } static void mark_pieces() { guint i, j; guint x; Piece *piece = NULL; guint nbgood = 0; guint nbmisplaced = 0; guint solution_tmp[MAX_PIECES]; for(i=0; iselecteditem == solution_tmp[i-1]) { if(gcomprisBoard->levelgood); nbgood++; solution_tmp[i-1] = G_MAXINT; } else { gamewon = FALSE; } piece->completed = TRUE; } /* Mark misplaced */ for(i=1; i<=number_of_piece; i++) { gboolean done; piece = g_list_nth_data(listPieces, i); /* Search if this color is elsewhere */ j = 1; done = FALSE; do { if(piece->selecteditem != solution[i-1] && piece->selecteditem == solution_tmp[j-1]) { nbmisplaced++; solution_tmp[j-1] = G_MAXINT; if(gcomprisBoard->levelmisplaced); done = TRUE; } } while (!done && j++!=number_of_piece); } /* Display the matermind information to the user */ // x = (BOARDWIDTH + (number_of_piece+2)*(PIECE_WIDTH+PIECE_GAP))/2; x = PLAYING_HELP_X; for(i=0; inext) g_free(l->data); g_list_free(listPieces); superbrain_create_item(boardRootItem); }