1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2004-2006 Antoine Cellerier <dionoea -at- videolan -dot- org>
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
24 #ifdef HAVE_LCD_BITMAP
26 #include "lib/playback_control.h"
30 /* what the minesweeper() function can return */
31 enum minesweeper_status
{
38 /* variable button definitions */
39 #if CONFIG_KEYPAD == RECORDER_PAD
40 # define MINESWP_LEFT BUTTON_LEFT
41 # define MINESWP_RIGHT BUTTON_RIGHT
42 # define MINESWP_UP BUTTON_UP
43 # define MINESWP_DOWN BUTTON_DOWN
44 # define MINESWP_QUIT BUTTON_OFF
45 # define MINESWP_TOGGLE BUTTON_ON
46 # define MINESWP_TOGGLE2 BUTTON_F1
47 # define MINESWP_DISCOVER BUTTON_PLAY
48 # define MINESWP_DISCOVER2 BUTTON_F2
49 # define MINESWP_INFO BUTTON_F3
51 #elif CONFIG_KEYPAD == ARCHOS_AV300_PAD
52 # define MINESWP_LEFT BUTTON_LEFT
53 # define MINESWP_RIGHT BUTTON_RIGHT
54 # define MINESWP_UP BUTTON_UP
55 # define MINESWP_DOWN BUTTON_DOWN
56 # define MINESWP_QUIT BUTTON_OFF
57 # define MINESWP_TOGGLE BUTTON_ON
58 # define MINESWP_TOGGLE2 BUTTON_F1
59 # define MINESWP_DISCOVER BUTTON_SELECT
60 # define MINESWP_DISCOVER2 BUTTON_F2
61 # define MINESWP_INFO BUTTON_F3
63 #elif CONFIG_KEYPAD == ONDIO_PAD
64 # define MINESWP_LEFT BUTTON_LEFT
65 # define MINESWP_RIGHT BUTTON_RIGHT
66 # define MINESWP_UP BUTTON_UP
67 # define MINESWP_DOWN BUTTON_DOWN
68 # define MINESWP_QUIT BUTTON_OFF
69 # define MINESWP_TOGGLE_PRE BUTTON_MENU
70 # define MINESWP_TOGGLE (BUTTON_MENU | BUTTON_REL)
71 # define MINESWP_DISCOVER (BUTTON_MENU | BUTTON_REPEAT)
72 # define MINESWP_INFO (BUTTON_MENU | BUTTON_OFF)
74 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
75 (CONFIG_KEYPAD == IRIVER_H300_PAD)
76 # define MINESWP_LEFT BUTTON_LEFT
77 # define MINESWP_RIGHT BUTTON_RIGHT
78 # define MINESWP_UP BUTTON_UP
79 # define MINESWP_DOWN BUTTON_DOWN
80 # define MINESWP_QUIT BUTTON_OFF
81 # define MINESWP_TOGGLE BUTTON_ON
82 # define MINESWP_TOGGLE2 BUTTON_REC
83 # define MINESWP_DISCOVER BUTTON_SELECT
84 # define MINESWP_INFO BUTTON_MODE
86 # define MINESWP_RC_QUIT BUTTON_RC_STOP
88 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
89 (CONFIG_KEYPAD == IPOD_3G_PAD) || \
90 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
91 # define MINESWP_SCROLLWHEEL
92 # define MINESWP_LEFT BUTTON_LEFT
93 # define MINESWP_RIGHT BUTTON_RIGHT
94 # define MINESWP_UP BUTTON_MENU
95 # define MINESWP_DOWN BUTTON_PLAY
96 # define MINESWP_NEXT BUTTON_SCROLL_FWD
97 # define MINESWP_PREV BUTTON_SCROLL_BACK
98 # define MINESWP_QUIT (BUTTON_SELECT | BUTTON_MENU)
99 # define MINESWP_TOGGLE_PRE BUTTON_SELECT
100 # define MINESWP_TOGGLE (BUTTON_SELECT | BUTTON_REL)
101 # define MINESWP_DISCOVER (BUTTON_SELECT | BUTTON_REPEAT)
102 # define MINESWP_INFO (BUTTON_SELECT | BUTTON_PLAY)
104 #elif (CONFIG_KEYPAD == IAUDIO_X5M5_PAD)
105 # define MINESWP_LEFT BUTTON_LEFT
106 # define MINESWP_RIGHT BUTTON_RIGHT
107 # define MINESWP_UP BUTTON_UP
108 # define MINESWP_DOWN BUTTON_DOWN
109 # define MINESWP_QUIT BUTTON_POWER
110 # define MINESWP_TOGGLE BUTTON_PLAY
111 # define MINESWP_DISCOVER BUTTON_SELECT
112 # define MINESWP_INFO BUTTON_REC
114 #elif (CONFIG_KEYPAD == GIGABEAT_PAD)
115 # define MINESWP_LEFT BUTTON_LEFT
116 # define MINESWP_RIGHT BUTTON_RIGHT
117 # define MINESWP_UP BUTTON_UP
118 # define MINESWP_DOWN BUTTON_DOWN
119 # define MINESWP_QUIT BUTTON_POWER
120 # define MINESWP_TOGGLE BUTTON_A
121 # define MINESWP_DISCOVER BUTTON_SELECT
122 # define MINESWP_INFO BUTTON_MENU
124 #elif (CONFIG_KEYPAD == SANSA_E200_PAD)
126 # define MINESWP_SCROLLWHEEL
127 # define MINESWP_LEFT BUTTON_LEFT
128 # define MINESWP_RIGHT BUTTON_RIGHT
129 # define MINESWP_UP BUTTON_UP
130 # define MINESWP_DOWN BUTTON_DOWN
131 # define MINESWP_QUIT BUTTON_POWER
132 # define MINESWP_NEXT BUTTON_SCROLL_FWD
133 # define MINESWP_PREV BUTTON_SCROLL_BACK
134 # define MINESWP_TOGGLE BUTTON_REC
135 # define MINESWP_DISCOVER BUTTON_SELECT
136 # define MINESWP_INFO (BUTTON_REC|BUTTON_REPEAT)
138 #elif (CONFIG_KEYPAD == SANSA_FUZE_PAD)
140 # define MINESWP_LEFT BUTTON_LEFT
141 # define MINESWP_RIGHT BUTTON_RIGHT
142 # define MINESWP_UP BUTTON_UP
143 # define MINESWP_DOWN BUTTON_DOWN
144 # define MINESWP_QUIT (BUTTON_HOME|BUTTON_REPEAT)
145 # define MINESWP_TOGGLE BUTTON_SCROLL_FWD
146 # define MINESWP_DISCOVER BUTTON_SELECT
147 # define MINESWP_INFO BUTTON_SCROLL_BACK
149 #elif (CONFIG_KEYPAD == SANSA_C200_PAD) || \
150 (CONFIG_KEYPAD == SANSA_CLIP_PAD) || \
151 (CONFIG_KEYPAD == SANSA_M200_PAD)
152 # define MINESWP_LEFT BUTTON_LEFT
153 # define MINESWP_RIGHT BUTTON_RIGHT
154 # define MINESWP_UP BUTTON_UP
155 # define MINESWP_DOWN BUTTON_DOWN
156 # define MINESWP_QUIT BUTTON_POWER
157 # define MINESWP_TOGGLE_PRE BUTTON_SELECT
158 # define MINESWP_TOGGLE (BUTTON_SELECT | BUTTON_REL)
159 # define MINESWP_TOGGLE2 BUTTON_VOL_DOWN
160 # define MINESWP_DISCOVER (BUTTON_SELECT | BUTTON_REPEAT)
161 # define MINESWP_DISCOVER2 BUTTON_VOL_UP
162 # define MINESWP_INFO (BUTTON_SELECT | BUTTON_UP)
164 #elif (CONFIG_KEYPAD == IRIVER_H10_PAD)
165 # define MINESWP_LEFT BUTTON_LEFT
166 # define MINESWP_RIGHT BUTTON_RIGHT
167 # define MINESWP_UP BUTTON_SCROLL_UP
168 # define MINESWP_DOWN BUTTON_SCROLL_DOWN
169 # define MINESWP_QUIT BUTTON_POWER
170 # define MINESWP_TOGGLE BUTTON_PLAY
171 # define MINESWP_DISCOVER BUTTON_REW
172 # define MINESWP_INFO (BUTTON_REW | BUTTON_PLAY)
174 #elif (CONFIG_KEYPAD == GIGABEAT_S_PAD)
175 # define MINESWP_LEFT BUTTON_LEFT
176 # define MINESWP_RIGHT BUTTON_RIGHT
177 # define MINESWP_UP BUTTON_UP
178 # define MINESWP_DOWN BUTTON_DOWN
179 # define MINESWP_QUIT BUTTON_BACK
180 # define MINESWP_TOGGLE BUTTON_PLAY
181 # define MINESWP_DISCOVER BUTTON_SELECT
182 # define MINESWP_INFO BUTTON_MENU
184 #elif (CONFIG_KEYPAD == MROBE100_PAD)
185 # define MINESWP_LEFT BUTTON_LEFT
186 # define MINESWP_RIGHT BUTTON_RIGHT
187 # define MINESWP_UP BUTTON_UP
188 # define MINESWP_DOWN BUTTON_DOWN
189 # define MINESWP_QUIT BUTTON_POWER
190 # define MINESWP_TOGGLE BUTTON_DISPLAY
191 # define MINESWP_DISCOVER BUTTON_SELECT
192 # define MINESWP_INFO BUTTON_MENU
194 #elif CONFIG_KEYPAD == IAUDIO_M3_PAD
195 # define MINESWP_LEFT BUTTON_RC_REW
196 # define MINESWP_RIGHT BUTTON_RC_FF
197 # define MINESWP_UP BUTTON_RC_VOL_UP
198 # define MINESWP_DOWN BUTTON_RC_VOL_DOWN
199 # define MINESWP_QUIT BUTTON_RC_REC
200 # define MINESWP_TOGGLE BUTTON_RC_MODE
201 # define MINESWP_DISCOVER BUTTON_RC_PLAY
202 # define MINESWP_INFO BUTTON_RC_MENU
204 #elif (CONFIG_KEYPAD == COWON_D2_PAD)
205 # define MINESWP_QUIT BUTTON_POWER
207 #elif CONFIG_KEYPAD == CREATIVEZVM_PAD
208 # define MINESWP_LEFT BUTTON_LEFT
209 # define MINESWP_RIGHT BUTTON_RIGHT
210 # define MINESWP_UP BUTTON_UP
211 # define MINESWP_DOWN BUTTON_DOWN
212 # define MINESWP_QUIT BUTTON_BACK
213 # define MINESWP_TOGGLE BUTTON_SELECT
214 # define MINESWP_DISCOVER BUTTON_PLAY
215 # define MINESWP_INFO BUTTON_MENU
217 #elif CONFIG_KEYPAD == PHILIPS_HDD1630_PAD
218 # define MINESWP_LEFT BUTTON_LEFT
219 # define MINESWP_RIGHT BUTTON_RIGHT
220 # define MINESWP_UP BUTTON_UP
221 # define MINESWP_DOWN BUTTON_DOWN
222 # define MINESWP_QUIT BUTTON_POWER
223 # define MINESWP_TOGGLE BUTTON_VIEW
224 # define MINESWP_DISCOVER BUTTON_SELECT
225 # define MINESWP_INFO BUTTON_MENU
227 #elif CONFIG_KEYPAD == PHILIPS_SA9200_PAD
228 # define MINESWP_LEFT BUTTON_PREV
229 # define MINESWP_RIGHT BUTTON_NEXT
230 # define MINESWP_UP BUTTON_UP
231 # define MINESWP_DOWN BUTTON_DOWN
232 # define MINESWP_QUIT BUTTON_POWER
233 # define MINESWP_TOGGLE BUTTON_RIGHT
234 # define MINESWP_DISCOVER BUTTON_PLAY
235 # define MINESWP_INFO BUTTON_MENU
237 #elif (CONFIG_KEYPAD == ONDAVX747_PAD) || \
238 CONFIG_KEYPAD == ONDAVX777_PAD || \
239 CONFIG_KEYPAD == MROBE500_PAD
240 # define MINESWP_QUIT BUTTON_POWER
242 #elif (CONFIG_KEYPAD == SAMSUNG_YH_PAD)
243 # define MINESWP_LEFT BUTTON_LEFT
244 # define MINESWP_RIGHT BUTTON_RIGHT
245 # define MINESWP_UP BUTTON_UP
246 # define MINESWP_DOWN BUTTON_DOWN
247 # define MINESWP_QUIT BUTTON_REC
248 # define MINESWP_TOGGLE BUTTON_PLAY
249 # define MINESWP_DISCOVER BUTTON_REW
250 # define MINESWP_INFO BUTTON_FFWD
252 #elif (CONFIG_KEYPAD == PBELL_VIBE500_PAD)
253 # define MINESWP_LEFT BUTTON_PREV
254 # define MINESWP_RIGHT BUTTON_NEXT
255 # define MINESWP_UP BUTTON_UP
256 # define MINESWP_DOWN BUTTON_DOWN
257 # define MINESWP_QUIT BUTTON_REC
258 # define MINESWP_TOGGLE BUTTON_PLAY
259 # define MINESWP_DISCOVER BUTTON_OK
260 # define MINESWP_INFO BUTTON_MENU
262 #elif CONFIG_KEYPAD == MPIO_HD200_PAD
263 # define MINESWP_LEFT BUTTON_VOL_DOWN
264 # define MINESWP_RIGHT BUTTON_VOL_UP
265 # define MINESWP_UP BUTTON_PREV
266 # define MINESWP_DOWN BUTTON_NEXT
267 # define MINESWP_QUIT (BUTTON_REC|BUTTON_PLAY)
268 # define MINESWP_TOGGLE BUTTON_PLAY
269 # define MINESWP_DISCOVER BUTTON_SELECT
270 # define MINESWP_INFO BUTTON_REC
273 #error No keymap defined!
276 #ifdef HAVE_TOUCHSCREEN
278 # define MINESWP_QUIT BUTTON_TOPLEFT
281 # define MINESWP_LEFT BUTTON_MIDLEFT
283 #ifndef MINESWP_RIGHT
284 # define MINESWP_RIGHT BUTTON_MIDRIGHT
287 # define MINESWP_UP BUTTON_TOPMIDDLE
290 # define MINESWP_DOWN BUTTON_BOTTOMMIDDLE
292 #ifndef MINESWP_TOGGLE
293 # define MINESWP_TOGGLE BUTTON_CENTER
295 #ifndef MINESWP_DISCOVER
296 # define MINESWP_DISCOVER BUTTON_BOTTOMLEFT
299 # define MINESWP_INFO BUTTON_BOTTOMRIGHT
303 extern const fb_data minesweeper_tiles
[];
305 #ifdef HAVE_LCD_COLOR
306 # if ( LCD_HEIGHT * LCD_WIDTH ) / ( 16 * 16 ) >= 130
307 /* We want to have at least 130 tiles on the screen */
309 # elif ( LCD_HEIGHT * LCD_WIDTH ) / ( 12 * 12 ) >= 130
314 # define BackgroundColor LCD_RGBPACK( 128, 128, 128 )
324 #define ExplodedMine 12
326 #define CorrectFlag 14
328 #define draw_tile( num, x, y ) \
329 rb->lcd_bitmap_part( minesweeper_tiles, 0, num * TileSize, \
330 TileSize, left+x*TileSize, top+y*TileSize, \
333 #define invert_tile( x, y ) \
334 rb->lcd_set_drawmode(DRMODE_COMPLEMENT); \
335 rb->lcd_fillrect( left+x*TileSize, top+y*TileSize, TileSize, TileSize ); \
336 rb->lcd_set_drawmode(DRMODE_SOLID);
340 * if there is a mine, mine is true
341 * if tile is known by player, known is true
342 * if tile has a flag, flag is true
343 * neighbors is the total number of mines arround tile
347 unsigned char mine
: 1;
348 unsigned char known
: 1;
349 unsigned char flag
: 1;
350 unsigned char neighbors
: 4;
353 /* the height and width of the field */
354 #define MAX_HEIGHT (LCD_HEIGHT/TileSize)
355 #define MAX_WIDTH (LCD_WIDTH/TileSize)
356 int height
= MAX_HEIGHT
;
357 int width
= MAX_WIDTH
;
361 /* The Minefield. Caution it is defined as Y, X! Not the opposite. */
362 tile minefield
[MAX_HEIGHT
][MAX_WIDTH
];
364 /* total number of mines on the game */
367 /* percentage of mines on minefield used during generation */
370 /* number of tiles left on the game */
373 /* number of used flags on the game */
376 /* Because mines are set after the first move... */
377 bool no_mines
= true;
379 /* We need a stack (created on discover()) for the cascade algorithm. */
382 /* a usefull string for snprintf */
385 #ifdef HAVE_TOUCHSCREEN
387 #include "lib/pluginlib_touchscreen.h"
388 static struct ts_raster mine_raster
= { 0, 0, MAX_WIDTH
, MAX_HEIGHT
, TileSize
, TileSize
};
392 void push( int *stack
, int y
, int x
)
394 if( stack_pos
<= height
*width
)
396 stack
[++stack_pos
] = y
;
397 stack
[++stack_pos
] = x
;
401 /* Unveil tiles and push them to stack if they are empty. */
402 void unveil( int *stack
, int y
, int x
)
404 if( x
< 0 || y
< 0 || x
> width
- 1 || y
> height
- 1
405 || minefield
[y
][x
].known
406 || minefield
[y
][x
].mine
|| minefield
[y
][x
].flag
) return;
408 minefield
[y
][x
].known
= 1;
410 if( minefield
[y
][x
].neighbors
== 0 )
414 int is_flagged( int y
, int x
)
416 if( x
>= 0 && y
>= 0 && x
< width
&& y
< height
&& minefield
[y
][x
].flag
)
421 int neighbors_flagged( int y
, int x
)
423 return is_flagged( y
-1, x
-1 ) +
424 is_flagged( y
-1, x
) +
425 is_flagged( y
-1, x
+1 ) +
426 is_flagged( y
, x
-1 ) +
428 is_flagged( y
, x
+1 ) +
429 is_flagged( y
+1, x
-1 ) +
430 is_flagged( y
+1, x
) +
431 is_flagged( y
+1, x
+1 );
434 bool discover( int y
, int x
, bool explore_neighbors
)
437 if( x
< 0 || y
< 0 || x
> width
- 1 || y
> height
- 1
438 || minefield
[y
][x
].known
439 || minefield
[y
][x
].mine
|| minefield
[y
][x
].flag
)
441 if( !minefield
[y
][x
].flag
&& minefield
[y
][x
].mine
)
444 if( explore_neighbors
&& minefield
[y
][x
].known
&&
445 minefield
[y
][x
].neighbors
== neighbors_flagged( y
, x
) )
447 return discover( y
-1, x
-1, false ) ||
448 discover( y
-1, x
, false ) ||
449 discover( y
-1, x
+1, false ) ||
450 discover( y
, x
-1, false ) ||
451 discover( y
, x
, false ) ||
452 discover( y
, x
+1, false ) ||
453 discover( y
+1, x
-1, false ) ||
454 discover( y
+1, x
, false ) ||
455 discover( y
+1, x
+1, false );
461 minefield
[y
][x
].known
= 1;
462 /* Exit if the tile is not empty. (no mines nearby) */
463 if( minefield
[y
][x
].neighbors
) return false;
465 int stack
[height
*width
];
469 /* Scan all nearby tiles. If we meet a tile with a number we just unveil
470 * it. If we meet an empty tile, we push the location in stack. For each
471 * location in stack we do the same thing. (scan again all nearby tiles)
475 /* Pop x, y from stack. */
476 x
= stack
[stack_pos
--];
477 y
= stack
[stack_pos
--];
479 unveil( stack
, y
-1, x
-1 );
480 unveil( stack
, y
-1, x
);
481 unveil( stack
, y
-1, x
+1 );
482 unveil( stack
, y
, x
+1 );
483 unveil( stack
, y
+1, x
+1 );
484 unveil( stack
, y
+1, x
);
485 unveil( stack
, y
+1, x
-1 );
486 unveil( stack
, y
, x
-1 );
492 /* Reset the whole board for a new game. */
493 void minesweeper_init( void )
497 for( i
= 0; i
< MAX_HEIGHT
; i
++ )
499 for( j
= 0; j
< MAX_WIDTH
; j
++ )
501 minefield
[i
][j
].known
= 0;
502 minefield
[i
][j
].flag
= 0;
503 minefield
[i
][j
].mine
= 0;
504 minefield
[i
][j
].neighbors
= 0;
508 tiles_left
= width
*height
;
512 /* put mines on the mine field */
513 /* there is p% chance that a tile is a mine */
514 /* if the tile has coordinates (x,y), then it can't be a mine */
515 void minesweeper_putmines( int p
, int x
, int y
)
520 for( i
= 0; i
< height
; i
++ )
522 for( j
= 0; j
< width
; j
++ )
524 if( rb
->rand()%100 < p
&& !( y
==i
&& x
==j
) )
526 minefield
[i
][j
].mine
= 1;
531 minefield
[i
][j
].mine
= 0;
533 minefield
[i
][j
].neighbors
= 0;
537 /* we need to compute the neighbor element for each tile */
538 for( i
= 0; i
< height
; i
++ )
540 for( j
= 0; j
< width
; j
++ )
545 minefield
[i
][j
].neighbors
+= minefield
[i
-1][j
-1].mine
;
546 minefield
[i
][j
].neighbors
+= minefield
[i
-1][j
].mine
;
548 minefield
[i
][j
].neighbors
+= minefield
[i
-1][j
+1].mine
;
551 minefield
[i
][j
].neighbors
+= minefield
[i
][j
-1].mine
;
553 minefield
[i
][j
].neighbors
+= minefield
[i
][j
+1].mine
;
557 minefield
[i
][j
].neighbors
+= minefield
[i
+1][j
-1].mine
;
558 minefield
[i
][j
].neighbors
+= minefield
[i
+1][j
].mine
;
560 minefield
[i
][j
].neighbors
+= minefield
[i
+1][j
+1].mine
;
567 /* In case the user is lucky and there are no mines positioned. */
568 if( !mine_num
&& height
*width
!= 1 )
570 minesweeper_putmines(p
, x
, y
);
574 /* A function that will uncover all the board, when the user wins or loses.
575 can easily be expanded, (just a call assigned to a button) as a solver. */
576 void mine_show( void )
580 for( i
= 0; i
< height
; i
++ )
582 for( j
= 0; j
< width
; j
++ )
584 if( minefield
[i
][j
].mine
)
586 if( minefield
[i
][j
].known
)
587 draw_tile( ExplodedMine
, j
, i
);
588 else if( minefield
[i
][j
].flag
)
589 draw_tile( CorrectFlag
, j
, i
);
591 draw_tile( Mine
, j
, i
);
595 if( minefield
[i
][j
].flag
)
596 draw_tile( WrongFlag
, j
, i
);
598 draw_tile( minefield
[i
][j
].neighbors
, j
, i
);
605 button
= rb
->button_get(true);
606 while( ( button
== BUTTON_NONE
)
607 || ( button
& (BUTTON_REL
|BUTTON_REPEAT
) ) );
608 #ifdef HAVE_TOUCHSCREEN
609 button
= BUTTON_NONE
;
613 int count_tiles_left( void )
617 for( i
= 0; i
< height
; i
++ )
618 for( j
= 0; j
< width
; j
++ )
619 if( minefield
[i
][j
].known
== 0 )
624 int count_flags( void )
628 for( i
= 0; i
< height
; i
++ )
629 for( j
= 0; j
< width
; j
++ )
630 if( minefield
[i
][j
].flag
== 1 )
635 /* welcome screen where player can chose mine percentage */
636 enum minesweeper_status
menu( void )
638 int selection
= 0, result
= MINESWEEPER_QUIT
;
639 bool menu_quit
= false;
641 MENUITEM_STRINGLIST( menu
, "Minesweeper Menu", NULL
, "Play Minesweeper",
642 "Mine Percentage", "Number of Rows",
643 "Number of Columns", "Playback Control", "Quit" );
645 #ifdef HAVE_LCD_COLOR
646 rb
->lcd_set_foreground( rb
->global_settings
->fg_color
);
647 rb
->lcd_set_background( rb
->global_settings
->bg_color
);
652 switch( rb
->do_menu( &menu
, &selection
, NULL
, false ) )
655 result
= MINESWEEPER_WIN
; /* start playing */
660 rb
->set_int( "Mine Percentage", "%", UNIT_INT
, &p
, NULL
,
665 rb
->set_int( "Number of Rows", "", UNIT_INT
, &height
, NULL
,
666 1, 1, MAX_HEIGHT
, NULL
);
670 rb
->set_int( "Number of Columns", "", UNIT_INT
, &width
, NULL
,
671 1, 1, MAX_WIDTH
, NULL
);
675 playback_control( NULL
);
679 result
= MINESWEEPER_QUIT
; /* quit program */
688 /* the big and ugly game function */
689 enum minesweeper_status
minesweeper( void )
693 int lastbutton
= BUTTON_NONE
;
695 /* the cursor coordinates */
701 if( ( i
= menu() ) != MINESWEEPER_WIN
) return i
;
706 top
= (LCD_HEIGHT
-height
*TileSize
)/2;
707 left
= (LCD_WIDTH
-width
*TileSize
)/2;
709 #ifdef HAVE_TOUCHSCREEN
710 mine_raster
.tl_x
= left
;
711 mine_raster
.tl_y
= top
;
712 mine_raster
.width
= width
*TileSize
;
713 mine_raster
.height
= height
*TileSize
;
716 rb
->srand( *rb
->current_tick
);
727 /* clear the screen buffer */
728 #ifdef HAVE_LCD_COLOR
729 rb
->lcd_set_background( BackgroundColor
);
731 rb
->lcd_clear_display();
733 /* display the mine field */
734 for( i
= 0; i
< height
; i
++ )
736 for( j
= 0; j
< width
; j
++ )
738 if( minefield
[i
][j
].known
)
740 draw_tile( minefield
[i
][j
].neighbors
, j
, i
);
742 else if(minefield
[i
][j
].flag
)
744 draw_tile( Flag
, j
, i
);
748 draw_tile( Unknown
, j
, i
);
753 /* display the cursor */
756 /* update the screen */
759 button
= rb
->button_get(true);
760 #ifdef HAVE_TOUCHSCREEN
761 if(button
& BUTTON_TOUCHSCREEN
)
763 struct ts_raster_result res
;
764 if(touchscreen_map_raster(&mine_raster
, rb
->button_get_data() >> 16, rb
->button_get_data() & 0xffff, &res
) == 1)
766 button
&= ~BUTTON_TOUCHSCREEN
;
767 lastbutton
&= ~BUTTON_TOUCHSCREEN
;
769 if(button
& BUTTON_REPEAT
&& lastbutton
!= MINESWP_TOGGLE
&& lastbutton
^ BUTTON_REPEAT
)
770 button
= MINESWP_TOGGLE
;
771 else if(button
== BUTTON_REL
&& lastbutton
^ BUTTON_REPEAT
)
772 button
= MINESWP_DISCOVER
;
774 button
|= BUTTON_TOUCHSCREEN
;
783 /* quit minesweeper (you really shouldn't use this button ...) */
784 #ifdef MINESWP_RC_QUIT
785 case MINESWP_RC_QUIT
:
788 return MINESWEEPER_QUIT
;
790 /* move cursor left */
792 case MINESWP_LEFT
|BUTTON_REPEAT
:
793 x
= ( x
+ width
- 1 )%width
;
796 /* move cursor right */
798 case MINESWP_RIGHT
|BUTTON_REPEAT
:
802 /* move cursor down */
804 case MINESWP_DOWN
|BUTTON_REPEAT
:
805 y
= ( y
+ 1 )%height
;
810 case MINESWP_UP
|BUTTON_REPEAT
:
811 y
= ( y
+ height
- 1 )%height
;
814 /*move cursor though the entire field*/
815 #ifdef MINESWP_SCROLLWHEEL
817 case MINESWP_NEXT
|BUTTON_REPEAT
:
818 if (x
== width
-1 ) {
819 y
= ( y
+ 1 )%height
;
825 case MINESWP_PREV
|BUTTON_REPEAT
:
827 y
= ( y
+ height
- 1 )%height
;
829 x
= ( x
+ width
- 1 )%width
;
832 /* discover a tile (and it's neighbors if .neighbors == 0) */
833 case MINESWP_DISCOVER
:
834 #ifdef MINESWP_DISCOVER2
835 case MINESWP_DISCOVER2
:
837 if( minefield
[y
][x
].flag
) break;
838 /* we put the mines on the first "click" so that you don't
839 * lose on the first "click" */
840 if( tiles_left
== width
*height
&& no_mines
)
841 minesweeper_putmines(p
,x
,y
);
843 if( discover( y
, x
, true ) )
845 minefield
[y
][x
].known
= 1;
846 return MINESWEEPER_LOSE
;
849 tiles_left
= count_tiles_left();
850 if( tiles_left
== mine_num
)
852 return MINESWEEPER_WIN
;
856 /* toggle flag under cursor */
858 #ifdef MINESWP_TOGGLE_PRE
859 if( lastbutton
!= MINESWP_TOGGLE_PRE
)
862 #ifdef MINESWP_TOGGLE2
863 case MINESWP_TOGGLE2
:
865 minefield
[y
][x
].flag
= ( minefield
[y
][x
].flag
+ 1 )%2;
868 /* show how many mines you think you have found and how many
869 * there really are on the game */
873 flags_used
= count_flags();
874 if (flags_used
== 1) {
875 rb
->splashf( HZ
*2, "You marked 1 field. There are %d mines.",
880 rb
->splashf( HZ
*2, "You marked %d fields. There are %d mines.",
881 flags_used
, mine_num
);
886 if( rb
->default_event_handler( button
) == SYS_USB_CONNECTED
)
887 return MINESWEEPER_USB
;
890 if( button
!= BUTTON_NONE
)
896 /* plugin entry point */
897 enum plugin_status
plugin_start(const void* parameter
)
903 rb
->lcd_set_backdrop(NULL
);
908 switch( minesweeper() )
910 case MINESWEEPER_WIN
:
911 rb
->splash( HZ
, "You Win!" );
912 rb
->lcd_clear_display();
916 case MINESWEEPER_LOSE
:
917 rb
->splash( HZ
, "You Lose!" );
918 rb
->lcd_clear_display();
922 case MINESWEEPER_USB
:
923 return PLUGIN_USB_CONNECTED
;
925 case MINESWEEPER_QUIT
: