From 619a5ca1d3dfbc86839245b9ce8977002efd187e Mon Sep 17 00:00:00 2001 From: Björn Stenberg Date: Tue, 17 Aug 2004 06:50:14 +0000 Subject: Minesweeper and Solitaire plugins by Antoine Cellerier git-svn-id: svn://svn.rockbox.org/rockbox/trunk@4997 a1c6a512-1295-4272-9138-f99709370657 --- apps/plugins/minesweeper.c | 436 +++++++++++++++++++++++ apps/plugins/solitaire.c | 867 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 1303 insertions(+) create mode 100644 apps/plugins/minesweeper.c create mode 100644 apps/plugins/solitaire.c (limited to 'apps') diff --git a/apps/plugins/minesweeper.c b/apps/plugins/minesweeper.c new file mode 100644 index 0000000000..b155c3fbad --- /dev/null +++ b/apps/plugins/minesweeper.c @@ -0,0 +1,436 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2004 dionoea (Antoine Cellerier) + * + * 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. + * + ****************************************************************************/ + +/***************************************************************************** +Mine Sweeper by dionoea + +use arrow keys to move cursor +use ON or F2 to clear a tile +use PLAY or F1 to put a flag on a tile +use F3 to see how many mines are left (supposing all your flags are correct) + +*****************************************************************************/ + +#include "plugin.h" +#include "button.h" +#include "lcd.h" + +#ifdef HAVE_LCD_BITMAP + +//what the minesweeper() function can return +#define MINESWEEPER_QUIT 2 +#define MINESWEEPER_LOSE 1 +#define MINESWEEPER_WIN 0 + + +/* here is a global api struct pointer. while not strictly necessary, + it's nice not to have to pass the api pointer in all function calls + in the plugin */ +static struct plugin_api* rb; + + +//define how numbers are displayed (that way we don't have to +//worry about fonts) +static unsigned char num[9][8] = { + /*reading the sprites: + on screen f123 + 4567 + 890a + bcde + + in binary b84f + c951 + d062 + ea73 + */ + + //0 + {0x00, //........ + 0x00, //........ + 0x00, //........ + 0x00, //........ + 0x00, //........ + 0x00, //........ + 0x00, //........ + 0x00},//........ + //1 + {0x00, //........ + 0x00, //........ + 0x00, //...OO... + 0x44, //....O... + 0x7c, //....O... + 0x40, //....O... + 0x00, //...OOO.. + 0x00},//........ + //2 + {0x00, //........ + 0x00, //........ + 0x48, //...OO... + 0x64, //..O..O.. + 0x54, //....O... + 0x48, //...O.... + 0x00, //..OOOO.. + 0x00},//........ + //3 + {0x00, //........ + 0x00, //........ + 0x44, //..OOO... + 0x54, //.....O.. + 0x54, //...OO... + 0x28, //.....O.. + 0x00, //..OOO... + 0x00},//........ + //4 + {0x00, //........ + 0x00, //........ + 0x1c, //..O..... + 0x10, //..O..... + 0x70, //..OOOO.. + 0x10, //....O... + 0x00, //....O... + 0x00},//........ + //5 + {0x00, //........ + 0x00, //........ + 0x5c, //..OOOO.. + 0x54, //..O..... + 0x54, //..OOO... + 0x24, //.....O.. + 0x00, //..OOO... + 0x00},//........ + //6 + {0x00, //........ + 0x00, //........ + 0x38, //...OOO.. + 0x54, //..O..... + 0x54, //..OOO... + 0x24, //..O..O.. + 0x00, //...OO... + 0x00},//........ + //7 + {0x00, //........ + 0x00, //........ + 0x44, //..OOOO.. + 0x24, //.....O.. + 0x14, //....O... + 0x0c, //...O.... + 0x00, //..O..... + 0x00},//........ + //8 + {0x00, //........ + 0x00, //........ + 0x28, //...OO... + 0x54, //..O..O.. + 0x54, //...OO... + 0x28, //..O..O.. + 0x00, //...OO... + 0x00},//........ +}; + +/* the tile struct +if there is a mine, mine is true +if tile is known by player, known is true +if tile has a flag, flag is true +neighbors is the total number of mines arround tile +*/ +typedef struct tile { + unsigned char mine : 1; + unsigned char known : 1; + unsigned char flag : 1; + unsigned char neighbors : 4; +} tile; + +//the height and width of the field +//could be variable if malloc worked in the API :) +const int height = LCD_HEIGHT/8; +const int width = LCD_WIDTH/8; + +//the minefield +tile minefield[LCD_HEIGHT/8][LCD_WIDTH/8]; + +//total number of mines on the game +int mine_num = 0; + +//discovers the tile when player clears one of them +//a chain reaction (of discovery) occurs if tile has no mines +//as neighbors +void discover(int, int); +void discover(int x, int y){ + + if(x<0) return; + if(y<0) return; + if(x>width-1) return; + if(y>height-1) return; + if(minefield[y][x].known) return; + + minefield[y][x].known = 1; + if(minefield[y][x].neighbors == 0){ + discover(x-1,y-1); + discover(x,y-1); + discover(x+1,y-1); + discover(x+1,y); + discover(x+1,y+1); + discover(x,y+1); + discover(x-1,y+1); + discover(x-1,y); + } + return; +} + + +//init not mine related elements of the mine field +void minesweeper_init(void){ + int i,j; + + for(i=0;irand()%100

0){ + if(j>0) minefield[i][j].neighbors += minefield[i-1][j-1].mine; + minefield[i][j].neighbors += minefield[i-1][j].mine; + if(j0) minefield[i][j].neighbors += minefield[i][j-1].mine; + if(j0) minefield[i][j].neighbors += minefield[i+1][j-1].mine; + minefield[i][j].neighbors += minefield[i+1][j].mine; + if(jlcd_clear_display(); + + rb->lcd_putsxy(1,1,"Mine Sweeper"); + + rb->snprintf(str, 20, "%d%% mines", p); + rb->lcd_putsxy(1,19,str); + rb->lcd_putsxy(1,28,"down / up"); + rb->lcd_putsxy(1,44,"ON to start"); + + rb->lcd_update(); + + + switch(rb->button_get(true)){ + case BUTTON_DOWN: + case BUTTON_LEFT: + p = (p + 98)%100; + break; + + case BUTTON_UP: + case BUTTON_RIGHT: + p = (p + 2)%100; + break; + + case BUTTON_ON://start playing + i = 1; + break; + + case BUTTON_OFF://quit program + return MINESWEEPER_QUIT; + } + if(i==1) break; + } + + + /******************** + * init * + ********************/ + + minesweeper_init(); + + /********************** + * play * + **********************/ + + while(true){ + + //clear the screen buffer + rb->lcd_clear_display(); + + //display the mine field + for(i=0;ilcd_drawrect(j*8,i*8,8,8); + if(minefield[i][j].known){ + if(minefield[i][j].mine){ + rb->lcd_putsxy(j*8+1,i*8+1,"b"); + } else if(minefield[i][j].neighbors){ + rb->lcd_bitmap(num[minefield[i][j].neighbors],j*8,i*8,8,8,false); + } + } else if(minefield[i][j].flag) { + rb->lcd_drawline(j*8+2,i*8+2,j*8+5,i*8+5); + rb->lcd_drawline(j*8+2,i*8+5,j*8+5,i*8+2); + } else { + rb->lcd_fillrect(j*8+2,i*8+2,4,4); + } + } + } + + //display the cursor + rb->lcd_invertrect(x*8,y*8,8,8); + + //update the screen + rb->lcd_update(); + + switch(rb->button_get(true)){ + //quit minesweeper (you really shouldn't use this button ...) + case BUTTON_OFF: + return MINESWEEPER_QUIT; + + //move cursor left + case BUTTON_LEFT: + x = (x + width - 1)%width; + break; + + //move cursor right + case BUTTON_RIGHT: + x = (x + 1)%width; + break; + + //move cursor down + case BUTTON_DOWN: + y = (y + 1)%height; + break; + + //move cursor up + case BUTTON_UP: + y = (y + height - 1)%height; + break; + + //discover a tile (and it's neighbors if .neighbors == 0) + case BUTTON_ON: + case BUTTON_F2: + if(minefield[y][x].flag) break; + //we put the mines on the first "click" so that you don't + //lose on the first "click" + if(tiles_left == width*height) minesweeper_putmines(p,x,y); + discover(x,y); + if(minefield[y][x].mine){ + return MINESWEEPER_LOSE; + } + tiles_left = 0; + for(i=0;isplash(HZ*2, true, "You found %d mines out of %d", tiles_left, mine_num); + break; + } + } + +} + +//plugin entry point +enum plugin_status plugin_start(struct plugin_api* api, void* parameter) +{ + //plugin init + TEST_PLUGIN_API(api); + (void)parameter; + rb = api; + //end of plugin init + + switch(minesweeper()){ + case MINESWEEPER_WIN: + rb->splash(HZ*2, true, "You Win :)"); + break; + + case MINESWEEPER_LOSE: + rb->splash(HZ*2, true, "You Lost :("); + break; + + default: + break; + } + + return PLUGIN_OK; +} + +#endif diff --git a/apps/plugins/solitaire.c b/apps/plugins/solitaire.c new file mode 100644 index 0000000000..28334437c7 --- /dev/null +++ b/apps/plugins/solitaire.c @@ -0,0 +1,867 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2004 dionoea (Antoine Cellerier) + * + * 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. + * + ****************************************************************************/ + +/***************************************************************************** +Solitaire by dionoea + +use arrows to move the cursor +use ON to select cards in the columns, move cards inside the columns, + reveal hidden cards, ... +use PLAY to move a card from the remains' stack to the top of the cursor +use F1 to put card under cursor on one of the 4 final color stacks +use F2 to un-select card if a card was selected, else draw 3 new cards + out of the remains' stack +use F3 to put card on top of the remains' stack on one of the 4 final color + stacks + +*****************************************************************************/ + +#include "plugin.h" +#include "button.h" +#include "lcd.h" + +#ifdef HAVE_LCD_BITMAP + +/* here is a global api struct pointer. while not strictly necessary, + it's nice not to have to pass the api pointer in all function calls + in the plugin */ +static struct plugin_api* rb; + +#define min(a,b) (asplash(HZ*1, true, # key " : " HELP_BUTTON_ ## key); \ + break; + +#define HELP_BUTTON_UP "Move the cursor up in the column." +#define HELP_BUTTON_DOWN "Move the cursor down in the column." +#define HELP_BUTTON_LEFT "Move the cursor to the previous column." +#define HELP_BUTTON_RIGHT "Move the cursor to the next column." +#define HELP_BUTTON_F1 "Put the card under the cursor on one of the 4 final color stacks." +#define HELP_BUTTON_F2 "Un-select a card if it was selected. Else, draw 3 new cards out of the remains' stack." +#define HELP_BUTTON_F3 "Put the card on top of the remains' stack on one of the 4 final color stacks." +#define HELP_BUTTON_PLAY "Put the card on top of the remains' stack on top of the cursor." +#define HELP_BUTTON_ON "Select cards in the columns, Move cards inside the columns, reveal hidden cards ..." + +static unsigned char colors[4][8] = { +//Spades +{0x00, //........ + 0x18, //...O.... + 0x1c, //..OOO... + 0x3e, //.OOOOO.. + 0x1c, //.OOOOO.. + 0x18, //...O.... + 0x00, //........ + 0x00},//........ +//Hearts +{0x00, //........ + 0x0c, //..O.O... + 0x1e, //.OOOOO.. + 0x3c, //.OOOOO.. + 0x1e, //..OOO... + 0x0c, //...O.... + 0x00, //........ + 0x00},//........ +//Clubs +{0x00, //........ + 0x18, //..OOO... + 0x0a, //...O.... + 0x3e, //.OOOOO.. + 0x0a, //.O.O.O.. + 0x18, //...O.... + 0x00, //........ + 0x00},//........ +//Diamonds +{0x00, //........ + 0x08, //...O.... + 0x1c, //..OOO... + 0x3e, //.OOOOO.. + 0x1c, //..OOO... + 0x08, //...O.... + 0x00, //........ + 0x00} //........ +}; + +static unsigned char numbers[13][8] = { +//Ace +{0x00, //........ + 0x38, //...O.... + 0x14, //..O.O... + 0x12, //.O...O.. + 0x14, //.OOOOO.. + 0x38, //.O...O.. + 0x00, //........ + 0x00},//........ +//2 +{0x00, //........ + 0x24, //..OOO... + 0x32, //.O...O.. + 0x32, //....O... + 0x2a, //..OO.... + 0x24, //.OOOOO.. + 0x00, //........ + 0x00},//........ +//3 +{0x00, //........ + 0x22, //.OOOO... + 0x2a, //.....O.. + 0x2a, //..OOO... + 0x2a, //.....O.. + 0x14, //.OOOO... + 0x00, //........ + 0x00},//........ +//4 +{0x00, //........ + 0x10, //....O... + 0x18, //...O.... + 0x34, //..O..... + 0x12, //.OOOOO.. + 0x10, //...O.... + 0x00, //........ + 0x00},//........ +//5 +{0x00, //........ + 0x2e, //.OOOOO.. + 0x2a, //.O...... + 0x2a, //.OOOO... + 0x2a, //.....O.. + 0x12, //.OOOO... + 0x00, //........ + 0x00},//........ +//6 +{0x00, //........ + 0x1c, //..OOO... + 0x2a, //.O...... + 0x2a, //.OOOO... + 0x2a, //.O...O.. + 0x10, //..OOO... + 0x00, //........ + 0x00},//........ +//7 +{0x00, //........ + 0x22, //.OOOOO.. + 0x12, //....O... + 0x0a, //...O.... + 0x06, //..O..... + 0x02, //.O...... + 0x00, //........ + 0x00},//........ +//8 +{0x00, //........ + 0x14, //..OOO... + 0x2a, //.O...O.. + 0x2a, //..OOO... + 0x2a, //.O...O.. + 0x14, //..OOO... + 0x00, //........ + 0x00},//........ +//9 +{0x00, //........ + 0x04, //..OOO... + 0x2a, //.O...O.. + 0x2a, //..OOOO.. + 0x2a, //.....O.. + 0x1c, //..OOO... + 0x00, //........ + 0x00},//........ +//10 +{0x00, //........ + 0x3e, //.O..O... + 0x00, //.O.O.O.. + 0x1c, //.O.O.O.. + 0x22, //.O.O.O.. + 0x1c, //.O..O... + 0x00, //........ + 0x00},//........ +//Jack +{0x00, //........ + 0x12, //.OOOOO.. + 0x22, //...O.... + 0x1e, //...O.... + 0x02, //.O.O.... + 0x02, //..O..... + 0x00, //........ + 0x00},//........ +//Queen +{0x00, //........ + 0x1c, //..OOO... + 0x22, //.O...O.. + 0x32, //.O...O.. + 0x22, //.O.O.O.. + 0x1c, //..OOO... + 0x00, //........ + 0x00},//........ +//King +{0x00, //........ + 0x3e, //.O...O.. + 0x08, //.O..O... + 0x08, //.OOO.... + 0x14, //.O..O... + 0x22, //.O...O.. + 0x00, //........ + 0x00} //........ +}; + +#define NOT_A_CARD 255 + +//number of cards per color +#define CARDS_PER_COLOR 13 + +//number of colors +#define COLORS 4 + +//number of columns +#define COL_NUM 7 + +//number of cards that are drawn on the remains' stack (by pressing F2) +#define CARDS_PER_DRAW 3 + +//size of a card on the screen +#define CARD_WIDTH 14 +#define CARD_HEIGHT 10 + +typedef struct card { + unsigned char color : 2; + unsigned char num : 4; + unsigned char known : 1; + unsigned char used : 1;//this is what is used when dealing cards + unsigned char next; +} card; + +unsigned char next_random_card(card *deck){ + unsigned char i,r; + + r = rb->rand()%(COLORS * CARDS_PER_COLOR)+1; + i = 0; + + while(r>0){ + i = (i + 1)%(COLORS * CARDS_PER_COLOR); + if(!deck[i].used) r--; + } + + deck[i].used = 1; + + return i; +} + +//help for the not so intuitive interface +void solitaire_help(void){ + + rb->lcd_clear_display(); + + rb->lcd_putsxy(0, 0, "Press a key to see"); + rb->lcd_putsxy(0, 7, "it's role."); + rb->lcd_putsxy(0, 21, "Press OFF to"); + rb->lcd_putsxy(0, 28, "return to menu"); + + rb->lcd_update(); + + while(1){ + + switch(rb->button_get(true)){ + HELP_CASE( UP ); + HELP_CASE( DOWN ); + HELP_CASE( LEFT ); + HELP_CASE( RIGHT ); + HELP_CASE( F1 ); + HELP_CASE( F2 ); + HELP_CASE( F3 ); + HELP_CASE( PLAY ); + HELP_CASE( ON ); + + case BUTTON_OFF: + return; + } + } +} + +//menu return codes +#define MENU_RESUME 0 +#define MENU_RESTART 1 +#define MENU_HELP 2 +#define MENU_QUIT 3 + +//menu item number +#define MENU_LENGTH 4 + +//different menu behaviors +#define MENU_BEFOREGAME 0 +#define MENU_DURINGGAME 1 + +//the menu +//text displayed changes depending on the 'when' parameter +int solitaire_menu(unsigned char when){ + + static char menu[2][MENU_LENGTH][13] = + { { "Start Game", + "", + "Help", + "Quit" }, + { "Resume Game", + "Restart Game", + "Help", + "Quit"} }; + + int i; + int cursor=0; + + if(when!=MENU_BEFOREGAME && when!=MENU_DURINGGAME) when = MENU_DURINGGAME; + + while(1){ + + rb->lcd_clear_display(); + + rb->lcd_putsxy(20, 1, "Solitaire"); + + for(i = 0; ilcd_putsxy(1, 17+9*i, menu[when][i]); + if(cursor == i) + rb->lcd_invertrect(0,17-1+9*i, LCD_WIDTH, 9); + } + + rb->lcd_update(); + + switch(rb->button_get(true)){ + case BUTTON_UP: + cursor = (cursor + MENU_LENGTH - 1)%MENU_LENGTH; + break; + + case BUTTON_DOWN: + cursor = (cursor + 1)%MENU_LENGTH; + break; + + case BUTTON_LEFT: + return MENU_RESUME; + + case BUTTON_PLAY: + case BUTTON_RIGHT: + switch(cursor){ + case MENU_RESUME: + case MENU_RESTART: + case MENU_QUIT: + return cursor; + + case MENU_HELP: + solitaire_help(); + break; + } + + case BUTTON_F1: + case BUTTON_F2: + case BUTTON_F3: + rb->splash(HZ, true, "Solitaire for Rockbox by dionoea"); + break; + + case BUTTON_OFF: + return MENU_QUIT; + + default: + break; + } + } +} + +//player's cursor +unsigned char cur_card; +//player's cursor column num +unsigned char cur_col; + +//selected card +unsigned char sel_card; + +//the deck +card deck[COLORS * CARDS_PER_COLOR]; + +//the remaining cards +unsigned char rem; +unsigned char cur_rem; + +//the 7 game columns +unsigned char cols[COL_NUM]; + +//the 4 final color stacks +unsigned char stacks[COLORS]; + +//initialize the game +void solitaire_init(void){ + unsigned char c; + int i,j; + + //init deck + for(i=0;ilcd_clear_display(); + + //get the biggest column length so that display can be "optimized" + biggest_col_length = 0; + + for(i=0;ibiggest_col_length) biggest_col_length = j; + } + + //check if there are cards remaining in the game. + //if there aren't any, that means you won :) + if(biggest_col_length == 0 && rem == NOT_A_CARD){ + rb->splash(HZ*2, true, "You Won :)"); + return; + } + + //draw the columns + for(i=0;ilcd_clearrect(i*(LCD_WIDTH - CARD_WIDTH)/COL_NUM, j+1, CARD_WIDTH, CARD_HEIGHT-1); + //known card + if(deck[c].known){ + rb->lcd_bitmap(numbers[deck[c].num], i*(LCD_WIDTH - CARD_WIDTH)/COL_NUM+1, j, 8, 8, true); + rb->lcd_bitmap(colors[deck[c].color], i*(LCD_WIDTH - CARD_WIDTH)/COL_NUM+7, j, 8, 8, true); + } + //draw top line of the card + rb->lcd_drawline(i*(LCD_WIDTH - CARD_WIDTH)/COL_NUM+1,j,i*(LCD_WIDTH - CARD_WIDTH)/COL_NUM+CARD_WIDTH-1,j); + //selected card + if(c == sel_card && sel_card != NOT_A_CARD){ + rb->lcd_drawrect(i*(LCD_WIDTH - CARD_WIDTH)/COL_NUM+1, j+1, CARD_WIDTH-1, CARD_HEIGHT-1); + } + //cursor (or not) + if(c == cur_card){ + rb->lcd_invertrect(i*(LCD_WIDTH - CARD_WIDTH)/COL_NUM+1, j+1, CARD_WIDTH-1, CARD_HEIGHT-1); + //go to the next card + c = deck[c].next; + if(c == NOT_A_CARD) break; + j += CARD_HEIGHT - 2; + } else { + //go to the next card + c = deck[c].next; + if(c == NOT_A_CARD) break; + j += min(CARD_HEIGHT - 2, (LCD_HEIGHT - CARD_HEIGHT)/biggest_col_length); + } + } + //draw line to the left of the column + rb->lcd_drawline(i*(LCD_WIDTH - CARD_WIDTH)/COL_NUM,1,i*(LCD_WIDTH - CARD_WIDTH)/COL_NUM,j+CARD_HEIGHT-1); + //draw line to the right of the column + rb->lcd_drawline(i*(LCD_WIDTH - CARD_WIDTH)/COL_NUM+CARD_WIDTH,1,i*(LCD_WIDTH - CARD_WIDTH)/COL_NUM+CARD_WIDTH,j+CARD_HEIGHT-1); + //draw bottom of the last card + rb->lcd_drawline(i*(LCD_WIDTH - CARD_WIDTH)/COL_NUM+1,j+CARD_HEIGHT,i*(LCD_WIDTH - CARD_WIDTH)/COL_NUM+CARD_WIDTH-1,j+CARD_HEIGHT); + } + + //draw the stacks + for(i=0; ilcd_bitmap(numbers[deck[c].num], LCD_WIDTH - CARD_WIDTH+1, i*CARD_HEIGHT, 8, 8, true); + } + rb->lcd_bitmap(colors[i], LCD_WIDTH - CARD_WIDTH+7, i*CARD_HEIGHT, 8, 8, true); + rb->lcd_drawline(LCD_WIDTH - CARD_WIDTH+1,i*CARD_HEIGHT,LCD_WIDTH - 1,i*CARD_HEIGHT); + rb->lcd_drawline(LCD_WIDTH - CARD_WIDTH+1,(i+1)*CARD_HEIGHT,LCD_WIDTH - 1,(i+1)*CARD_HEIGHT); + } + + //draw the remains + rb->lcd_drawline(LCD_WIDTH - CARD_WIDTH+1,LCD_HEIGHT-CARD_HEIGHT-1,LCD_WIDTH - 1,LCD_HEIGHT-CARD_HEIGHT-1); + rb->lcd_drawline(LCD_WIDTH - CARD_WIDTH+1,LCD_HEIGHT-1,LCD_WIDTH - 1,LCD_HEIGHT-1); + if(cur_rem != NOT_A_CARD){ + rb->lcd_bitmap(numbers[deck[cur_rem].num], LCD_WIDTH - CARD_WIDTH+1, LCD_HEIGHT-CARD_HEIGHT, 8, 8, true); + rb->lcd_bitmap(colors[deck[cur_rem].color], LCD_WIDTH - CARD_WIDTH+7, LCD_HEIGHT-CARD_HEIGHT, 8, 8, true); + } + + rb->lcd_update(); + + //what to do when a key is pressed ... + switch(rb->button_get(true)){ + + //move cursor to the last card of the previous column + case BUTTON_RIGHT: + cur_col = (cur_col+1)%COL_NUM; + cur_card = cols[cur_col]; + if(cur_card != NOT_A_CARD){ + while(deck[cur_card].next != NOT_A_CARD){ + cur_card = deck[cur_card].next; + } + } + break; + + //move cursor to the last card of the next column + case BUTTON_LEFT: + cur_col = (cur_col + COL_NUM - 1)%COL_NUM; + cur_card = cols[cur_col]; + if(cur_card != NOT_A_CARD){ + while(deck[cur_card].next != NOT_A_CARD){ + cur_card = deck[cur_card].next; + } + } + break; + + //move cursor to card that's bellow + case BUTTON_DOWN: + if(cur_card == NOT_A_CARD) break; + if(deck[cur_card].next != NOT_A_CARD){ + cur_card = deck[cur_card].next; + } else { + cur_card = cols[cur_col]; + } + break; + + //move cursor to card that's above + case BUTTON_UP: + if(cur_card == NOT_A_CARD) break; + if(cols[cur_col] == cur_card){ + while(deck[cur_card].next != NOT_A_CARD){ + cur_card = deck[cur_card].next; + } + } else { + c = cols[cur_col]; + while(deck[c].next != cur_card){ + c = deck[c].next; + } + cur_card = c; + } + break; + + //Try to put card under cursor on one of the stacks + case BUTTON_F1: + //check if a card is selected + //else there would be nothing to move on the stacks ! + if(cur_card != NOT_A_CARD){ + //find the last card in the color's stack and put it's number in 'c'. + c = stacks[deck[cur_card].color]; + if(c!=NOT_A_CARD){ + while(deck[c].next!=NOT_A_CARD){ + c = deck[c].next; + } + } + //if 'c' isn't a card, that means that the stack is empty + //which implies that only an ace can be moved + if(c == NOT_A_CARD){ + //check if the selected card is an ace + //we don't have to check if any card is in the *.next + //position since the ace is the last possible card + if(deck[cur_card].num == 0){ + //remove 'cur_card' from any *.next postition ... + //... by looking in the columns + for(i=0;i0 && deck[cur_rem].next != NOT_A_CARD){ + cur_rem = deck[cur_rem].next; + i--; + } + //test if any cards are really left on the remains' stack + if(i == CARDS_PER_DRAW){ + cur_rem = NOT_A_CARD; + } + } + break; + + //Show the menu + case BUTTON_OFF: + switch(solitaire_menu(MENU_DURINGGAME)){ + case MENU_QUIT: + return; + + case MENU_RESTART: + solitaire_init(); + break; + } + } + } +} + +enum plugin_status plugin_start(struct plugin_api* api, void* parameter) +{ + //plugin init + TEST_PLUGIN_API(api); + (void)parameter; + rb = api; + //end of plugin init + + //Welcome to Solitaire ! + rb->splash(HZ*2, true, "Welcome to Solitaire !"); + + //play the game :) + solitaire(); + + //Exit the plugin + return PLUGIN_OK; +} + +#endif -- cgit v1.2.3