From e2a73dc3895d2f2457cf6397def93773f15050d9 Mon Sep 17 00:00:00 2001 From: Antoine Cellerier Date: Sun, 13 Aug 2006 20:44:53 +0000 Subject: [PATCH] *: Enhance minesweeper graphics minesweeper.c: clean source code (ipod keys still need to be changed) git-svn-id: svn://svn.rockbox.org/rockbox/trunk@10562 a1c6a512-1295-4272-9138-f99709370657 --- apps/plugins/bitmaps/native/SOURCES | 12 + .../bitmaps/native/minesweeper_tiles.12x12x2.bmp | Bin 0 -> 2950 bytes .../bitmaps/native/minesweeper_tiles.12x12x24.bmp | Bin 0 -> 5670 bytes .../bitmaps/native/minesweeper_tiles.16x16x24.bmp | Bin 0 -> 10038 bytes .../bitmaps/native/minesweeper_tiles.8x8x1.bmp | Bin 0 -> 2550 bytes apps/plugins/minesweeper.c | 1412 ++++++++++---------- 6 files changed, 687 insertions(+), 737 deletions(-) create mode 100644 apps/plugins/bitmaps/native/minesweeper_tiles.12x12x2.bmp create mode 100644 apps/plugins/bitmaps/native/minesweeper_tiles.12x12x24.bmp create mode 100644 apps/plugins/bitmaps/native/minesweeper_tiles.16x16x24.bmp create mode 100644 apps/plugins/bitmaps/native/minesweeper_tiles.8x8x1.bmp rewrite apps/plugins/minesweeper.c (67%) diff --git a/apps/plugins/bitmaps/native/SOURCES b/apps/plugins/bitmaps/native/SOURCES index 98c3eef443..10e61fb97b 100644 --- a/apps/plugins/bitmaps/native/SOURCES +++ b/apps/plugins/bitmaps/native/SOURCES @@ -280,4 +280,16 @@ rockpaint.bmp rockpaint_hsvrgb.bmp #endif +#if defined( HAVE_LCD_COLOR ) +#if ( LCD_HEIGHT * LCD_WIDTH ) / ( 16 * 16 ) >= 130 +minesweeper_tiles.16x16x24.bmp +#else +minesweeper_tiles.12x12x24.bmp +#endif +#elif LCD_DEPTH > 1 +minesweeper_tiles.12x12x2.bmp +#else +minesweeper_tiles.8x8x1.bmp +#endif + #endif /* HAVE_LCD_BITMAP */ diff --git a/apps/plugins/bitmaps/native/minesweeper_tiles.12x12x2.bmp b/apps/plugins/bitmaps/native/minesweeper_tiles.12x12x2.bmp new file mode 100644 index 0000000000000000000000000000000000000000..fddd3667821c299a7c85345c896e0235ba74434f GIT binary patch literal 2950 zcwW7f2V9L`7{|XzMM-32%gj~?p_Gvo#Wk}M8A)b#W|39)$`;q&RJIC9WmkkKdzL-w zs{7vCeQ#aS5$QXIhm9IPKfRUas zG8ToA`O1@rym|AIFJC^iw6w^dKR?>q+UV%$psTA(fdU06Sg;^^dV1*V>r<#uAq)%* zC|tNOhK7a|DN=-@MT=r&WJIxI#VB69I3-Gypk&FC7#kZ?s#GaTmo812GG!=Rwk+k! zm7{$5@>Hl$fr=F?Vq#)KrAn2kT)8q;s#KwB)v8phR*mY_t7B?vN{t#ds9CcnwQAL( zcJ12KsZ)o#b?Z{EUOnp9uaB9T8Rq8ZG-%L(h7B9is8J&gk*;04(yd!JBoYbTyLYEYj~?{w*^^$q zdeOUgZ~FAgvkS zp+gxqY#76b4`;-P5xBXzF>>Tc+}+(7HEI+d9v+MyJ(@9N#xQp5SjLST$N2H%nJ{4j zo}QjeoH&t5lO{2F@?@q=nZnemQ<*kx8q=pw$IHu$88c=ubLLED&6>sR*|V85XAX1c z&c)l?8y_DZ=FOYO{Q2|o_4Q@Jf(0yGxR6DQ7O{BoVwNmff}fus{{H?fUAmNI%a*Zx z`EpjQSi#DbD_ON_6{}aTX3d&4tX;d7b?er#e*Jm^0s`2uVFMdCZe-J@O>Ex0nJrtk zuyyNJwr$(S_U+pV3=Cw)jvegWxf7{W%C23z*u8rC+xx^#)lmoF0$5y6!!SBQ*^)g0;gPS*Ra_iPDZr{GmojZ4kjg2KPE{^#4c<$c4%e{N|NJvQF z{{8zrc<_LS43?k9hp}F-b{DBqt~H({S*`}U3R z-@o(Y#}9t~{7G6`8tLij$Yiq2-)pu&1sVShimC8NArUbmR7|9@ED;i^CcRpHjUg3< zOw6+Xnw24Dv4b3bgl#G6C{R%osYWJ?m2zdSNUyA~*^fjtk*GiAXDf${kKCKEt~h={ zpqyl`%kN8}7w${J^4rQ$U-cA64nJ9p%7daU0%v|Nuvnw6S82q#YI;?#-1(7bYh;-^ zi|VU$4nJz%vLcs$)b=Z`DKz^{FPTaslVxB3C+DMHU)5J0{FNW2p?~pwGUNAmA^T&m z%$Mj)RJmf#>Xkb`qW!8iuhe9*N~6vyjk?cl8hNi=`4R6|%&N-}_AAVUTupwm=l)$k YiewF}bo3|YcN&?Pg~+X+|BXfQ3)f!%*Z=?k literal 0 HcwPel00001 diff --git a/apps/plugins/bitmaps/native/minesweeper_tiles.12x12x24.bmp b/apps/plugins/bitmaps/native/minesweeper_tiles.12x12x24.bmp new file mode 100644 index 0000000000000000000000000000000000000000..28340760dfc598037019c623e1cba8787713a4ec GIT binary patch literal 5670 zcwX(7p^n=?5Qew729>H-egLZ~G%AjYOv?NK`v3-oW@iv!Q0W#HSV}-a-~m5?!GVI4 za_~T0eK8y4kg-dr_3AQh%+Z&G^gA&d#pAdHe3wOV#TQuGhFCTn(-# zD(>yyUnuqbDP0fJdal%Nzbzfh5HlHP-YYfhfoJ{avbQ+QrE<0O7+({Mp%A`)2etiF zRkhpM4kunLJ()}{E-ox)<}-a`T@K|HGC$mAj-@PXU~=oauCD7!)ONcCHXo5Oh9+dS zT6H4=M$CG>J__?M#@cK)>k)N*6?USi3f-~mm3s2?f-#P1&nt8W83>-W)&S6Pa(CvC zJU9&bY1?aKZjcvyRYMREe_>4V24wL73 zS(X5zD8eVa!QwDQQK)@!P-c`T4hn`s_zVZN{Z#wUL)#B^vMh6+hw$$+5CcfT&x<9@ z4~s*vrqihjQ1>@IiV^%%-}L(t%ZcvN?zVr<3|1x?X^A>a+qS+R7$3`o#0nX67m&NG zv($@(wTCt4EFqu4LdBxx3G|unVWSx_ciON?k_Zeo9X*8oy=)6lV1Ex%IxO-dGbCXT z`Z`O!j7gp5FtAjWs_U5UqJyuD+01;d$%xJv6XJ&%VLTkmQMjKjAa_}(uUDQoX=IOUMseVx8uILG3+>ol2(B{A8@4E@1a zzdBb20I+Bp!AaBp`6uF!89-defEnXhdamJ$jOc?&_uqpwX8fE+OMV=NFsE_!kU2bk zy`Y<>aTeJa^CODzr)V3;gA56`z^t^kjf2d3gt>0pTVw8%L|{HI7UV>Z1x)tCg10;I QY&@v5)ayTUFcVU*p9IbfCjbBd literal 0 HcwPel00001 diff --git a/apps/plugins/bitmaps/native/minesweeper_tiles.16x16x24.bmp b/apps/plugins/bitmaps/native/minesweeper_tiles.16x16x24.bmp new file mode 100644 index 0000000000000000000000000000000000000000..4e1191fad0f76c22a03846f875f06204a1ca873e GIT binary patch literal 10038 zcwX(9%}oO_5Jt_J3lbMPfC^FocY1PZQvw|&t2J4T$Mb7DP9*Z=MT+;$mxm_}Z8{7T&*K%FSIj3~?57|#Q@YD4trmAi7S(JQlPbT@f_)Frwg2<}72rqm+vi&t@r#pcNG-`v z99SUv5`(^CV%YrhXj&8J_xTWCpSI+fZ+#4jJ(%T7s$9DTuHZ|RK|TL9exxm zvSOvb{prsR)|X^b()xAUd_UTcBC|fIjQh@hloHAJ(BVh1A}f~pDP?IyeO#jVGtrOs z2M@S|9f70Z0( ze;iRCm+1Z6!gu!H?PEOsU=&|k$qpY7-TT2wj$=huEc3;qa36Dhkiq>+nUY`7tEBaj zO7!*geBP+fj@DO70MWf4oa8uGWW{2iJy0h4q^iC3;J)%nS)Y`6e2DaO5cMTG{3upr N#nab$`Z^2z5Ep+?F5LhC literal 0 HcwPel00001 diff --git a/apps/plugins/bitmaps/native/minesweeper_tiles.8x8x1.bmp b/apps/plugins/bitmaps/native/minesweeper_tiles.8x8x1.bmp new file mode 100644 index 0000000000000000000000000000000000000000..610fbac1fbc02fb843f835a879e28f28635ddc39 GIT binary patch literal 2550 zcwWVhK@I{j3t{G6FX3H{l^}{QmCHJPVu4M z*%3?8=|@F*w)hE4fp^1Op^i_auTR)d=g5yevtX8XRKovJe$`1mgrz9@f3O*K<@YJ_ zQx9P&Fiv-sPH|icFw_Z4fkD-eHt!kwhyAF}Lc!wxjr#GEbV^ZAxFeQ=vcBKM-6>t| Lh^0_H|I$OgielQ$ literal 0 HcwPel00001 diff --git a/apps/plugins/minesweeper.c b/apps/plugins/minesweeper.c dissimilarity index 67% index 21e655671f..317a969fb0 100644 --- a/apps/plugins/minesweeper.c +++ b/apps/plugins/minesweeper.c @@ -1,737 +1,675 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2004-2006 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 -*****************************************************************************/ - -#include "plugin.h" - -#ifdef HAVE_LCD_BITMAP - -PLUGIN_HEADER - -/*what the minesweeper() function can return */ -#define MINESWEEPER_USB 3 -#define MINESWEEPER_QUIT 2 -#define MINESWEEPER_LOSE 1 -#define MINESWEEPER_WIN 0 - -/* variable button definitions */ -#if CONFIG_KEYPAD == RECORDER_PAD -#define MINESWP_UP BUTTON_UP -#define MINESWP_DOWN BUTTON_DOWN -#define MINESWP_QUIT BUTTON_OFF -#define MINESWP_START BUTTON_ON -#define MINESWP_TOGGLE BUTTON_PLAY -#define MINESWP_TOGGLE2 BUTTON_F1 -#define MINESWP_DISCOVER BUTTON_ON -#define MINESWP_DISCOVER2 BUTTON_F2 -#define MINESWP_INFO BUTTON_F3 -#define MINESWP_RIGHT (BUTTON_F1 | BUTTON_RIGHT) -#define MINESWP_LEFT (BUTTON_F1 | BUTTON_LEFT) - -#elif CONFIG_KEYPAD == ONDIO_PAD -#define MINESWP_UP BUTTON_UP -#define MINESWP_DOWN BUTTON_DOWN -#define MINESWP_QUIT BUTTON_OFF -#define MINESWP_START BUTTON_MENU -#define MINESWP_TOGGLE_PRE BUTTON_MENU -#define MINESWP_TOGGLE (BUTTON_MENU | BUTTON_REL) -#define MINESWP_DISCOVER (BUTTON_MENU | BUTTON_REPEAT) -#define MINESWP_INFO (BUTTON_MENU | BUTTON_OFF) -#define MINESWP_RIGHT (BUTTON_MENU | BUTTON_RIGHT) -#define MINESWP_LEFT (BUTTON_MENU | BUTTON_LEFT) - -#elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \ - (CONFIG_KEYPAD == IRIVER_H300_PAD) -#define MINESWP_UP BUTTON_UP -#define MINESWP_DOWN BUTTON_DOWN -#define MINESWP_QUIT BUTTON_OFF -#define MINESWP_START BUTTON_SELECT -#define MINESWP_TOGGLE BUTTON_ON -#define MINESWP_DISCOVER BUTTON_SELECT -#define MINESWP_INFO BUTTON_MODE -#define MINESWP_RIGHT (BUTTON_ON | BUTTON_RIGHT) -#define MINESWP_LEFT (BUTTON_ON | BUTTON_LEFT) - -#define MINESWP_RC_QUIT BUTTON_RC_STOP - -#elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \ - (CONFIG_KEYPAD == IPOD_3G_PAD) -#define MINESWP_UP BUTTON_SCROLL_BACK -#define MINESWP_DOWN BUTTON_SCROLL_FWD -#define MINESWP_QUIT BUTTON_MENU -#define MINESWP_START BUTTON_SELECT -#define MINESWP_TOGGLE BUTTON_PLAY -#define MINESWP_DISCOVER (BUTTON_SELECT | BUTTON_PLAY) -#define MINESWP_INFO (BUTTON_SELECT | BUTTON_MENU) -#define MINESWP_RIGHT (BUTTON_SELECT | BUTTON_RIGHT) -#define MINESWP_LEFT (BUTTON_SELECT | BUTTON_LEFT) - -#elif (CONFIG_KEYPAD == IAUDIO_X5_PAD) -#define MINESWP_UP BUTTON_UP -#define MINESWP_DOWN BUTTON_DOWN -#define MINESWP_QUIT BUTTON_POWER -#define MINESWP_START BUTTON_REC -#define MINESWP_TOGGLE BUTTON_PLAY -#define MINESWP_DISCOVER BUTTON_SELECT -#define MINESWP_INFO (BUTTON_REC | BUTTON_PLAY) -#define MINESWP_RIGHT (BUTTON_PLAY | BUTTON_RIGHT) -#define MINESWP_LEFT (BUTTON_PLAY | BUTTON_LEFT) - -#elif (CONFIG_KEYPAD == GIGABEAT_PAD) -#define MINESWP_UP BUTTON_UP -#define MINESWP_DOWN BUTTON_DOWN -#define MINESWP_QUIT BUTTON_A -#define MINESWP_START BUTTON_SELECT -#define MINESWP_TOGGLE BUTTON_POWER -#define MINESWP_DISCOVER BUTTON_SELECT -#define MINESWP_INFO BUTTON_MENU -#define MINESWP_RIGHT (BUTTON_SELECT | BUTTON_RIGHT) -#define MINESWP_LEFT (BUTTON_SELECT | BUTTON_LEFT) - -#elif (CONFIG_KEYPAD == IRIVER_H10_PAD) -#define MINESWP_UP BUTTON_SCROLL_UP -#define MINESWP_DOWN BUTTON_SCROLL_DOWN -#define MINESWP_QUIT BUTTON_POWER -#define MINESWP_START BUTTON_FF -#define MINESWP_TOGGLE BUTTON_PLAY -#define MINESWP_DISCOVER BUTTON_REW -#define MINESWP_INFO (BUTTON_REW | BUTTON_PLAY) -#define MINESWP_RIGHT (BUTTON_RIGHT | BUTTON_PLAY) -#define MINESWP_LEFT (BUTTON_LEFT | BUTTON_PLAY) - -#endif - -/* 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[10][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},/* ........ */ - /* mine */ - {0x00, /* ........ */ - 0x00, /* ........ */ - 0x18, /* ...OO... */ - 0x3c, /* ..OOOO.. */ - 0x3c, /* ..OOOO.. */ - 0x18, /* ...OO... */ - 0x00, /* ........ */ - 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 */ -int height = LCD_HEIGHT/8; -int width = LCD_WIDTH/8; - -/* The Minefield. Caution it is defined as Y, X! Not the opposite. */ -tile minefield[LCD_HEIGHT/8][LCD_WIDTH/8]; - -/* total number of mines on the game */ -int mine_num = 0; - -/* percentage of mines on minefield used during generation */ -int p=16; - -/* number of tiles left on the game */ -int tiles_left; - -/* Because mines are set after the first move... */ -bool no_mines = true; - -/* We need a stack (created on discover()) for the cascade algorithm. */ -int stack_pos = 0; - -/* Functions to center the board on screen. */ -int c_height(void){ - return LCD_HEIGHT/16 - height/2; -} - -int c_width(void){ - return LCD_WIDTH/16 - width/2; -} - -void push (int *stack, int y, int x){ - - if(stack_pos <= height*width){ - stack_pos++; - stack[stack_pos] = y; - stack_pos++; - stack[stack_pos] = x; - } -} - -/* Unveil tiles and push them to stack if they are empty. */ -void unveil(int *stack, int y, int x){ - - if(x < c_width() || y < c_height() || x > c_width() + width-1 - || y > c_height() + height-1 || minefield[y][x].known - || minefield[y][x].mine || minefield[y][x].flag) return; - - if(minefield[y][x].neighbors == 0){ - minefield[y][x].known = 1; - push(stack, y, x); - } else - minefield[y][x].known = 1; -} - -void discover(int y, int x){ - - int stack[height*width]; - - /* Selected tile. */ - if(x < c_width() || y < c_height() || x > c_width() + width-1 - || y > c_height() + height-1 || minefield[y][x].known - || minefield[y][x].mine || minefield[y][x].flag) return; - - minefield[y][x].known = 1; - /* Exit if the tile is not empty. (no mines nearby) */ - if(minefield[y][x].neighbors) return; - - push(stack, y, x); - - /* Scan all nearby tiles. If we meet a tile with a number we just unveil - it. If we meet an empty tile, we push the location in stack. For each - location in stack we do the same thing. (scan again all nearby tiles) */ - while(stack_pos){ - /* Retrieve x, y from stack. */ - x = stack[stack_pos]; - y = stack[stack_pos-1]; - - /* Pop. */ - if(stack_pos > 0) stack_pos -= 2; - else rb->splash(HZ,true,"ERROR"); - - unveil(stack, y-1, x-1); - unveil(stack, y-1, x); - unveil(stack, y-1, x+1); - unveil(stack, y, x+1); - unveil(stack, y+1, x+1); - unveil(stack, y+1, x); - unveil(stack, y+1, x-1); - unveil(stack, y, x-1); - } -} - -/* Reset the whole board for a new game. */ -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(j 1 - rb->lcd_set_foreground(LCD_DARKGRAY); - rb->lcd_drawrect(j*8,i*8,8,8); - rb->lcd_set_foreground(LCD_BLACK); -#else - rb->lcd_drawrect(j*8,i*8,8,8); -#endif - if(!minefield[i][j].known){ - if(minefield[i][j].mine){ - rb->lcd_set_drawmode(DRMODE_COMPLEMENT); - rb->lcd_mono_bitmap(num[9], j*8,i*8,8,8); - rb->lcd_set_drawmode(DRMODE_SOLID); - } else if(minefield[i][j].neighbors){ - rb->lcd_set_drawmode(DRMODE_COMPLEMENT); - rb->lcd_mono_bitmap(num[minefield[i][j].neighbors], - j*8,i*8,8,8); - rb->lcd_set_drawmode(DRMODE_SOLID); - } - } - } - } - rb->lcd_update(); - - do - button = rb->button_get(true); - while ((button == BUTTON_NONE) || (button & (BUTTON_REL|BUTTON_REPEAT))); -} - - -/* the big and ugly function that is the game */ -int minesweeper(void) -{ - int i,j; - int button; - int lastbutton = BUTTON_NONE; - - /* the cursor coordinates */ - int x=0, y=0; - - /* a usefull string for snprintf */ - char str[30]; - - /* welcome screen where player can chose mine percentage */ - i = 0; - while(true){ - rb->lcd_clear_display(); - - rb->lcd_puts(0,0,"Mine Sweeper"); - - rb->snprintf(str, 20, "%d%% mines", p); - rb->lcd_puts(0,2,str); - rb->lcd_puts(0,3,"down / up"); - rb->snprintf(str, 20, "%d cols x %d rows", width, height); - rb->lcd_puts(0,4,str); - rb->lcd_puts(0,5,"left x right "); -#if CONFIG_KEYPAD == RECORDER_PAD - rb->lcd_puts(0,6,"ON to start"); -#elif CONFIG_KEYPAD == ONDIO_PAD - rb->lcd_puts(0,6,"MODE to start"); -#elif (CONFIG_KEYPAD==IRIVER_H100_PAD) || (CONFIG_KEYPAD==IPOD_4G_PAD) - rb->lcd_puts(0,6,"SELECT to start"); -#elif CONFIG_KEYPAD == IAUDIO_X5_PAD - rb->lcd_puts(0,6,"REC to start"); -#endif - rb->lcd_update(); - - button = rb->button_get(true); - switch(button){ - case MINESWP_DOWN: - case (MINESWP_DOWN | BUTTON_REPEAT): - p = (p + 98)%100; - /* Don't let the user play without mines. */ - if(!p) p = 98; - break; - - case MINESWP_UP: - case (MINESWP_UP | BUTTON_REPEAT): - p = (p + 2)%100; - /* Don't let the user play without mines. */ - if(!p) p = 2; - break; - - case BUTTON_RIGHT: - case (BUTTON_RIGHT | BUTTON_REPEAT): - height = height%(LCD_HEIGHT/8)+1; - break; - - case BUTTON_LEFT: - case (BUTTON_LEFT | BUTTON_REPEAT): - width = width%(LCD_WIDTH/8)+1; - break; - - case MINESWP_RIGHT: - case (MINESWP_RIGHT | BUTTON_REPEAT): - height--; - if(height < 1) height = LCD_HEIGHT/8; - if(height > LCD_HEIGHT) height = 1; - break; - - case MINESWP_LEFT: - case (MINESWP_LEFT | BUTTON_REPEAT): - width--; - if(width < 1) width = LCD_WIDTH/8; - if(width > LCD_WIDTH) width = 1; - break; - - case MINESWP_START:/* start playing */ - i = 1; - break; -#ifdef MINESWP_RC_QUIT - case MINESWP_RC_QUIT: -#endif - case MINESWP_QUIT:/* quit program */ - return MINESWEEPER_QUIT; - - default: - if (rb->default_event_handler(button) == SYS_USB_CONNECTED) - return MINESWEEPER_USB; - break; - } - if(i==1) - break; - } - - - /******************** - * init * - ********************/ - - minesweeper_init(); - x = c_width(); - y = c_height(); - - /********************** - * play * - **********************/ - - while(true){ - - /*clear the screen buffer */ - rb->lcd_clear_display(); - - /*display the mine field */ - for(i=c_height();i 1 - rb->lcd_set_foreground(LCD_DARKGRAY); - rb->lcd_drawrect(j*8,i*8,8,8); - rb->lcd_set_foreground(LCD_BLACK); -#else - rb->lcd_drawrect(j*8,i*8,8,8); -#endif - if(minefield[i][j].known){ - if(minefield[i][j].neighbors){ - rb->lcd_set_drawmode(DRMODE_COMPLEMENT); - rb->lcd_mono_bitmap(num[minefield[i][j].neighbors], - j*8,i*8,8,8); - rb->lcd_set_drawmode(DRMODE_SOLID); - } - } 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 { -#if LCD_DEPTH > 1 - rb->lcd_set_foreground(LCD_LIGHTGRAY); - rb->lcd_fillrect(j*8+1,i*8+1,6,6); - rb->lcd_set_foreground(LCD_BLACK); -#else - rb->lcd_fillrect(j*8+2,i*8+2,4,4); -#endif - } - } - } - - /* display the cursor */ - rb->lcd_set_drawmode(DRMODE_COMPLEMENT); - rb->lcd_fillrect(x*8,y*8,8,8); - rb->lcd_set_drawmode(DRMODE_SOLID); - - /* update the screen */ - rb->lcd_update(); - - button = rb->button_get(true); - switch(button){ - /* quit minesweeper (you really shouldn't use this button ...) */ -#ifdef MINESWP_RC_QUIT - case MINESWP_RC_QUIT: -#endif - case MINESWP_QUIT: - return MINESWEEPER_QUIT; - - /* move cursor left */ - case BUTTON_LEFT: - case (BUTTON_LEFT | BUTTON_REPEAT): - if(x<=c_width()) x = width + c_width(); - x = x-1; - break; - - /* move cursor right */ - case BUTTON_RIGHT: - case (BUTTON_RIGHT | BUTTON_REPEAT): - if(x>=width + c_width() - 1) x = c_width() - 1; - x = x+1; - break; - - /* move cursor down */ - case MINESWP_DOWN: - case (MINESWP_DOWN | BUTTON_REPEAT): - if(y>=height + c_height() - 1) y = c_height() - 1; - y = y+1; - break; - - /* move cursor up */ - case MINESWP_UP: - case (MINESWP_UP | BUTTON_REPEAT): - if(y<=c_height()) y = height + c_height(); - y = y-1; - break; - - /* discover a tile (and it's neighbors if .neighbors == 0) */ - case MINESWP_DISCOVER: -#ifdef MINESWP_DISCOVER2 - case MINESWP_DISCOVER2: -#endif - 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 && no_mines) - minesweeper_putmines(p,x,y); - - discover(y, x); - - if(minefield[y][x].mine){ - return MINESWEEPER_LOSE; - } - tiles_left = 0; - for(i=c_height();isplash(HZ*2, true, "You found %d mines out of %d", - tiles_left, mine_num); - break; - - default: - if (rb->default_event_handler(button) == SYS_USB_CONNECTED) - return MINESWEEPER_USB; - break; - } - if (button != BUTTON_NONE) - lastbutton = button; - } - -} - -/* plugin entry point */ -enum plugin_status plugin_start(struct plugin_api* api, void* parameter) -{ - bool exit = false; - /* plugin init */ - (void)parameter; - rb = api; - /* end of plugin init */ - - while(!exit) { - switch(minesweeper()){ - case MINESWEEPER_WIN: - rb->splash(HZ*2, true, "You Win! Press a key"); - rb->lcd_clear_display(); - mine_show(); - break; - - case MINESWEEPER_LOSE: - rb->splash(HZ*2, true, "You Lose! Press a key"); - rb->lcd_clear_display(); - mine_show(); - break; - - case MINESWEEPER_USB: - return PLUGIN_USB_CONNECTED; - - case MINESWEEPER_QUIT: - exit = true; - break; - - default: - break; - } - } - - return PLUGIN_OK; -} - -#endif +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2004-2006 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. + * + ****************************************************************************/ + +#include "plugin.h" + +#ifdef HAVE_LCD_BITMAP + +PLUGIN_HEADER + +/* what the minesweeper() function can return */ +enum minesweeper_status { + MINESWEEPER_WIN, + MINESWEEPER_LOSE, + MINESWEEPER_QUIT, + MINESWEEPER_USB +}; + +/* variable button definitions */ +#if CONFIG_KEYPAD == RECORDER_PAD +# define MINESWP_UP BUTTON_UP +# define MINESWP_DOWN BUTTON_DOWN +# define MINESWP_QUIT BUTTON_OFF +# define MINESWP_START BUTTON_ON +# define MINESWP_TOGGLE BUTTON_PLAY +# define MINESWP_TOGGLE2 BUTTON_F1 +# define MINESWP_DISCOVER BUTTON_ON +# define MINESWP_DISCOVER2 BUTTON_F2 +# define MINESWP_INFO BUTTON_F3 +# define MINESWP_RIGHT (BUTTON_F1 | BUTTON_RIGHT) +# define MINESWP_LEFT (BUTTON_F1 | BUTTON_LEFT) + +#elif CONFIG_KEYPAD == ONDIO_PAD +# define MINESWP_UP BUTTON_UP +# define MINESWP_DOWN BUTTON_DOWN +# define MINESWP_QUIT BUTTON_OFF +# define MINESWP_START BUTTON_MENU +# define MINESWP_TOGGLE_PRE BUTTON_MENU +# define MINESWP_TOGGLE (BUTTON_MENU | BUTTON_REL) +# define MINESWP_DISCOVER (BUTTON_MENU | BUTTON_REPEAT) +# define MINESWP_INFO (BUTTON_MENU | BUTTON_OFF) +# define MINESWP_RIGHT (BUTTON_MENU | BUTTON_RIGHT) +# define MINESWP_LEFT (BUTTON_MENU | BUTTON_LEFT) + +#elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \ + (CONFIG_KEYPAD == IRIVER_H300_PAD) +# define MINESWP_UP BUTTON_UP +# define MINESWP_DOWN BUTTON_DOWN +# define MINESWP_QUIT BUTTON_OFF +# define MINESWP_START BUTTON_SELECT +# define MINESWP_TOGGLE BUTTON_ON +# define MINESWP_DISCOVER BUTTON_SELECT +# define MINESWP_INFO BUTTON_MODE +# define MINESWP_RIGHT (BUTTON_ON | BUTTON_RIGHT) +# define MINESWP_LEFT (BUTTON_ON | BUTTON_LEFT) + +# define MINESWP_RC_QUIT BUTTON_RC_STOP + +#elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \ + (CONFIG_KEYPAD == IPOD_3G_PAD) +# define MINESWP_UP BUTTON_SCROLL_BACK +# define MINESWP_DOWN BUTTON_SCROLL_FWD +# define MINESWP_QUIT BUTTON_MENU +# define MINESWP_START BUTTON_SELECT +# define MINESWP_TOGGLE BUTTON_PLAY +# define MINESWP_DISCOVER (BUTTON_SELECT | BUTTON_PLAY) +# define MINESWP_INFO (BUTTON_SELECT | BUTTON_MENU) +# define MINESWP_RIGHT (BUTTON_SELECT | BUTTON_RIGHT) +# define MINESWP_LEFT (BUTTON_SELECT | BUTTON_LEFT) + +#elif (CONFIG_KEYPAD == IAUDIO_X5_PAD) +# define MINESWP_UP BUTTON_UP +# define MINESWP_DOWN BUTTON_DOWN +# define MINESWP_QUIT BUTTON_POWER +# define MINESWP_START BUTTON_REC +# define MINESWP_TOGGLE BUTTON_PLAY +# define MINESWP_DISCOVER BUTTON_SELECT +# define MINESWP_INFO (BUTTON_REC | BUTTON_PLAY) +# define MINESWP_RIGHT (BUTTON_PLAY | BUTTON_RIGHT) +# define MINESWP_LEFT (BUTTON_PLAY | BUTTON_LEFT) + +#elif (CONFIG_KEYPAD == GIGABEAT_PAD) +# define MINESWP_UP BUTTON_UP +# define MINESWP_DOWN BUTTON_DOWN +# define MINESWP_QUIT BUTTON_A +# define MINESWP_START BUTTON_SELECT +# define MINESWP_TOGGLE BUTTON_POWER +# define MINESWP_DISCOVER BUTTON_SELECT +# define MINESWP_INFO BUTTON_MENU +# define MINESWP_RIGHT (BUTTON_SELECT | BUTTON_RIGHT) +# define MINESWP_LEFT (BUTTON_SELECT | BUTTON_LEFT) + +#elif (CONFIG_KEYPAD == IRIVER_H10_PAD) +# define MINESWP_UP BUTTON_SCROLL_UP +# define MINESWP_DOWN BUTTON_SCROLL_DOWN +# define MINESWP_QUIT BUTTON_POWER +# define MINESWP_START BUTTON_FF +# define MINESWP_TOGGLE BUTTON_PLAY +# define MINESWP_DISCOVER BUTTON_REW +# define MINESWP_INFO (BUTTON_REW | BUTTON_PLAY) +# define MINESWP_RIGHT (BUTTON_RIGHT | BUTTON_PLAY) +# define MINESWP_LEFT (BUTTON_LEFT | BUTTON_PLAY) + +#else +# warning Missing key definitions for this keypad +#endif + +/* 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; + +extern const fb_data minesweeper_tiles[]; + +#ifdef HAVE_LCD_COLOR +# if ( LCD_HEIGHT * LCD_WIDTH ) / ( 16 * 16 ) >= 130 + /* We want to have at least 130 tiles on the screen */ +# define TileSize 16 +# else +# define TileSize 12 +# endif +# define BackgroundColor LCD_RGBPACK( 128, 128, 128 ) +#elif LCD_DEPTH > 1 +# define TileSize 12 +#else +# define TileSize 8 +#endif + +#define Mine 9 +#define Flag 10 +#define Unknown 11 +#define ExplodedMine 12 + +#define draw_tile( num, x, y ) \ + rb->lcd_bitmap_part( minesweeper_tiles, 0, num * TileSize, \ + TileSize, left+x*TileSize, top+y*TileSize, \ + TileSize, TileSize ) + +#define invert_tile( x, y ) \ + rb->lcd_set_drawmode(DRMODE_COMPLEMENT); \ + rb->lcd_fillrect( left+x*TileSize, top+y*TileSize, TileSize, TileSize ); \ + rb->lcd_set_drawmode(DRMODE_SOLID); + + +/* 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 */ +#define MAX_HEIGHT (LCD_HEIGHT/TileSize) +#define MAX_WIDTH (LCD_WIDTH/TileSize) +int height = MAX_HEIGHT; +int width = MAX_WIDTH; +int top; +int left; + +/* The Minefield. Caution it is defined as Y, X! Not the opposite. */ +tile minefield[MAX_HEIGHT][MAX_WIDTH]; + +/* total number of mines on the game */ +int mine_num = 0; + +/* percentage of mines on minefield used during generation */ +int p = 16; + +/* number of tiles left on the game */ +int tiles_left; + +/* Because mines are set after the first move... */ +bool no_mines = true; + +/* We need a stack (created on discover()) for the cascade algorithm. */ +int stack_pos = 0; + +/* a usefull string for snprintf */ +char str[30]; + + +void push( int *stack, int y, int x ) +{ + if( stack_pos <= height*width ) + { + stack[++stack_pos] = y; + stack[++stack_pos] = x; + } +} + +/* Unveil tiles and push them to stack if they are empty. */ +void unveil( int *stack, int y, int x ) +{ + if( x < 0 || y < 0 || x > width - 1 || y > height - 1 + || minefield[y][x].known + || minefield[y][x].mine || minefield[y][x].flag ) return; + + minefield[y][x].known = 1; + + if( minefield[y][x].neighbors == 0 ) + push( stack, y, x ); +} + +void discover( int y, int x ) +{ + int stack[height*width]; + + /* Selected tile. */ + if( x < 0 || y < 0 || x > width - 1 || y > height - 1 + || minefield[y][x].known + || minefield[y][x].mine || minefield[y][x].flag ) return; + + minefield[y][x].known = 1; + /* Exit if the tile is not empty. (no mines nearby) */ + if( minefield[y][x].neighbors ) return; + + push( stack, y, x ); + + /* Scan all nearby tiles. If we meet a tile with a number we just unveil + * it. If we meet an empty tile, we push the location in stack. For each + * location in stack we do the same thing. (scan again all nearby tiles) + */ + while( stack_pos ) + { + /* Pop x, y from stack. */ + x = stack[stack_pos--]; + y = stack[stack_pos--]; + + unveil( stack, y-1, x-1 ); + unveil( stack, y-1, x ); + unveil( stack, y-1, x+1 ); + unveil( stack, y, x+1 ); + unveil( stack, y+1, x+1 ); + unveil( stack, y+1, x ); + unveil( stack, y+1, x-1 ); + unveil( stack, y, x-1 ); + } +} + +/* Reset the whole board for a new game. */ +void minesweeper_init( void ) +{ + int i,j; + + for( i = 0; i < MAX_HEIGHT; i++ ) + { + for( j = 0; j < MAX_WIDTH; j++ ) + { + minefield[i][j].known = 0; + minefield[i][j].flag = 0; + minefield[i][j].mine = 0; + minefield[i][j].neighbors = 0; + } + } + no_mines = true; + tiles_left = width*height; +} + + +/* put mines on the mine field */ +/* there is p% chance that a tile is a mine */ +/* if the tile has coordinates (x,y), then it can't be a mine */ +void minesweeper_putmines( int p, int x, int y ) +{ + int i,j; + + mine_num = 0; + for( i = 0; i < height; i++ ) + { + for( j = 0; j < width; j++ ) + { + if( rb->rand()%100 < p && !( y==i && x==j ) ) + { + minefield[i][j].mine = 1; + mine_num++; + } + else + { + minefield[i][j].mine = 0; + } + minefield[i][j].neighbors = 0; + } + } + + /* we need to compute the neighbor element for each tile */ + for( i = 0; i < height; i++ ) + { + for( j = 0; j < width; j++ ) + { + if( i > 0 ) + { + if( j > 0 ) + minefield[i][j].neighbors += minefield[i-1][j-1].mine; + minefield[i][j].neighbors += minefield[i-1][j].mine; + if( j < width - 1 ) + minefield[i][j].neighbors += minefield[i-1][j+1].mine; + } + if( j > 0 ) + minefield[i][j].neighbors += minefield[i][j-1].mine; + if( j < width - 1 ) + minefield[i][j].neighbors += minefield[i][j+1].mine; + if( i < height - 1 ) + { + if( j > 0 ) + minefield[i][j].neighbors += minefield[i+1][j-1].mine; + minefield[i][j].neighbors += minefield[i+1][j].mine; + if( j < width - 1 ) + minefield[i][j].neighbors += minefield[i+1][j+1].mine; + } + } + } + + no_mines = false; + + /* In case the user is lucky and there are no mines positioned. */ + if( !mine_num && height*width != 1 ) + { + minesweeper_putmines(p, x, y); + } +} + +/* A function that will uncover all the board, when the user wins or loses. + can easily be expanded, (just a call assigned to a button) as a solver. */ +void mine_show( void ) +{ + int i, j, button; + + for( i = 0; i < height; i++ ) + { + for( j = 0; j < width; j++ ) + { + if( minefield[i][j].mine ) + { + if( minefield[i][j].known ) + { + draw_tile( ExplodedMine, j, i ); + } + else + { + draw_tile( Mine, j, i ); + } + } + else + { + draw_tile( minefield[i][j].neighbors, j, i ); + } + } + } + rb->lcd_update(); + + do + button = rb->button_get(true); + while( ( button == BUTTON_NONE ) + || ( button & (BUTTON_REL|BUTTON_REPEAT) ) ); +} + +int count_tiles_left( void ) +{ + int tiles_left = 0; + int i, j; + for( i = 0; i < height; i++ ) + for( j = 0; j < width; j++ ) + if( minefield[i][j].known == 0 ) + tiles_left++; + return tiles_left; +} + +/* welcome screen where player can chose mine percentage */ +enum minesweeper_status menu( void ) +{ + int button; + + while( true ) + { +#ifdef HAVE_LCD_COLOR + rb->lcd_set_background( LCD_WHITE ); + rb->lcd_set_foreground( LCD_BLACK ); +#endif + rb->lcd_clear_display(); + + rb->lcd_puts( 0, 0, "Mine Sweeper" ); + + rb->snprintf( str, 20, "%d%% mines", p ); + rb->lcd_puts( 0, 2, str ); + rb->lcd_puts( 0, 3, "down / up" ); + rb->snprintf( str, 20, "%d cols x %d rows", width, height ); + rb->lcd_puts( 0, 4, str ); + rb->lcd_puts( 0, 5, "left x right" ); + rb->lcd_puts( 0, 6, +#if CONFIG_KEYPAD == RECORDER_PAD + "ON to start" +#elif CONFIG_KEYPAD == ONDIO_PAD + "MODE to start" +#elif (CONFIG_KEYPAD == IRIVER_H100_PAD) \ + || (CONFIG_KEYPAD == IRIVER_H300_PAD ) \ + || (CONFIG_KEYPAD == IPOD_4G_PAD) + "SELECT to start" +#elif CONFIG_KEYPAD == IAUDIO_X5_PAD + "REC to start" +#else + "" +# warning Please define help string for this keypad. +#endif + ); + rb->lcd_update(); + + switch( button = rb->button_get( true ) ) + { + case MINESWP_DOWN: + case MINESWP_DOWN|BUTTON_REPEAT: + p = (p + 94)%98 + 2; + break; + + case MINESWP_UP: + case MINESWP_UP|BUTTON_REPEAT: + p = p%98 + 2; + break; + + case BUTTON_RIGHT: + case BUTTON_RIGHT|BUTTON_REPEAT: + height = height%MAX_HEIGHT + 1; + break; + + case BUTTON_LEFT: + case BUTTON_LEFT|BUTTON_REPEAT: + width = width%MAX_WIDTH + 1; + break; + + case MINESWP_RIGHT: + case MINESWP_RIGHT|BUTTON_REPEAT: + height--; + if( height < 1 ) height = MAX_HEIGHT; + break; + + case MINESWP_LEFT: + case MINESWP_LEFT|BUTTON_REPEAT: + width--; + if( width < 1 ) width = MAX_WIDTH; + break; + + case MINESWP_START:/* start playing */ + return MINESWEEPER_WIN; + +#ifdef MINESWP_RC_QUIT + case MINESWP_RC_QUIT: +#endif + case MINESWP_QUIT:/* quit program */ + return MINESWEEPER_QUIT; + + default: + if( rb->default_event_handler(button) == SYS_USB_CONNECTED ) + return MINESWEEPER_USB; + break; + } + } +} + +/* the big and ugly game function */ +enum minesweeper_status minesweeper( void ) +{ + int i, j; + int button; + int lastbutton = BUTTON_NONE; + + /* the cursor coordinates */ + int x=0, y=0; + + /** + * Show the menu + */ + if( ( i = menu() ) != MINESWEEPER_WIN ) return i; + + /** + * Init game + */ + top = (LCD_HEIGHT-height*TileSize)/2; + left = (LCD_WIDTH-width*TileSize)/2; + + rb->srand( *rb->current_tick ); + minesweeper_init(); + x = 0; + y = 0; + + /** + * Play + */ + while( true ) + { + + /* clear the screen buffer */ +#ifdef HAVE_LCD_COLOR + rb->lcd_set_background( BackgroundColor ); +#endif + rb->lcd_clear_display(); + + /* display the mine field */ + for( i = 0; i < height; i++ ) + { + for( j = 0; j < width; j++ ) + { + if( minefield[i][j].known ) + { + draw_tile( minefield[i][j].neighbors, j, i ); + } + else if(minefield[i][j].flag) + { + draw_tile( Flag, j, i ); + } + else + { + draw_tile( Unknown, j, i ); + } + } + } + + /* display the cursor */ + invert_tile( x, y ); + + /* update the screen */ + rb->lcd_update(); + + switch( button = rb->button_get( true ) ) + { + /* quit minesweeper (you really shouldn't use this button ...) */ +#ifdef MINESWP_RC_QUIT + case MINESWP_RC_QUIT: +#endif + case MINESWP_QUIT: + return MINESWEEPER_QUIT; + + /* move cursor left */ + case BUTTON_LEFT: + case BUTTON_LEFT|BUTTON_REPEAT: + x = ( x + width - 1 )%width; + break; + + /* move cursor right */ + case BUTTON_RIGHT: + case BUTTON_RIGHT|BUTTON_REPEAT: + x = ( x + 1 )%width; + break; + + /* move cursor down */ + case MINESWP_DOWN: + case MINESWP_DOWN|BUTTON_REPEAT: + y = ( y + 1 )%height; + break; + + /* move cursor up */ + case MINESWP_UP: + case MINESWP_UP|BUTTON_REPEAT: + y = ( y + height - 1 )%height; + break; + + /* discover a tile (and it's neighbors if .neighbors == 0) */ + case MINESWP_DISCOVER: +#ifdef MINESWP_DISCOVER2 + case MINESWP_DISCOVER2: +#endif + 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 && no_mines ) + minesweeper_putmines(p,x,y); + + discover(y, x); + + if( minefield[y][x].mine ) + { + minefield[y][x].known = 1; + return MINESWEEPER_LOSE; + } + tiles_left = count_tiles_left(); + if( tiles_left == mine_num ) + { + return MINESWEEPER_WIN; + } + break; + + /* toggle flag under cursor */ + case MINESWP_TOGGLE: +#ifdef MINESWP_TOGGLE_PRE + if( lastbutton != MINESWP_TOGGLE_PRE ) + break; +#endif +#ifdef MINESWP_TOGGLE2 + case MINESWP_TOGGLE2: +#endif + minefield[y][x].flag = ( minefield[y][x].flag + 1 )%2; + break; + + /* show how many mines you think you have found and how many + * there really are on the game */ + case MINESWP_INFO: + if( no_mines ) + break; + tiles_left = count_tiles_left(); + rb->splash( HZ*2, true, "You found %d mines out of %d", + tiles_left, mine_num ); + break; + + default: + if( rb->default_event_handler( button ) == SYS_USB_CONNECTED ) + return MINESWEEPER_USB; + break; + } + if( button != BUTTON_NONE ) + lastbutton = button; + } + +} + +/* plugin entry point */ +enum plugin_status plugin_start(struct plugin_api* api, void* parameter) +{ + bool exit = false; + + (void)parameter; + rb = api; + + while( !exit ) + { + switch( minesweeper() ) + { + case MINESWEEPER_WIN: + rb->splash( HZ, true, "You Win!" ); + rb->lcd_clear_display(); + mine_show(); + break; + + case MINESWEEPER_LOSE: + rb->splash( HZ, true, "You Lose!" ); + rb->lcd_clear_display(); + mine_show(); + break; + + case MINESWEEPER_USB: + return PLUGIN_USB_CONNECTED; + + case MINESWEEPER_QUIT: + exit = true; + break; + + default: + break; + } + } + + return PLUGIN_OK; +} + +#endif -- 2.11.4.GIT