Index: apps/plugins/CATEGORIES =================================================================== --- apps/plugins/CATEGORIES (revision 19176) +++ apps/plugins/CATEGORIES (working copy) @@ -64,6 +64,7 @@ rockblox1d,games rockbox_flash,viewers rockboy,viewers +rockgo,games rocklife,games rockpaint,apps search,viewers Index: apps/plugins/rockgo.c =================================================================== --- apps/plugins/rockgo.c (revision 0) +++ apps/plugins/rockgo.c (revision 0) @@ -0,0 +1,898 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * + * Copyright (C) 2007-2008 Alex A. dos Santos + * + * All files in this archive are subject to the GNU General Public License. + * See the file COPYING in the source tree root for full license agreement. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +/***************************************************************************** +RockGo by Alex A. dos Santos + +*****************************************************************************/ + +#include "plugin.h" +#include "lib/playback_control.h" +#include "lib/configfile.h" + +#ifdef HAVE_LCD_BITMAP + +PLUGIN_HEADER + +#define MAX_BOARD 19 + +#define CFGFILE_VERSION 0 +#define CONFIG_FILENAME "rockgo.cfg" +#define SAVE_FILENAME PLUGIN_GAMES_DIR "/rockgo.save" + +struct options +{ + int jump_stones; +}; + +enum board_rules +{ + RULES_PENTE, + RULES_GO +}; + +struct point +{ + int x; + int y; +}; + +struct options rockgo_disk = {1}; +struct options rockgo_options; + +static struct configdata config[] = +{ + { TYPE_INT, 0, 1, &rockgo_disk.jump_stones, "jump_stones", NULL, NULL } +}; + +struct board_settings +{ + int board_size; + int square_size; + int stone_size; + int board_center_w; + int board_center_h; + int cursor_x; + int cursor_y; + bool player_black; + int black_captured; + int white_captured; + enum board_rules rules; + /* 0 == not used, 1 == black, 2 == white */ + int stones[MAX_BOARD][MAX_BOARD]; +}; + +static const struct plugin_api* rb; + +#if (CONFIG_KEYPAD == IPOD_4G_PAD) || (CONFIG_KEYPAD == IPOD_3G_PAD) || \ + (CONFIG_KEYPAD == IPOD_1G2G_PAD) +# define GO_HAS_SCROLLWHEEL +# define BT_QUIT (BUTTON_SELECT | BUTTON_MENU) +# define BT_UP (BUTTON_MENU | BUTTON_REL) +# define BT_DOWN (BUTTON_PLAY | BUTTON_REL) +# define BT_LEFT (BUTTON_LEFT | BUTTON_REL) +# define BT_RIGHT (BUTTON_RIGHT | BUTTON_REL) +# define BT_SELECT (BUTTON_SELECT | BUTTON_REL) +# define BT_MOVE_LEFT BUTTON_SCROLL_BACK +# define BT_MOVE_RIGHT BUTTON_SCROLL_FWD + +#elif CONFIG_KEYPAD == RECORDER_PAD +# define BT_QUIT BUTTON_OFF +# define BT_UP BUTTON_UP +# define BT_DOWN BUTTON_DOWN +# define BT_LEFT BUTTON_LEFT +# define BT_RIGHT BUTTON_RIGHT +# define BT_SELECT BUTTON_ON + +#elif CONFIG_KEYPAD == ARCHOS_AV300_PAD +# define BT_QUIT BUTTON_OFF +# define BT_UP BUTTON_UP +# define BT_DOWN BUTTON_DOWN +# define BT_LEFT BUTTON_LEFT +# define BT_RIGHT BUTTON_RIGHT +# define BT_SELECT BUTTON_ON + +#elif CONFIG_KEYPAD == ONDIO_PAD +# define BT_QUIT BUTTON_OFF +# define BT_UP (BUTTON_UP | BUTTON_REL) +# define BT_DOWN (BUTTON_DOWN | BUTTON_REL) +# define BT_LEFT (BUTTON_LEFT | BUTTON_REL) +# define BT_RIGHT (BUTTON_RIGHT | BUTTON_REL) +# define BT_SELECT (BUTTON_MENU | BUTTON_REL) + +#elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \ + (CONFIG_KEYPAD == IRIVER_H300_PAD) +# define BT_QUIT BUTTON_OFF +# define BT_UP (BUTTON_UP | BUTTON_REL) +# define BT_DOWN (BUTTON_DOWN | BUTTON_REL) +# define BT_LEFT (BUTTON_LEFT | BUTTON_REL) +# define BT_RIGHT (BUTTON_RIGHT | BUTTON_REL) +# define BT_SELECT (BUTTON_SELECT | BUTTON_REL) + +#elif (CONFIG_KEYPAD == IAUDIO_X5M5_PAD) +# define BT_QUIT BUTTON_POWER +# define BT_UP BUTTON_UP +# define BT_DOWN BUTTON_DOWN +# define BT_LEFT BUTTON_LEFT +# define BT_RIGHT BUTTON_RIGHT +# define BT_SELECT (BUTTON_SELECT | BUTTON_REL) + +#elif (CONFIG_KEYPAD == GIGABEAT_PAD) +# define BT_QUIT BUTTON_POWER +# define BT_UP BUTTON_UP +# define BT_DOWN BUTTON_DOWN +# define BT_LEFT BUTTON_LEFT +# define BT_RIGHT BUTTON_RIGHT +# define BT_SELECT (BUTTON_SELECT | BUTTON_REL) + +#elif (CONFIG_KEYPAD == SANSA_E200_PAD) +# define NOT_WIDE_SCREEN +# define BT_QUIT BUTTON_POWER +# define BT_UP BUTTON_UP +# define BT_DOWN BUTTON_DOWN +# define BT_LEFT BUTTON_LEFT +# define BT_RIGHT BUTTON_RIGHT +# define BT_SELECT BUTTON_SELECT + +#elif (CONFIG_KEYPAD == IRIVER_H10_PAD) +# define GO_HAS_SCROLLWHEEL +# define BT_QUIT BUTTON_POWER +# define BT_UP BUTTON_SCROLL_UP +# define BT_DOWN BUTTON_SCROLL_DOWN +# define BT_LEFT (BUTTON_LEFT | BUTTON_REL) +# define BT_RIGHT (BUTTON_RIGHT | BUTTON_REL) +# define BT_SELECT BUTTON_PLAY +# define BT_MOVE_LEFT BUTTON_LEFT +# define BT_MOVE_RIGHT BUTTON_RIGHT + +#else +# error "Unknown keypad" +#endif + +#if LCD_WIDTH >= 320 +# define MARGIN 4 +# define STATUS_WHITE "White: %d" +# define STATUS_BLACK "Black: %d" +# define STATUS_FULL_DESCRIPTION +# define STATUS_TURN "%s's turn" +#elif LCD_WIDTH >= 220 +# define MARGIN 3 +# define STATUS_WHITE "W:%d" +# define STATUS_BLACK "B:%d" +# define STATUS_TURN "%s" +#elif LCD_WIDTH >= 160 +/* SANSA... lcd is big enough, but + it is taller than wider... */ +# ifdef NOT_WIDE_SCREEN +# define MARGIN 4 +# define STATUS_WHITE "White: %d" +# define STATUS_BLACK "Black: %d" +# define STATUS_FULL_DESCRIPTION +# define STATUS_TURN "%s's turn" +# else +# define MARGIN 2 +# define STATUS_WHITE "W:%d" +# define STATUS_BLACK "B:%d" +# define STATUS_TURN "%s" +# endif +#elif LCD_WIDTH >= 128 +# define MARGIN 1 +# define STATUS_WHITE "W:%d" +# define STATUS_BLACK "B:%d" +# define STATUS_TURN "%s" +#else +# define MARGIN 0 +# define STATUS_WHITE "W:%d" +# define STATUS_BLACK "B:%d" +# define STATUS_TURN "%s" +#endif + + +static void init_board(struct board_settings* cb) +{ + cb->board_size = 0; + cb->square_size = 0; + cb->board_center_h = 0; + cb->board_center_w = 0; + cb->player_black = true; + cb->white_captured = 0; + cb->black_captured = 0; + cb->rules = RULES_GO; + cb->cursor_x = 0; + cb->cursor_y = 0; + int x,y; + for(x = 0;x < cb->board_size; x++) + for(y = 0;y < cb->board_size; y++) + cb->stones[x][y] = 0; +} + +/* x and y must be < board_size... this function will find the right X,Y in the screen... + x,y must be the position in the board (0,0), (1,5), etc... */ +static void draw_stone(struct board_settings* cb, int x1, int y1, bool black) +{ + int x = x1 * cb->square_size + MARGIN + cb->board_center_w; + int y = y1 * cb->square_size + MARGIN + cb->board_center_h; + if (black) + rb->lcd_set_foreground(LCD_BLACK); + else + rb->lcd_set_foreground(LCD_WHITE); + if (cb->stone_size == 4) + { + int diff = 2; /* to center... */ + rb->lcd_fillrect(x-diff,y-diff,cb->stone_size,cb->stone_size); + rb->lcd_fillrect(x+1-diff,y-1-diff,cb->stone_size - 2,cb->stone_size + 2); + rb->lcd_fillrect(x-1-diff,y+1-diff,cb->stone_size + 2,cb->stone_size - 2); + } + if (cb->stone_size == 7) + { + int diff = 3; /* to center... */ + rb->lcd_fillrect(x-diff,y-diff,cb->stone_size,cb->stone_size); + rb->lcd_fillrect(x+1-diff,y-1-diff,cb->stone_size - 2,cb->stone_size + 2); + rb->lcd_fillrect(x-1-diff,y+1-diff,cb->stone_size + 2,cb->stone_size - 2); + } +}; + +static void draw_board(struct board_settings* cb) +{ +#ifdef HAVE_LCD_COLOR + rb->lcd_set_background(LCD_RGBPACK(255,255,150)); /* 255,255,0|150 yellow LCD_DEFAULT_BG); LCD_RGBPACK(0,0,255)) blue */ + rb->lcd_set_foreground(LCD_RGBPACK(255,255,150)); +#else + rb->lcd_set_background(LCD_WHITE); + rb->lcd_set_foreground(LCD_WHITE); +#endif + rb->lcd_set_backdrop(NULL); + rb->lcd_fillrect(0,0,LCD_WIDTH,LCD_HEIGHT); + rb->lcd_set_foreground(LCD_BLACK); + /* cb->lcd_clear_display(); */ + int x = 0; + // + // draw board + while (x < cb->board_size) + { + rb->lcd_hline(MARGIN + cb->board_center_w, (cb->board_size-1)*cb->square_size + MARGIN + cb->board_center_w, x*cb->square_size + MARGIN + cb->board_center_h); + rb->lcd_vline(x*cb->square_size + MARGIN + cb->board_center_w, MARGIN + cb->board_center_h, (cb->board_size-1)*cb->square_size + MARGIN + cb->board_center_h); + x++; + } + /* draw "corners" if playing GO */ + if (cb->rules == RULES_GO) + { + int original_stone_size = cb->stone_size; + cb->stone_size = 4; /* smaller... */ + if (cb->board_size == 9) + { + draw_stone(cb,2,2,true); + draw_stone(cb,2,6,true); + draw_stone(cb,6,2,true); + draw_stone(cb,6,6,true); + } + if (cb->board_size == 13) + { + draw_stone(cb,3,3,true); + draw_stone(cb,9,3,true); + draw_stone(cb,3,9,true); + draw_stone(cb,9,9,true); + } + if (cb->board_size == 19) + { + draw_stone(cb,3,3,true); + draw_stone(cb,9,3,true); + draw_stone(cb,15,3,true); + draw_stone(cb,3,9,true); + draw_stone(cb,9,9,true); + draw_stone(cb,15,9,true); + draw_stone(cb,3,15,true); + draw_stone(cb,9,15,true); + draw_stone(cb,15,15,true); + } + cb->stone_size = original_stone_size; + } + /* draw status... */ + char status[50]; + if (cb->player_black) + { + #ifdef STATUS_FULL_DESCRIPTION + rb->snprintf(status, 50, STATUS_TURN, "Black"); + #else + rb->snprintf(status, 50, STATUS_TURN, "B"); + #endif + } + else + { + #ifdef STATUS_FULL_DESCRIPTION + rb->snprintf(status, 50, STATUS_TURN, "White"); + #else + rb->snprintf(status, 50, STATUS_TURN, "W"); + #endif + } +#ifdef NOT_WIDE_SCREEN + rb->lcd_putsxy(15, (cb->board_size-1) * cb->square_size + (MARGIN * 2) + cb->board_center_h + 40, status); + rb->snprintf(status, 50, STATUS_BLACK, cb->white_captured); + rb->lcd_putsxy(15, (cb->board_size - 1) * cb->square_size + (MARGIN * 2) + cb->board_center_h + 15, status); + rb->snprintf(status, 50, STATUS_WHITE, cb->black_captured); + rb->lcd_putsxy(70, (cb->board_size - 1) * cb->square_size + (MARGIN * 2) + cb->board_center_h + 15, status); +#else + rb->lcd_putsxy((cb->board_size-1) * cb->square_size + (MARGIN * 2) + cb->board_center_w, 15, status); + rb->snprintf(status, 50, STATUS_BLACK, cb->white_captured); + rb->lcd_putsxy((cb->board_size - 1) * cb->square_size + (MARGIN * 2) + cb->board_center_w, 50, status); + rb->snprintf(status, 50, STATUS_WHITE, cb->black_captured); + rb->lcd_putsxy((cb->board_size - 1) * cb->square_size + (MARGIN * 2) + cb->board_center_w, 70, status); +#endif + /* draw stones */ + int y = 0; + for(x = 0;x < cb->board_size; x++) + for(y = 0;y < cb->board_size; y++) + if (cb->stones[x][y] != 0) + { + if (cb->stones[x][y] == 1) + draw_stone(cb,x,y,true); + else + draw_stone(cb,x,y,false); + } + rb->lcd_update(); +}; + +static void draw_cursor(struct board_settings* cb) +{ + draw_stone(cb, cb->cursor_x, cb->cursor_y, cb->player_black); + rb->lcd_update(); +}; + +static void go_move(struct board_settings* cb, int x, int y) +{ + if (x == 1) + { + cb->cursor_x += 1; + if (cb->cursor_x > cb->board_size - 1) + { + cb->cursor_x = 0; + cb->cursor_y += 1; + } + } + if (x == -1) + { + cb->cursor_x -= 1; + if (cb->cursor_x < 0) + { + cb->cursor_x = cb->board_size - 1; + cb->cursor_y -= 1; + } + } + if (y == 1) + { + cb->cursor_y += 1; + } + if (y == -1) + { + cb->cursor_y -= 1; + } + if (cb->cursor_y > cb->board_size - 1) + cb->cursor_y = 0; + if (cb->cursor_y < 0) + cb->cursor_y = cb->board_size - 1; + /* jump stones... */ + if (rockgo_options.jump_stones == 1 && cb->stones[cb->cursor_x][cb->cursor_y] != 0) + go_move(cb,x,y); +}; + +static bool test_pente(struct board_settings* cb, int x, int y, int player) +{ + /* if it is testing out of the board return false... */ + bool ok = false; + if (x < MAX_BOARD && y < MAX_BOARD && x >= 0 && y >= 0) + if (cb->stones[x][y] == player) + ok = true; + return ok; +}; + +static bool was_tested(struct point* tested, int x, int y) +{ + int i = 0; + bool done = false; + while (tested[i].x != -1 && tested[i].y != -1) + { + if (tested[i].x == x && tested[i].y == y) + { + done = true; + break; + } + i++; + } + if (!done) + { + tested[i].x = x; + tested[i].y = y; + } + return done; +}; + +/* return true if the stone is alive (has liberties) */ +static bool test_go(struct board_settings* cb, struct point* tested, int x, int y, int player) +{ + bool ok = false; + if (x < MAX_BOARD && y < MAX_BOARD && x >= 0 && y >= 0) + { + if (cb->stones[x][y] == 0) /* liberty */ + ok = true; + if (!was_tested(tested, x, y)) + { + /* the stone is part of the group... */ + if (cb->stones[x][y] == player) + { + ok = true; + if (!test_go(cb, tested, x, y+1, player)) + if (!test_go(cb, tested, x, y-1, player)) + if (!test_go(cb, tested, x+1, y, player)) + if (!test_go(cb, tested, x-1, y, player)) + ok = false; + } + } + } + return ok; +}; + +/* if the group is dead, it will be removed. */ +static void group_go(struct board_settings* cb, int x, int y, int player) +{ + struct point tested[MAX_BOARD * MAX_BOARD]; + int i = 0; + for (i = 0; i < MAX_BOARD * MAX_BOARD; i++) + { + tested[i].x = -1; + tested[i].y = -1; + } + /* true the group is alive... */ + if (!test_go(cb, tested, x, y, player)) + { + /* group is dead.. remove the stones! */ + i = 0; + while(tested[i].x != -1 && tested[i].y != -1) + { + /* remove the stones that belong to that group (player color..) */ + if (cb->stones[tested[i].x][tested[i].y] == player) + cb->stones[tested[i].x][tested[i].y] = 0; + i++; + } + } +}; + +static void remove_stones(struct board_settings* cb) +{ + /* cb has the current cursor_x, cursor_y (last move) + and the player_black has the current player when you + call this function... see go_place_stone() + + remove stones based in the game rules: go / pente */ + int other_player, me; + int *count; + if (cb->player_black) + { + me = 1; + other_player = 2; + count = &cb->white_captured; + } + else + { + me = 2; + other_player = 1; + count = &cb->black_captured; + } + int x = cb->cursor_x; + int y = cb->cursor_y; + if (cb->rules == RULES_PENTE) + { + /* vertical down */ + if (test_pente(cb, x, y+1, other_player) && + test_pente(cb, x, y+2, other_player) && + test_pente(cb, x, y+3, me)) + { + cb->stones[x][y+1] = 0; + cb->stones[x][y+2] = 0; + *count = *count + 1; + } + /* veritcal up */ + if (test_pente(cb, x, y-1, other_player) && + test_pente(cb, x, y-2, other_player) && + test_pente(cb, x, y-3, me)) + { + cb->stones[x][y-1] = 0; + cb->stones[x][y-2] = 0; + *count = *count + 1; + } + /* horizontal left */ + if (test_pente(cb, x-1, y, other_player) && + test_pente(cb, x-2, y, other_player) && + test_pente(cb, x-3, y, me)) + { + cb->stones[x-1][y] = 0; + cb->stones[x-2][y] = 0; + *count = *count + 1; + } + /* horizontal right */ + if (test_pente(cb, x+1, y, other_player) && + test_pente(cb, x+2, y, other_player) && + test_pente(cb, x+3, y, me)) + { + cb->stones[x+1][y] = 0; + cb->stones[x+2][y] = 0; + *count = *count + 1; + } + /* diagonal down right */ + if (test_pente(cb, x+1, y+1, other_player) && + test_pente(cb, x+2, y+2, other_player) && + test_pente(cb, x+3, y+3, me)) + { + cb->stones[x+1][y+1] = 0; + cb->stones[x+2][y+2] = 0; + *count = *count + 1; + } + /* diagonal up right */ + if (test_pente(cb, x+1, y-1, other_player) && + test_pente(cb, x+2, y-2, other_player) && + test_pente(cb, x+3, y-3, me)) + { + cb->stones[x+1][y-1] = 0; + cb->stones[x+2][y-2] = 0; + *count = *count + 1; + } + /* diagonal up left */ + if (test_pente(cb, x-1, y-1, other_player) && + test_pente(cb, x-2, y-2, other_player) && + test_pente(cb, x-3, y-3, me)) + { + cb->stones[x-1][y-1] = 0; + cb->stones[x-2][y-2] = 0; + *count = *count + 1; + } + /* diagonal down left */ + if (test_pente(cb, x-1, y+1, other_player) && + test_pente(cb, x-2, y+2, other_player) && + test_pente(cb, x-3, y+3, me)) + { + cb->stones[x-1][y+1] = 0; + cb->stones[x-2][y+2] = 0; + *count = *count + 1; + } + } + if (cb->rules == RULES_GO) + { + if (test_pente(cb, x, y+1, other_player)) + group_go(cb, x, y+1, other_player); + if (test_pente(cb, x, y-1, other_player)) + group_go(cb, x, y-1, other_player); + if (test_pente(cb, x+1, y, other_player)) + group_go(cb, x+1, y, other_player); + if (test_pente(cb, x-1, y, other_player)) + group_go(cb, x-1, y, other_player); + /* test if the stone that was played is dead. */ + group_go(cb, x, y, me); + } +}; + +static void go_place_stone(struct board_settings* cb) +{ + if (cb->stones[cb->cursor_x][cb->cursor_y] != 0) + rb->splash(HZ*2, "Illegal move!"); + else + { + if (cb->player_black) + cb->stones[cb->cursor_x][cb->cursor_y] = 1; + else + cb->stones[cb->cursor_x][cb->cursor_y] = 2; + /* remove stones if there is something to be removed... */ + remove_stones(cb); + cb->player_black = !cb->player_black; + /* move to the next free spot. */ + go_move(cb,1,0); + } +}; + +static void new_game(struct board_settings* cb) +{ + /* set variables depending on board_size */ +#ifdef NOT_WIDE_SCREEN + cb->square_size = (LCD_WIDTH - (MARGIN * 2)) / cb->board_size; + cb->board_center_h = (LCD_WIDTH - ((cb->board_size-1) * cb->square_size + MARGIN)) / 2; + cb->board_center_w = (LCD_WIDTH - ((cb->board_size-1)* cb->square_size + MARGIN)) / 2; +#else + cb->square_size = (LCD_HEIGHT - (MARGIN * 2)) / cb->board_size; + cb->board_center_h = (LCD_HEIGHT - ((cb->board_size-1) * cb->square_size + MARGIN)) / 2; + /* instead of having the board in the center, + i moved it to the left, so I can have the "status" in the right side. */ + cb->board_center_w = 0; +#endif + cb->player_black = true; + cb->white_captured = 0; + cb->black_captured = 0; + cb->cursor_x = 0; + cb->cursor_y = 0; + int x,y; + for(x = 0;x < cb->board_size; x++) + for(y = 0;y < cb->board_size; y++) + cb->stones[x][y] = 0; +}; + +static bool load_game(struct board_settings* cb) +{ + init_board(cb); + bool loaded = false; + + int fd = rb->open(SAVE_FILENAME, O_RDONLY); + if (fd < 0) + return loaded; + + while(true) + { + if(rb->read(fd, &cb->board_size, sizeof(cb->board_size)) <= 0) + break; + if(rb->read(fd, &cb->square_size, sizeof(cb->square_size)) <= 0) + break; + if(rb->read(fd, &cb->stone_size, sizeof(cb->stone_size)) <= 0) + break; + if(rb->read(fd, &cb->board_center_h, sizeof(cb->board_center_h)) <= 0) + break; + if(rb->read(fd, &cb->board_center_w, sizeof(cb->board_center_w)) <= 0) + break; + if(rb->read(fd, &cb->rules, sizeof(cb->rules)) <= 0) + break; + if(rb->read(fd, &cb->player_black, sizeof(cb->player_black)) <= 0) + break; + if(rb->read(fd, &cb->black_captured, sizeof(cb->black_captured)) <= 0) + break; + if(rb->read(fd, &cb->white_captured, sizeof(cb->white_captured)) <= 0) + break; + if(rb->read(fd, &cb->cursor_x, sizeof(cb->cursor_x)) <= 0) + break; + if(rb->read(fd, &cb->cursor_y, sizeof(cb->cursor_y)) <= 0) + break; + if(rb->read(fd, &cb->stones, sizeof(cb->stones)) <= 0) + break; + loaded = true; + break; + } + rb->close(fd); + return loaded; +}; + +static void save_game(struct board_settings* cb) +{ + int fd = rb->open(SAVE_FILENAME, O_WRONLY|O_CREAT); + rb->write(fd, &cb->board_size, sizeof(cb->board_size)); + rb->write(fd, &cb->square_size, sizeof(cb->square_size)); + rb->write(fd, &cb->stone_size, sizeof(cb->stone_size)); + rb->write(fd, &cb->board_center_h, sizeof(cb->board_center_h)); + rb->write(fd, &cb->board_center_w, sizeof(cb->board_center_w)); + rb->write(fd, &cb->rules, sizeof(cb->rules)); + rb->write(fd, &cb->player_black, sizeof(cb->player_black)); + rb->write(fd, &cb->black_captured, sizeof(cb->black_captured)); + rb->write(fd, &cb->white_captured, sizeof(cb->white_captured)); + rb->write(fd, &cb->cursor_x, sizeof(cb->cursor_x)); + rb->write(fd, &cb->cursor_y, sizeof(cb->cursor_y)); + rb->write(fd, &cb->stones, sizeof(cb->stones)); + rb->close(fd); + rb->splash(HZ*2, "Game saved!"); +}; + +static bool menu_new_game(struct board_settings* cb) +{ + int selection = 0; + MENUITEM_STRINGLIST(menu_game, "RockGo - New Game", NULL, "Go 9x9", "Go 13x13", "Go 19x19", "Pente", "Return", ); + bool stop = true; + switch (rb->do_menu(&menu_game, &selection, NULL, false)) + { + case 0: + cb->board_size = 9; + cb->stone_size = 7; + cb->rules = RULES_GO; + new_game(cb); + break; + case 1: + cb->board_size = 13; + cb->stone_size = 7; + cb->rules = RULES_GO; + new_game(cb); + break; + case 2: + cb->board_size = 19; + cb->stone_size = 7; + cb->rules = RULES_GO; + new_game(cb); + break; + case 3: + cb->board_size = 19; + cb->stone_size = 7; + cb->rules = RULES_PENTE; + new_game(cb); + break; + default: /* return or nothing... */ + stop = false; + break; + } + return stop; +}; + +static void menu_options() +{ + /*if (rockgo_options.jump_stones) + MENUITEM_STRINGLIST(menu_options2, "RockGo - Options", NULL, "Disable Auto Jump Stones", "Return" ); + else + MENUITEM_STRINGLIST(menu_options2, "RockGo - Options", NULL, "Enable Auto Jump Stones", "Return" ); + */ + int selection = 0; + MENUITEM_STRINGLIST(menu_options2, "RockGo - Options", NULL, "Enable/Disable Auto Jump Stones", "Return" ); + switch (rb->do_menu(&menu_options2,&selection, NULL, false)) + { + case 0: + if (rockgo_options.jump_stones == 0) + rockgo_options.jump_stones = 1; + else + rockgo_options.jump_stones = 0; + break; + default: /* return... */ + break; + } +}; + +static bool show_menu(struct board_settings* cb) +{ +#ifdef HAVE_LCD_COLOR + rb->lcd_set_foreground (rb->global_settings->fg_color); + rb->lcd_set_background (rb->global_settings->bg_color); +#endif + /* rb->lcd_set_foreground(LCD_BLACK); */ + bool stop_game = false; + MENUITEM_STRINGLIST(menu, "RockGo", NULL, "New Game", "Playback Control", "Resume", "Load Last Game", "Save Current Game", "Options", "About", "Quit",); + bool stop = false; + int selection = 0; + while (!stop) + { + switch (rb->do_menu(&menu, &selection, NULL, false)) + { + case 0: /* New Game */ + stop = menu_new_game(cb); + break; + case 1: /* Playback Control */ + playback_control(rb, NULL); + stop = false; + break; + case 2: /* Resume */ + if (cb->board_size == 0) + rb->splash(HZ*2,"Nothing to resume"); + else + stop = true; + break; + case 3: /* Load game */ + if (load_game(cb)) + { + stop = true; + rb->splash(HZ*2,"Last game loaded"); + } + else + rb->splash(HZ*2,"Error reading file"); + break; + case 4: /* Save game */ + if (cb->board_size == 0) + rb->splash(HZ*2,"Nothing to save"); + else + save_game(cb); + break; + case 5: /* Options */ + menu_options(); + break; + case 6: /* About */ + rb->splash(HZ*2,"RockGo Version 0.2"); + rb->lcd_update(); + rb->splash(HZ*2,"Created by Alex A. dos Santos"); + break; + case 7: /* Quit */ + stop = true; + stop_game = true; + break; + default: + break; + } + } + return stop_game; +}; + +enum plugin_status plugin_start(const struct plugin_api* api, const void* parameter) +{ + (void)parameter; + + rb = api; +#ifdef HAVE_LCD_COLOR + rb->lcd_set_foreground (rb->global_settings->fg_color); + rb->lcd_set_background (rb->global_settings->bg_color); +#endif + /* + rb->lcd_set_background(LCD_RGBPACK(255,255,150)); // 255,255,0|150 yellow //LCD_DEFAULT_BG); //LCD_RGBPACK(0,0,255)) blue + rb->lcd_clear_display(); + rb->lcd_set_foreground(LCD_DEFAULT_FG); + */ + configfile_init(rb); + configfile_load(CONFIG_FILENAME, config, + sizeof(config) / sizeof(config[0]), CFGFILE_VERSION); + rb->memcpy(&rockgo_options, &rockgo_disk, sizeof(rockgo_options)); + // + /* current_board */ + struct board_settings cb; + init_board(&cb); + bool stop_game; + int button = 0; + while (true) + { + stop_game = show_menu(&cb); + if (stop_game) + break; + stop_game = false; + while(!stop_game) + { + draw_board(&cb); + draw_cursor(&cb); + // + button = rb->button_get(true); + switch(button) + { + case BT_QUIT: + stop_game = true; + break; + case BT_LEFT: + go_move(&cb,-1,0); + break; + case BT_RIGHT: + go_move(&cb,1,0); + break; + case BT_UP: + go_move(&cb,0,-1); + break; + case BT_DOWN: + go_move(&cb,0,1); + break; +#ifdef GO_HAS_SCROLLWHEEL + case BT_MOVE_LEFT: + case BT_MOVE_LEFT|BUTTON_REPEAT: + go_move(&cb,-1,0); + break; + case BT_MOVE_RIGHT: + case BT_MOVE_RIGHT|BUTTON_REPEAT: + go_move(&cb,1,0); + break; +#endif + case BT_SELECT: + go_place_stone(&cb); + break; + default: + if (rb->default_event_handler(button) == SYS_USB_CONNECTED) + { + return PLUGIN_USB_CONNECTED; + } + break; + } + } + } + /* save options if something was changed... */ + if (rb->memcmp(&rockgo_options, &rockgo_disk, sizeof(rockgo_options))) + { + rb->memcpy(&rockgo_disk, &rockgo_options, sizeof(rockgo_options)); + configfile_save(CONFIG_FILENAME, config, + sizeof(config) / sizeof(config[0]), CFGFILE_VERSION); + } + return PLUGIN_OK; +}; + +#endif /* HAVE_LCD_BITMAP */ Index: apps/plugins/SOURCES =================================================================== --- apps/plugins/SOURCES (revision 19176) +++ apps/plugins/SOURCES (working copy) @@ -1,4 +1,5 @@ /* plugins common to all models */ +rockgo.c battery_bench.c chessclock.c credits.c