/* gcompris - superbrain.c * * Copyright (C) 2002, 2008 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 { GooCanvasItem *rootitem; GList *listitem; guint selecteditem; GooCanvasItem *good; GooCanvasItem *misplaced; } Piece; /* The active list of pieces */ static GList * listPieces = NULL; static guint colors[] = { 0x0000FFC0, 0x00FF00C0, 0xFF0000C0, 0x00FFFFC0, 0xFF00FFC0, 0xFFFF00C0, 0x00007FC0, 0x007F00C0, 0x7F0000C0, 0x7F007FC0, }; #define MAX_COLORS 10 #define PIECE_WIDTH 9.0 #define PIECE_HEIGHT 9.0 #define PIECE_GAP 20.0 #define PIECE_GAP_GOOD 5 #define SCROLL_LIMIT 20 #define PLAYING_AREA_X 190 #define PLAYING_HELP_X (BOARDWIDTH-80) #define COLOR_GOOD 0x000000C0 #define COLOR_MISPLACED 0xFFFFFFC0 #define PIECE_DISPLAY_X 50.0 #define PIECE_DISPLAY_Y 47.0 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 GooCanvasItem *boardRootItem = NULL; static GooCanvasItem *boardLogoItem = NULL; static GooCanvasItem *superbrain_create_item(GooCanvasItem *parent); static void superbrain_destroy_all_items(void); static void superbrain_next_level(void); static gboolean item_event (GooCanvasItem *item, GooCanvasItem *target, GdkEventButton *event, Piece *piece); static void mark_pieces(void); static void listPiecesClear(); static guint number_of_color = 0; static guint number_of_piece = 0; static double current_y_position = 0; #define MAX_PIECES 10 static guint solution[MAX_PIECES]; /* After this level, we provide less feedback to the user */ #define LEVEL_MAX_FOR_HELP 4 #define Y_STEP (PIECE_HEIGHT*2+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, NULL, 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=6; /* Go to next level after this number of 'play' */ gc_bar_set(GC_BAR_LEVEL); gc_bar_location(30, -1, -1); gc_set_background(goo_canvas_get_root_item(gcomprisBoard->canvas), "superbrain/superbrain_background.svgz"); 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_ascii_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_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), NULL); boardLogoItem = goo_canvas_group_new (goo_canvas_get_root_item(gcomprisBoard->canvas), NULL); /* The OK Button */ GooCanvasItem *item = goo_canvas_svg_new (boardLogoItem, gc_skin_rsvg_get(), "svg-id", "#OK", NULL); SET_ITEM_LOCATION(item, 270, 50); g_signal_connect(item, "button_press_event", (GCallback) process_ok, NULL); gc_item_focus_init(item, NULL); /* The list of the pieces */ for(i=0; ilistitem = NULL; listPieces = g_list_append(listPieces, piece); piece->rootitem = goo_canvas_group_new (parent, NULL); // Good piece->good = goo_canvas_rect_new (piece->rootitem, x + i*(PIECE_WIDTH*2 + PIECE_GAP) - PIECE_WIDTH - PIECE_GAP_GOOD, current_y_position - PIECE_HEIGHT - PIECE_GAP_GOOD, PIECE_WIDTH*2 + PIECE_GAP_GOOD*2, PIECE_HEIGHT*2 + PIECE_GAP_GOOD*2, "fill_color_rgba", COLOR_GOOD, "stroke-color", "white", "line-width", 1.0, "tooltip", _("This item is well placed"), NULL); g_object_set (piece->good, "visibility", GOO_CANVAS_ITEM_INVISIBLE, NULL); // Misplaced piece->misplaced = goo_canvas_rect_new (piece->rootitem, x + i*(PIECE_WIDTH*2 + PIECE_GAP) - PIECE_WIDTH - PIECE_GAP_GOOD, current_y_position - PIECE_HEIGHT - PIECE_GAP_GOOD, PIECE_WIDTH*2 + PIECE_GAP_GOOD*2, PIECE_HEIGHT*2 + PIECE_GAP_GOOD*2, "fill_color_rgba", COLOR_MISPLACED, "stroke-color", "black", "line-width", 1.0, "tooltip", _("This item is misplaced"), NULL); g_object_set (piece->misplaced, "visibility", GOO_CANVAS_ITEM_INVISIBLE, NULL); for(j=0; jrootitem, x + i*(PIECE_WIDTH*2 + PIECE_GAP), current_y_position, PIECE_WIDTH, PIECE_HEIGHT, "fill_color_rgba", colors[j], "stroke-color", "white", "line-width", (double)1, NULL); gc_item_focus_init(item, NULL); g_object_set (item, "visibility", GOO_CANVAS_ITEM_INVISIBLE, NULL); piece->listitem = g_list_append(piece->listitem, item); g_signal_connect(item, "button-press-event", (GCallback) item_event, piece); } piece->selecteditem = 0; item = g_list_nth_data(piece->listitem, piece->selecteditem); g_object_set (item, "visibility", GOO_CANVAS_ITEM_VISIBLE, NULL); } 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) gcomprisBoard->level = gcomprisBoard->maxlevel; gc_sound_play_ogg ("sounds/bonus.wav", NULL); } superbrain_next_level(); } /* ==================================== */ static gboolean item_event (GooCanvasItem *item, GooCanvasItem *target, GdkEventButton *event, Piece *piece) { GooCanvasItem *newitem; guint j; if(board_paused) return FALSE; switch(event->button) { case 1: case 4: piece->selecteditem++; if(piece->selecteditem >= g_list_length(piece->listitem)) piece->selecteditem = 0; break; case 2: case 3: case 5: if(piece->selecteditem == 0) piece->selecteditem = g_list_length(piece->listitem)-1; else piece->selecteditem--; break; } for(j=0; jlistitem); j++) { g_object_set (g_list_nth_data(piece->listitem, j), "visibility", GOO_CANVAS_ITEM_INVISIBLE, NULL); } newitem = g_list_nth_data(piece->listitem, piece->selecteditem); g_object_set (newitem, "visibility", GOO_CANVAS_ITEM_VISIBLE, NULL); 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; ilistitem, piece->selecteditem); if(piece->selecteditem == solution_tmp[i]) { if(gcomprisBoard->levelgood, "visibility", GOO_CANVAS_ITEM_VISIBLE, NULL); nbgood++; solution_tmp[i] = G_MAXINT; g_object_set(item, "tooltip", _("This item is well placed"), NULL); } else { gamewon = FALSE; } } /* Mark misplaced */ for(i=0; ilistitem, piece->selecteditem); /* Search if this color is elsewhere */ j = 0; done = FALSE; do { if(piece->selecteditem != solution[i] && piece->selecteditem == solution_tmp[j]) { nbmisplaced++; solution_tmp[j] = G_MAXINT; if(gcomprisBoard->levelmisplaced, "visibility", GOO_CANVAS_ITEM_VISIBLE, NULL); g_object_set (item, "tooltip", _("This item is misplaced"), NULL); done = TRUE; } } while (!done && ++j!=number_of_piece); } /* Display the matermind information to the user */ x = PLAYING_HELP_X; for(i=0; ilistitem); j++) { GooCanvasItem *item = g_list_nth_data(piece->listitem, j); g_signal_handlers_disconnect_by_func(item, (GCallback) item_event, piece); gc_item_focus_remove(item, NULL); } g_free(piece); } g_list_free(listPieces); listPieces = NULL; }