1
0
Fork 0
forked from len0rd/rockbox

*: 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
This commit is contained in:
Antoine Cellerier 2006-08-13 20:44:53 +00:00
parent c9bb152a33
commit e2a73dc389
6 changed files with 378 additions and 428 deletions

View file

@ -280,4 +280,16 @@ rockpaint.bmp
rockpaint_hsvrgb.bmp rockpaint_hsvrgb.bmp
#endif #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 */ #endif /* HAVE_LCD_BITMAP */

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

View file

@ -17,10 +17,6 @@
* *
****************************************************************************/ ****************************************************************************/
/*****************************************************************************
Mine Sweeper by dionoea
*****************************************************************************/
#include "plugin.h" #include "plugin.h"
#ifdef HAVE_LCD_BITMAP #ifdef HAVE_LCD_BITMAP
@ -28,10 +24,12 @@ Mine Sweeper by dionoea
PLUGIN_HEADER PLUGIN_HEADER
/* what the minesweeper() function can return */ /* what the minesweeper() function can return */
#define MINESWEEPER_USB 3 enum minesweeper_status {
#define MINESWEEPER_QUIT 2 MINESWEEPER_WIN,
#define MINESWEEPER_LOSE 1 MINESWEEPER_LOSE,
#define MINESWEEPER_WIN 0 MINESWEEPER_QUIT,
MINESWEEPER_USB
};
/* variable button definitions */ /* variable button definitions */
#if CONFIG_KEYPAD == RECORDER_PAD #if CONFIG_KEYPAD == RECORDER_PAD
@ -118,129 +116,56 @@ PLUGIN_HEADER
# define MINESWP_RIGHT (BUTTON_RIGHT | BUTTON_PLAY) # define MINESWP_RIGHT (BUTTON_RIGHT | BUTTON_PLAY)
# define MINESWP_LEFT (BUTTON_LEFT | BUTTON_PLAY) # define MINESWP_LEFT (BUTTON_LEFT | BUTTON_PLAY)
#else
# warning Missing key definitions for this keypad
#endif #endif
/* here is a global api struct pointer. while not strictly necessary, /* 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 * it's nice not to have to pass the api pointer in all function calls
in the plugin */ * in the plugin
*/
static struct plugin_api *rb; static struct plugin_api *rb;
extern const fb_data minesweeper_tiles[];
/* define how numbers are displayed (that way we don't have to */ #ifdef HAVE_LCD_COLOR
/* worry about fonts) */ # if ( LCD_HEIGHT * LCD_WIDTH ) / ( 16 * 16 ) >= 130
static unsigned char num[10][8] = { /* We want to have at least 130 tiles on the screen */
/*reading the sprites: # define TileSize 16
on screen f123 # else
4567 # define TileSize 12
890a # endif
bcde # define BackgroundColor LCD_RGBPACK( 128, 128, 128 )
#elif LCD_DEPTH > 1
# define TileSize 12
#else
# define TileSize 8
#endif
in binary b84f #define Mine 9
c951 #define Flag 10
d062 #define Unknown 11
ea73 #define ExplodedMine 12
*/
/* 0 */ #define draw_tile( num, x, y ) \
{0x00, /* ........ */ rb->lcd_bitmap_part( minesweeper_tiles, 0, num * TileSize, \
0x00, /* ........ */ TileSize, left+x*TileSize, top+y*TileSize, \
0x00, /* ........ */ TileSize, TileSize )
0x00, /* ........ */
0x00, /* ........ */ #define invert_tile( x, y ) \
0x00, /* ........ */ rb->lcd_set_drawmode(DRMODE_COMPLEMENT); \
0x00, /* ........ */ rb->lcd_fillrect( left+x*TileSize, top+y*TileSize, TileSize, TileSize ); \
0x00},/* ........ */ rb->lcd_set_drawmode(DRMODE_SOLID);
/* 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 /* the tile struct
if there is a mine, mine is true * if there is a mine, mine is true
if tile is known by player, known is true * if tile is known by player, known is true
if tile has a flag, flag is true * if tile has a flag, flag is true
neighbors is the total number of mines arround tile * neighbors is the total number of mines arround tile
*/ */
typedef struct tile { typedef struct tile
{
unsigned char mine : 1; unsigned char mine : 1;
unsigned char known : 1; unsigned char known : 1;
unsigned char flag : 1; unsigned char flag : 1;
@ -248,11 +173,15 @@ typedef struct tile {
} tile; } tile;
/* the height and width of the field */ /* the height and width of the field */
int height = LCD_HEIGHT/8; #define MAX_HEIGHT (LCD_HEIGHT/TileSize)
int width = LCD_WIDTH/8; #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. */ /* The Minefield. Caution it is defined as Y, X! Not the opposite. */
tile minefield[LCD_HEIGHT/8][LCD_WIDTH/8]; tile minefield[MAX_HEIGHT][MAX_WIDTH];
/* total number of mines on the game */ /* total number of mines on the game */
int mine_num = 0; int mine_num = 0;
@ -269,46 +198,39 @@ bool no_mines = true;
/* We need a stack (created on discover()) for the cascade algorithm. */ /* We need a stack (created on discover()) for the cascade algorithm. */
int stack_pos = 0; int stack_pos = 0;
/* Functions to center the board on screen. */ /* a usefull string for snprintf */
int c_height(void){ char str[30];
return LCD_HEIGHT/16 - height/2;
}
int c_width(void){
return LCD_WIDTH/16 - width/2;
}
void push (int *stack, int y, int x){ void push( int *stack, int y, int x )
{
if(stack_pos <= height*width){ if( stack_pos <= height*width )
stack_pos++; {
stack[stack_pos] = y; stack[++stack_pos] = y;
stack_pos++; stack[++stack_pos] = x;
stack[stack_pos] = x;
} }
} }
/* Unveil tiles and push them to stack if they are empty. */ /* Unveil tiles and push them to stack if they are empty. */
void unveil(int *stack, int y, int x){ void unveil( int *stack, int y, int x )
{
if(x < c_width() || y < c_height() || x > c_width() + width-1 if( x < 0 || y < 0 || x > width - 1 || y > height - 1
|| y > c_height() + height-1 || minefield[y][x].known || minefield[y][x].known
|| minefield[y][x].mine || minefield[y][x].flag ) return; || minefield[y][x].mine || minefield[y][x].flag ) return;
if(minefield[y][x].neighbors == 0){
minefield[y][x].known = 1; minefield[y][x].known = 1;
if( minefield[y][x].neighbors == 0 )
push( stack, y, x ); push( stack, y, x );
} else
minefield[y][x].known = 1;
} }
void discover(int y, int x){ void discover( int y, int x )
{
int stack[height*width]; int stack[height*width];
/* Selected tile. */ /* Selected tile. */
if(x < c_width() || y < c_height() || x > c_width() + width-1 if( x < 0 || y < 0 || x > width - 1 || y > height - 1
|| y > c_height() + height-1 || minefield[y][x].known || minefield[y][x].known
|| minefield[y][x].mine || minefield[y][x].flag ) return; || minefield[y][x].mine || minefield[y][x].flag ) return;
minefield[y][x].known = 1; minefield[y][x].known = 1;
@ -318,16 +240,14 @@ void discover(int y, int x){
push( stack, y, x ); push( stack, y, x );
/* Scan all nearby tiles. If we meet a tile with a number we just unveil /* 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 * 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) */ * location in stack we do the same thing. (scan again all nearby tiles)
while(stack_pos){ */
/* Retrieve x, y from stack. */ while( stack_pos )
x = stack[stack_pos]; {
y = stack[stack_pos-1]; /* Pop x, y from stack. */
x = stack[stack_pos--];
/* Pop. */ y = stack[stack_pos--];
if(stack_pos > 0) stack_pos -= 2;
else rb->splash(HZ,true,"ERROR");
unveil( stack, y-1, x-1 ); unveil( stack, y-1, x-1 );
unveil( stack, y-1, x ); unveil( stack, y-1, x );
@ -341,11 +261,14 @@ void discover(int y, int x){
} }
/* Reset the whole board for a new game. */ /* Reset the whole board for a new game. */
void minesweeper_init(void){ void minesweeper_init( void )
{
int i,j; int i,j;
for(i=0;i<LCD_HEIGHT/8;i++){ for( i = 0; i < MAX_HEIGHT; i++ )
for(j=0;j<LCD_WIDTH/8;j++){ {
for( j = 0; j < MAX_WIDTH; j++ )
{
minefield[i][j].known = 0; minefield[i][j].known = 0;
minefield[i][j].flag = 0; minefield[i][j].flag = 0;
minefield[i][j].mine = 0; minefield[i][j].mine = 0;
@ -360,16 +283,22 @@ void minesweeper_init(void){
/* put mines on the mine field */ /* put mines on the mine field */
/* there is p% chance that a tile is a mine */ /* there is p% chance that a tile is a mine */
/* if the tile has coordinates (x,y), then it can't be 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){ void minesweeper_putmines( int p, int x, int y )
{
int i,j; int i,j;
mine_num = 0; mine_num = 0;
for(i=c_height();i<c_height() + height;i++){ for( i = 0; i < height; i++ )
for(j=c_width();j<c_width() + width;j++){ {
if(rb->rand()%100<p && !(y==i && x==j)){ for( j = 0; j < width; j++ )
{
if( rb->rand()%100 < p && !( y==i && x==j ) )
{
minefield[i][j].mine = 1; minefield[i][j].mine = 1;
mine_num++; mine_num++;
} else { }
else
{
minefield[i][j].mine = 0; minefield[i][j].mine = 0;
} }
minefield[i][j].neighbors = 0; minefield[i][j].neighbors = 0;
@ -377,59 +306,66 @@ void minesweeper_putmines(int p, int x, int y){
} }
/* we need to compute the neighbor element for each tile */ /* we need to compute the neighbor element for each tile */
for(i=c_height();i<c_height() + height;i++){ for( i = 0; i < height; i++ )
for(j=c_width();j<c_width() + width;j++){ {
if(i>0){ for( j = 0; j < width; j++ )
{
if( i > 0 )
{
if( j > 0 ) if( j > 0 )
minefield[i][j].neighbors += minefield[i-1][j-1].mine; minefield[i][j].neighbors += minefield[i-1][j-1].mine;
minefield[i][j].neighbors += minefield[i-1][j].mine; minefield[i][j].neighbors += minefield[i-1][j].mine;
if(j<c_width() + width-1) if( j < width - 1 )
minefield[i][j].neighbors += minefield[i-1][j+1].mine; minefield[i][j].neighbors += minefield[i-1][j+1].mine;
} }
if( j > 0 ) if( j > 0 )
minefield[i][j].neighbors += minefield[i][j-1].mine; minefield[i][j].neighbors += minefield[i][j-1].mine;
if(j<c_width() + width-1) if( j < width - 1 )
minefield[i][j].neighbors += minefield[i][j+1].mine; minefield[i][j].neighbors += minefield[i][j+1].mine;
if(i<c_height() + height-1){ if( i < height - 1 )
{
if( j > 0 ) if( j > 0 )
minefield[i][j].neighbors += minefield[i+1][j-1].mine; minefield[i][j].neighbors += minefield[i+1][j-1].mine;
minefield[i][j].neighbors += minefield[i+1][j].mine; minefield[i][j].neighbors += minefield[i+1][j].mine;
if(j<c_width() + width-1) if( j < width - 1 )
minefield[i][j].neighbors += minefield[i+1][j+1].mine; minefield[i][j].neighbors += minefield[i+1][j+1].mine;
} }
} }
} }
no_mines = false; no_mines = false;
/* In case the user is lucky and there are no mines positioned. */ /* In case the user is lucky and there are no mines positioned. */
if(!mine_num && height*width != 1) minesweeper_putmines(p, x, y); 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. /* 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. */ can easily be expanded, (just a call assigned to a button) as a solver. */
void mine_show(void){ void mine_show( void )
{
int i, j, button; int i, j, button;
for(i=c_height();i<c_height() + height;i++){ for( i = 0; i < height; i++ )
for(j=c_width();j<c_width() + width;j++){ {
#if LCD_DEPTH > 1 for( j = 0; j < width; j++ )
rb->lcd_set_foreground(LCD_DARKGRAY); {
rb->lcd_drawrect(j*8,i*8,8,8); if( minefield[i][j].mine )
rb->lcd_set_foreground(LCD_BLACK); {
#else if( minefield[i][j].known )
rb->lcd_drawrect(j*8,i*8,8,8); {
#endif draw_tile( ExplodedMine, j, i );
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);
} }
else
{
draw_tile( Mine, j, i );
}
}
else
{
draw_tile( minefield[i][j].neighbors, j, i );
} }
} }
} }
@ -437,26 +373,32 @@ void mine_show(void){
do do
button = rb->button_get(true); button = rb->button_get(true);
while ((button == BUTTON_NONE) || (button & (BUTTON_REL|BUTTON_REPEAT))); while( ( button == BUTTON_NONE )
|| ( button & (BUTTON_REL|BUTTON_REPEAT) ) );
} }
int count_tiles_left( void )
/* the big and ugly function that is the game */
int minesweeper(void)
{ {
int tiles_left = 0;
int i, j; int i, j;
int button; for( i = 0; i < height; i++ )
int lastbutton = BUTTON_NONE; for( j = 0; j < width; j++ )
if( minefield[i][j].known == 0 )
/* the cursor coordinates */ tiles_left++;
int x=0, y=0; return tiles_left;
}
/* a usefull string for snprintf */
char str[30];
/* welcome screen where player can chose mine percentage */ /* welcome screen where player can chose mine percentage */
i = 0; enum minesweeper_status menu( void )
while(true){ {
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_clear_display();
rb->lcd_puts( 0, 0, "Mine Sweeper" ); rb->lcd_puts( 0, 0, "Mine Sweeper" );
@ -467,60 +409,61 @@ int minesweeper(void)
rb->snprintf( str, 20, "%d cols x %d rows", width, height ); rb->snprintf( str, 20, "%d cols x %d rows", width, height );
rb->lcd_puts( 0, 4, str ); rb->lcd_puts( 0, 4, str );
rb->lcd_puts( 0, 5, "left x right" ); rb->lcd_puts( 0, 5, "left x right" );
rb->lcd_puts( 0, 6,
#if CONFIG_KEYPAD == RECORDER_PAD #if CONFIG_KEYPAD == RECORDER_PAD
rb->lcd_puts(0,6,"ON to start"); "ON to start"
#elif CONFIG_KEYPAD == ONDIO_PAD #elif CONFIG_KEYPAD == ONDIO_PAD
rb->lcd_puts(0,6,"MODE to start"); "MODE to start"
#elif (CONFIG_KEYPAD==IRIVER_H100_PAD) || (CONFIG_KEYPAD==IPOD_4G_PAD) #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) \
rb->lcd_puts(0,6,"SELECT to start"); || (CONFIG_KEYPAD == IRIVER_H300_PAD ) \
|| (CONFIG_KEYPAD == IPOD_4G_PAD)
"SELECT to start"
#elif CONFIG_KEYPAD == IAUDIO_X5_PAD #elif CONFIG_KEYPAD == IAUDIO_X5_PAD
rb->lcd_puts(0,6,"REC to start"); "REC to start"
#else
""
# warning Please define help string for this keypad.
#endif #endif
);
rb->lcd_update(); rb->lcd_update();
button = rb->button_get(true); switch( button = rb->button_get( true ) )
switch(button){ {
case MINESWP_DOWN: case MINESWP_DOWN:
case (MINESWP_DOWN | BUTTON_REPEAT): case MINESWP_DOWN|BUTTON_REPEAT:
p = (p + 98)%100; p = (p + 94)%98 + 2;
/* Don't let the user play without mines. */
if(!p) p = 98;
break; break;
case MINESWP_UP: case MINESWP_UP:
case (MINESWP_UP | BUTTON_REPEAT): case MINESWP_UP|BUTTON_REPEAT:
p = (p + 2)%100; p = p%98 + 2;
/* Don't let the user play without mines. */
if(!p) p = 2;
break; break;
case BUTTON_RIGHT: case BUTTON_RIGHT:
case (BUTTON_RIGHT | BUTTON_REPEAT): case BUTTON_RIGHT|BUTTON_REPEAT:
height = height%(LCD_HEIGHT/8)+1; height = height%MAX_HEIGHT + 1;
break; break;
case BUTTON_LEFT: case BUTTON_LEFT:
case (BUTTON_LEFT | BUTTON_REPEAT): case BUTTON_LEFT|BUTTON_REPEAT:
width = width%(LCD_WIDTH/8)+1; width = width%MAX_WIDTH + 1;
break; break;
case MINESWP_RIGHT: case MINESWP_RIGHT:
case (MINESWP_RIGHT | BUTTON_REPEAT): case MINESWP_RIGHT|BUTTON_REPEAT:
height--; height--;
if(height < 1) height = LCD_HEIGHT/8; if( height < 1 ) height = MAX_HEIGHT;
if(height > LCD_HEIGHT) height = 1;
break; break;
case MINESWP_LEFT: case MINESWP_LEFT:
case (MINESWP_LEFT | BUTTON_REPEAT): case MINESWP_LEFT|BUTTON_REPEAT:
width--; width--;
if(width < 1) width = LCD_WIDTH/8; if( width < 1 ) width = MAX_WIDTH;
if(width > LCD_WIDTH) width = 1;
break; break;
case MINESWP_START:/* start playing */ case MINESWP_START:/* start playing */
i = 1; return MINESWEEPER_WIN;
break;
#ifdef MINESWP_RC_QUIT #ifdef MINESWP_RC_QUIT
case MINESWP_RC_QUIT: case MINESWP_RC_QUIT:
#endif #endif
@ -532,70 +475,75 @@ int minesweeper(void)
return MINESWEEPER_USB; return MINESWEEPER_USB;
break; break;
} }
if(i==1) }
break;
} }
/* the big and ugly game function */
enum minesweeper_status minesweeper( void )
{
int i, j;
int button;
int lastbutton = BUTTON_NONE;
/******************** /* the cursor coordinates */
* init * 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(); minesweeper_init();
x = c_width(); x = 0;
y = c_height(); y = 0;
/********************** /**
* play * * Play
**********************/ */
while( true )
while(true){ {
/* clear the screen buffer */ /* clear the screen buffer */
#ifdef HAVE_LCD_COLOR
rb->lcd_set_background( BackgroundColor );
#endif
rb->lcd_clear_display(); rb->lcd_clear_display();
/* display the mine field */ /* display the mine field */
for(i=c_height();i<c_height() + height;i++){ for( i = 0; i < height; i++ )
for(j=c_width();j<c_width() + width;j++){ {
#if LCD_DEPTH > 1 for( j = 0; j < width; j++ )
rb->lcd_set_foreground(LCD_DARKGRAY); {
rb->lcd_drawrect(j*8,i*8,8,8); if( minefield[i][j].known )
rb->lcd_set_foreground(LCD_BLACK); {
#else draw_tile( minefield[i][j].neighbors, j, i );
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) { 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); draw_tile( Flag, j, i );
} else { }
#if LCD_DEPTH > 1 else
rb->lcd_set_foreground(LCD_LIGHTGRAY); {
rb->lcd_fillrect(j*8+1,i*8+1,6,6); draw_tile( Unknown, j, i );
rb->lcd_set_foreground(LCD_BLACK);
#else
rb->lcd_fillrect(j*8+2,i*8+2,4,4);
#endif
} }
} }
} }
/* display the cursor */ /* display the cursor */
rb->lcd_set_drawmode(DRMODE_COMPLEMENT); invert_tile( x, y );
rb->lcd_fillrect(x*8,y*8,8,8);
rb->lcd_set_drawmode(DRMODE_SOLID);
/* update the screen */ /* update the screen */
rb->lcd_update(); rb->lcd_update();
button = rb->button_get(true); switch( button = rb->button_get( true ) )
switch(button){ {
/* quit minesweeper (you really shouldn't use this button ...) */ /* quit minesweeper (you really shouldn't use this button ...) */
#ifdef MINESWP_RC_QUIT #ifdef MINESWP_RC_QUIT
case MINESWP_RC_QUIT: case MINESWP_RC_QUIT:
@ -605,30 +553,26 @@ int minesweeper(void)
/* move cursor left */ /* move cursor left */
case BUTTON_LEFT: case BUTTON_LEFT:
case (BUTTON_LEFT | BUTTON_REPEAT): case BUTTON_LEFT|BUTTON_REPEAT:
if(x<=c_width()) x = width + c_width(); x = ( x + width - 1 )%width;
x = x-1;
break; break;
/* move cursor right */ /* move cursor right */
case BUTTON_RIGHT: case BUTTON_RIGHT:
case (BUTTON_RIGHT | BUTTON_REPEAT): case BUTTON_RIGHT|BUTTON_REPEAT:
if(x>=width + c_width() - 1) x = c_width() - 1; x = ( x + 1 )%width;
x = x+1;
break; break;
/* move cursor down */ /* move cursor down */
case MINESWP_DOWN: case MINESWP_DOWN:
case (MINESWP_DOWN | BUTTON_REPEAT): case MINESWP_DOWN|BUTTON_REPEAT:
if(y>=height + c_height() - 1) y = c_height() - 1; y = ( y + 1 )%height;
y = y+1;
break; break;
/* move cursor up */ /* move cursor up */
case MINESWP_UP: case MINESWP_UP:
case (MINESWP_UP | BUTTON_REPEAT): case MINESWP_UP|BUTTON_REPEAT:
if(y<=c_height()) y = height + c_height(); y = ( y + height - 1 )%height;
y = y-1;
break; break;
/* discover a tile (and it's neighbors if .neighbors == 0) */ /* discover a tile (and it's neighbors if .neighbors == 0) */
@ -637,23 +581,21 @@ int minesweeper(void)
case MINESWP_DISCOVER2: case MINESWP_DISCOVER2:
#endif #endif
if( minefield[y][x].flag ) break; if( minefield[y][x].flag ) break;
/* we put the mines on the first "click" so that you don't */ /* we put the mines on the first "click" so that you don't
/* lose on the first "click" */ * lose on the first "click" */
if( tiles_left == width*height && no_mines ) if( tiles_left == width*height && no_mines )
minesweeper_putmines(p,x,y); minesweeper_putmines(p,x,y);
discover(y, x); discover(y, x);
if(minefield[y][x].mine){ if( minefield[y][x].mine )
{
minefield[y][x].known = 1;
return MINESWEEPER_LOSE; return MINESWEEPER_LOSE;
} }
tiles_left = 0; tiles_left = count_tiles_left();
for(i=c_height();i<c_height() + height;i++){ if( tiles_left == mine_num )
for(j=c_width();j<c_width() + width;j++){ {
if(minefield[i][j].known == 0) tiles_left++;
}
}
if(tiles_left == mine_num){
return MINESWEEPER_WIN; return MINESWEEPER_WIN;
} }
break; break;
@ -670,17 +612,12 @@ int minesweeper(void)
minefield[y][x].flag = ( minefield[y][x].flag + 1 )%2; minefield[y][x].flag = ( minefield[y][x].flag + 1 )%2;
break; break;
/* show how many mines you think you have found and how many */ /* show how many mines you think you have found and how many
/* there really are on the game */ * there really are on the game */
case MINESWP_INFO: case MINESWP_INFO:
if(no_mines) break; if( no_mines )
tiles_left = 0; break;
for(i=c_height();i<c_height() + height;i++){ tiles_left = count_tiles_left();
for(j=c_width();j<c_width() + width;j++){
if(minefield[i][j].flag && !minefield[i][j].known)
tiles_left++;
}
}
rb->splash( HZ*2, true, "You found %d mines out of %d", rb->splash( HZ*2, true, "You found %d mines out of %d",
tiles_left, mine_num ); tiles_left, mine_num );
break; break;
@ -700,21 +637,22 @@ int minesweeper(void)
enum plugin_status plugin_start(struct plugin_api* api, void* parameter) enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
{ {
bool exit = false; bool exit = false;
/* plugin init */
(void)parameter; (void)parameter;
rb = api; rb = api;
/* end of plugin init */
while(!exit) { while( !exit )
switch(minesweeper()){ {
switch( minesweeper() )
{
case MINESWEEPER_WIN: case MINESWEEPER_WIN:
rb->splash(HZ*2, true, "You Win! Press a key"); rb->splash( HZ, true, "You Win!" );
rb->lcd_clear_display(); rb->lcd_clear_display();
mine_show(); mine_show();
break; break;
case MINESWEEPER_LOSE: case MINESWEEPER_LOSE:
rb->splash(HZ*2, true, "You Lose! Press a key"); rb->splash( HZ, true, "You Lose!" );
rb->lcd_clear_display(); rb->lcd_clear_display();
mine_show(); mine_show();
break; break;