/*************************************************************************** * __________ __ ___. * 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 "configfile.h" 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 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 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 # define MARGIN 2 # define STATUS_WHITE "W:%d" # define STATUS_BLACK "B:%d" # define STATUS_TURN "%s" #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) { 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)); rb->lcd_set_backdrop(NULL); rb->lcd_fillrect(0,0,LCD_WIDTH,LCD_HEIGHT); rb->lcd_set_foreground(LCD_BLACK); //rb->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 } 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); // // 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 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. //board_center_w = (LCD_WIDTH - ((board_size-1)*square_size + MARGIN)) / 2; cb->board_center_w = 0; 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) { 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, NULL)) { 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() { MENUITEM_STRINGLIST(menu_options, "RockGo - Options", NULL, "Enable/Disable Auto Jump Stones", "Return" ); switch (rb->do_menu(&menu_options, NULL)) { 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) { rb->lcd_set_foreground (rb->global_settings->fg_color); rb->lcd_set_background (rb->global_settings->bg_color); //rb->lcd_set_foreground(LCD_BLACK); bool stop_game = false; MENUITEM_STRINGLIST(menu, "RockGo", NULL, "New Game", "Resume", "Load Last Game", "Save Current Game", "Options", "About", "Quit",); bool stop = false; while (!stop) { switch (rb->do_menu(&menu, NULL)) { case 0: /* New Game */ stop = menu_new_game(cb); break; case 1: /* Resume */ if (cb->board_size == 0) rb->splash(HZ*2,"Nothing to resume"); else stop = true; break; case 2: /* 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 3: /* Save game */ if (cb->board_size == 0) rb->splash(HZ*2,"Nothing to save"); else save_game(cb); break; case 4: /* Options */ menu_options(); break; case 5: /* About */ rb->splash(HZ*2,"Created by Alex A. dos Santos"); rb->lcd_update(); rb->splash(HZ*2,"RockGo Version 0.1"); break; case 6: /* Quit */ stop = true; stop_game = true; break; default: break; } } return stop_game; }; enum plugin_status plugin_start(struct plugin_api* api, void* parameter) { (void)parameter; rb = api; // rb->lcd_set_foreground (rb->global_settings->fg_color); rb->lcd_set_background (rb->global_settings->bg_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_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; };