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 #include "lib/playback_control.h"
28 /* what the minesweeper() function can return */
29 enum minesweeper_status
{
36 /* variable button definitions */
37 #if CONFIG_KEYPAD == RECORDER_PAD
38 # define MINESWP_LEFT BUTTON_LEFT
39 # define MINESWP_RIGHT BUTTON_RIGHT
40 # define MINESWP_UP BUTTON_UP
41 # define MINESWP_DOWN BUTTON_DOWN
42 # define MINESWP_QUIT BUTTON_OFF
43 # define MINESWP_TOGGLE BUTTON_ON
44 # define MINESWP_TOGGLE2 BUTTON_F1
45 # define MINESWP_DISCOVER BUTTON_PLAY
46 # define MINESWP_DISCOVER2 BUTTON_F2
47 # define MINESWP_INFO BUTTON_F3
49 #elif CONFIG_KEYPAD == ARCHOS_AV300_PAD
50 # define MINESWP_LEFT BUTTON_LEFT
51 # define MINESWP_RIGHT BUTTON_RIGHT
52 # define MINESWP_UP BUTTON_UP
53 # define MINESWP_DOWN BUTTON_DOWN
54 # define MINESWP_QUIT BUTTON_OFF
55 # define MINESWP_TOGGLE BUTTON_ON
56 # define MINESWP_TOGGLE2 BUTTON_F1
57 # define MINESWP_DISCOVER BUTTON_SELECT
58 # define MINESWP_DISCOVER2 BUTTON_F2
59 # define MINESWP_INFO BUTTON_F3
61 #elif CONFIG_KEYPAD == ONDIO_PAD
62 # define MINESWP_LEFT BUTTON_LEFT
63 # define MINESWP_RIGHT BUTTON_RIGHT
64 # define MINESWP_UP BUTTON_UP
65 # define MINESWP_DOWN BUTTON_DOWN
66 # define MINESWP_QUIT BUTTON_OFF
67 # define MINESWP_TOGGLE_PRE BUTTON_MENU
68 # define MINESWP_TOGGLE (BUTTON_MENU | BUTTON_REL)
69 # define MINESWP_DISCOVER (BUTTON_MENU | BUTTON_REPEAT)
70 # define MINESWP_INFO (BUTTON_MENU | BUTTON_OFF)
72 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
73 (CONFIG_KEYPAD == IRIVER_H300_PAD)
74 # define MINESWP_LEFT BUTTON_LEFT
75 # define MINESWP_RIGHT BUTTON_RIGHT
76 # define MINESWP_UP BUTTON_UP
77 # define MINESWP_DOWN BUTTON_DOWN
78 # define MINESWP_QUIT BUTTON_OFF
79 # define MINESWP_TOGGLE BUTTON_ON
80 # define MINESWP_TOGGLE2 BUTTON_REC
81 # define MINESWP_DISCOVER BUTTON_SELECT
82 # define MINESWP_INFO BUTTON_MODE
84 # define MINESWP_RC_QUIT BUTTON_RC_STOP
86 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
87 (CONFIG_KEYPAD == IPOD_3G_PAD) || \
88 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
89 # define MINESWP_SCROLLWHEEL
90 # define MINESWP_LEFT BUTTON_LEFT
91 # define MINESWP_RIGHT BUTTON_RIGHT
92 # define MINESWP_UP BUTTON_MENU
93 # define MINESWP_DOWN BUTTON_PLAY
94 # define MINESWP_NEXT BUTTON_SCROLL_FWD
95 # define MINESWP_PREV BUTTON_SCROLL_BACK
96 # define MINESWP_QUIT (BUTTON_SELECT | BUTTON_MENU)
97 # define MINESWP_TOGGLE_PRE BUTTON_SELECT
98 # define MINESWP_TOGGLE (BUTTON_SELECT | BUTTON_REL)
99 # define MINESWP_DISCOVER (BUTTON_SELECT | BUTTON_REPEAT)
100 # define MINESWP_INFO (BUTTON_SELECT | BUTTON_PLAY)
102 #elif (CONFIG_KEYPAD == IAUDIO_X5M5_PAD)
103 # define MINESWP_LEFT BUTTON_LEFT
104 # define MINESWP_RIGHT BUTTON_RIGHT
105 # define MINESWP_UP BUTTON_UP
106 # define MINESWP_DOWN BUTTON_DOWN
107 # define MINESWP_QUIT BUTTON_POWER
108 # define MINESWP_TOGGLE BUTTON_PLAY
109 # define MINESWP_DISCOVER BUTTON_SELECT
110 # define MINESWP_INFO BUTTON_REC
112 #elif (CONFIG_KEYPAD == GIGABEAT_PAD)
113 # define MINESWP_LEFT BUTTON_LEFT
114 # define MINESWP_RIGHT BUTTON_RIGHT
115 # define MINESWP_UP BUTTON_UP
116 # define MINESWP_DOWN BUTTON_DOWN
117 # define MINESWP_QUIT BUTTON_POWER
118 # define MINESWP_TOGGLE BUTTON_A
119 # define MINESWP_DISCOVER BUTTON_SELECT
120 # define MINESWP_INFO BUTTON_MENU
122 #elif (CONFIG_KEYPAD == SANSA_E200_PAD)
124 # define MINESWP_SCROLLWHEEL
125 # define MINESWP_LEFT BUTTON_LEFT
126 # define MINESWP_RIGHT BUTTON_RIGHT
127 # define MINESWP_UP BUTTON_UP
128 # define MINESWP_DOWN BUTTON_DOWN
129 # define MINESWP_QUIT BUTTON_POWER
130 # define MINESWP_NEXT BUTTON_SCROLL_FWD
131 # define MINESWP_PREV BUTTON_SCROLL_BACK
132 # define MINESWP_TOGGLE BUTTON_REC
133 # define MINESWP_DISCOVER BUTTON_SELECT
134 # define MINESWP_INFO (BUTTON_REC|BUTTON_REPEAT)
136 #elif (CONFIG_KEYPAD == SANSA_FUZE_PAD)
138 # define MINESWP_LEFT BUTTON_LEFT
139 # define MINESWP_RIGHT BUTTON_RIGHT
140 # define MINESWP_UP BUTTON_UP
141 # define MINESWP_DOWN BUTTON_DOWN
142 # define MINESWP_QUIT (BUTTON_HOME|BUTTON_REPEAT)
143 # define MINESWP_TOGGLE BUTTON_SCROLL_FWD
144 # define MINESWP_DISCOVER BUTTON_SELECT
145 # define MINESWP_INFO BUTTON_SCROLL_BACK
147 #elif (CONFIG_KEYPAD == SANSA_C200_PAD) || \
148 (CONFIG_KEYPAD == SANSA_CLIP_PAD) || \
149 (CONFIG_KEYPAD == SANSA_M200_PAD)
150 # define MINESWP_LEFT BUTTON_LEFT
151 # define MINESWP_RIGHT BUTTON_RIGHT
152 # define MINESWP_UP BUTTON_UP
153 # define MINESWP_DOWN BUTTON_DOWN
154 # define MINESWP_QUIT BUTTON_POWER
155 # define MINESWP_TOGGLE_PRE BUTTON_SELECT
156 # define MINESWP_TOGGLE (BUTTON_SELECT | BUTTON_REL)
157 # define MINESWP_TOGGLE2 BUTTON_VOL_DOWN
158 # define MINESWP_DISCOVER (BUTTON_SELECT | BUTTON_REPEAT)
159 # define MINESWP_DISCOVER2 BUTTON_VOL_UP
160 # define MINESWP_INFO (BUTTON_SELECT | BUTTON_UP)
162 #elif (CONFIG_KEYPAD == IRIVER_H10_PAD)
163 # define MINESWP_LEFT BUTTON_LEFT
164 # define MINESWP_RIGHT BUTTON_RIGHT
165 # define MINESWP_UP BUTTON_SCROLL_UP
166 # define MINESWP_DOWN BUTTON_SCROLL_DOWN
167 # define MINESWP_QUIT BUTTON_POWER
168 # define MINESWP_TOGGLE BUTTON_PLAY
169 # define MINESWP_DISCOVER BUTTON_REW
170 # define MINESWP_INFO (BUTTON_REW | BUTTON_PLAY)
172 #elif (CONFIG_KEYPAD == GIGABEAT_S_PAD)
173 # define MINESWP_LEFT BUTTON_LEFT
174 # define MINESWP_RIGHT BUTTON_RIGHT
175 # define MINESWP_UP BUTTON_UP
176 # define MINESWP_DOWN BUTTON_DOWN
177 # define MINESWP_QUIT BUTTON_BACK
178 # define MINESWP_TOGGLE BUTTON_PLAY
179 # define MINESWP_DISCOVER BUTTON_SELECT
180 # define MINESWP_INFO BUTTON_MENU
182 #elif (CONFIG_KEYPAD == MROBE100_PAD)
183 # define MINESWP_LEFT BUTTON_LEFT
184 # define MINESWP_RIGHT BUTTON_RIGHT
185 # define MINESWP_UP BUTTON_UP
186 # define MINESWP_DOWN BUTTON_DOWN
187 # define MINESWP_QUIT BUTTON_POWER
188 # define MINESWP_TOGGLE BUTTON_DISPLAY
189 # define MINESWP_DISCOVER BUTTON_SELECT
190 # define MINESWP_INFO BUTTON_MENU
192 #elif CONFIG_KEYPAD == IAUDIO_M3_PAD
193 # define MINESWP_LEFT BUTTON_RC_REW
194 # define MINESWP_RIGHT BUTTON_RC_FF
195 # define MINESWP_UP BUTTON_RC_VOL_UP
196 # define MINESWP_DOWN BUTTON_RC_VOL_DOWN
197 # define MINESWP_QUIT BUTTON_RC_REC
198 # define MINESWP_TOGGLE BUTTON_RC_MODE
199 # define MINESWP_DISCOVER BUTTON_RC_PLAY
200 # define MINESWP_INFO BUTTON_RC_MENU
202 #elif (CONFIG_KEYPAD == COWON_D2_PAD)
203 # define MINESWP_QUIT BUTTON_POWER
205 #elif CONFIG_KEYPAD == CREATIVEZVM_PAD
206 # define MINESWP_LEFT BUTTON_LEFT
207 # define MINESWP_RIGHT BUTTON_RIGHT
208 # define MINESWP_UP BUTTON_UP
209 # define MINESWP_DOWN BUTTON_DOWN
210 # define MINESWP_QUIT BUTTON_BACK
211 # define MINESWP_TOGGLE BUTTON_SELECT
212 # define MINESWP_DISCOVER BUTTON_PLAY
213 # define MINESWP_INFO BUTTON_MENU
215 #elif CONFIG_KEYPAD == PHILIPS_HDD1630_PAD
216 # define MINESWP_LEFT BUTTON_LEFT
217 # define MINESWP_RIGHT BUTTON_RIGHT
218 # define MINESWP_UP BUTTON_UP
219 # define MINESWP_DOWN BUTTON_DOWN
220 # define MINESWP_QUIT BUTTON_POWER
221 # define MINESWP_TOGGLE BUTTON_VIEW
222 # define MINESWP_DISCOVER BUTTON_SELECT
223 # define MINESWP_INFO BUTTON_MENU
225 #elif CONFIG_KEYPAD == PHILIPS_HDD6330_PAD
226 # define MINESWP_LEFT BUTTON_LEFT
227 # define MINESWP_RIGHT BUTTON_RIGHT
228 # define MINESWP_UP BUTTON_UP
229 # define MINESWP_DOWN BUTTON_DOWN
230 # define MINESWP_QUIT BUTTON_POWER
231 # define MINESWP_TOGGLE BUTTON_NEXT
232 # define MINESWP_DISCOVER BUTTON_PLAY
233 # define MINESWP_INFO BUTTON_MENU
235 #elif CONFIG_KEYPAD == PHILIPS_SA9200_PAD
236 # define MINESWP_LEFT BUTTON_PREV
237 # define MINESWP_RIGHT BUTTON_NEXT
238 # define MINESWP_UP BUTTON_UP
239 # define MINESWP_DOWN BUTTON_DOWN
240 # define MINESWP_QUIT BUTTON_POWER
241 # define MINESWP_TOGGLE BUTTON_RIGHT
242 # define MINESWP_DISCOVER BUTTON_PLAY
243 # define MINESWP_INFO BUTTON_MENU
245 #elif (CONFIG_KEYPAD == ONDAVX747_PAD) || \
246 CONFIG_KEYPAD == ONDAVX777_PAD || \
247 CONFIG_KEYPAD == MROBE500_PAD
248 # define MINESWP_QUIT BUTTON_POWER
250 #elif (CONFIG_KEYPAD == SAMSUNG_YH_PAD)
251 # define MINESWP_LEFT BUTTON_LEFT
252 # define MINESWP_RIGHT BUTTON_RIGHT
253 # define MINESWP_UP BUTTON_UP
254 # define MINESWP_DOWN BUTTON_DOWN
255 # define MINESWP_QUIT BUTTON_REC
256 # define MINESWP_TOGGLE BUTTON_PLAY
257 # define MINESWP_DISCOVER BUTTON_REW
258 # define MINESWP_INFO BUTTON_FFWD
260 #elif (CONFIG_KEYPAD == PBELL_VIBE500_PAD)
261 # define MINESWP_LEFT BUTTON_PREV
262 # define MINESWP_RIGHT BUTTON_NEXT
263 # define MINESWP_UP BUTTON_UP
264 # define MINESWP_DOWN BUTTON_DOWN
265 # define MINESWP_QUIT BUTTON_REC
266 # define MINESWP_TOGGLE BUTTON_PLAY
267 # define MINESWP_DISCOVER BUTTON_OK
268 # define MINESWP_INFO BUTTON_MENU
270 #elif CONFIG_KEYPAD == MPIO_HD200_PAD
271 # define MINESWP_LEFT BUTTON_VOL_DOWN
272 # define MINESWP_RIGHT BUTTON_VOL_UP
273 # define MINESWP_UP BUTTON_REW
274 # define MINESWP_DOWN BUTTON_FF
275 # define MINESWP_QUIT (BUTTON_REC|BUTTON_PLAY)
276 # define MINESWP_TOGGLE BUTTON_PLAY
277 # define MINESWP_DISCOVER BUTTON_FUNC
278 # define MINESWP_INFO BUTTON_REC
280 #elif CONFIG_KEYPAD == MPIO_HD300_PAD
281 # define MINESWP_LEFT BUTTON_MENU
282 # define MINESWP_RIGHT BUTTON_ENTER
283 # define MINESWP_UP BUTTON_UP
284 # define MINESWP_DOWN BUTTON_DOWN
285 # define MINESWP_QUIT BUTTON_REC
286 # define MINESWP_TOGGLE BUTTON_PLAY
287 # define MINESWP_DISCOVER BUTTON_FF
288 # define MINESWP_INFO BUTTON_REW
290 #elif CONFIG_KEYPAD == SANSA_FUZEPLUS_PAD
291 # define MINESWP_LEFT BUTTON_LEFT
292 # define MINESWP_RIGHT BUTTON_RIGHT
293 # define MINESWP_UP BUTTON_UP
294 # define MINESWP_DOWN BUTTON_DOWN
295 # define MINESWP_QUIT BUTTON_POWER
296 # define MINESWP_TOGGLE BUTTON_SELECT
297 # define MINESWP_DISCOVER BUTTON_PLAYPAUSE
298 # define MINESWP_INFO BUTTON_BACK
300 #elif (CONFIG_KEYPAD == SANSA_CONNECT_PAD)
302 # define MINESWP_SCROLLWHEEL
303 # define MINESWP_LEFT BUTTON_LEFT
304 # define MINESWP_RIGHT BUTTON_RIGHT
305 # define MINESWP_UP BUTTON_UP
306 # define MINESWP_DOWN BUTTON_DOWN
307 # define MINESWP_QUIT BUTTON_POWER
308 # define MINESWP_NEXT BUTTON_SCROLL_FWD
309 # define MINESWP_PREV BUTTON_SCROLL_BACK
310 # define MINESWP_TOGGLE BUTTON_NEXT
311 # define MINESWP_DISCOVER BUTTON_SELECT
312 # define MINESWP_INFO BUTTON_PREV
314 #elif (CONFIG_KEYPAD == SAMSUNG_YPR0_PAD)
315 # define MINESWP_LEFT BUTTON_LEFT
316 # define MINESWP_RIGHT BUTTON_RIGHT
317 # define MINESWP_UP BUTTON_UP
318 # define MINESWP_DOWN BUTTON_DOWN
319 # define MINESWP_QUIT BUTTON_BACK
320 # define MINESWP_TOGGLE BUTTON_USER
321 # define MINESWP_DISCOVER BUTTON_SELECT
322 # define MINESWP_INFO BUTTON_MENU
325 #error No keymap defined!
328 #ifdef HAVE_TOUCHSCREEN
330 # define MINESWP_QUIT BUTTON_TOPLEFT
333 # define MINESWP_LEFT BUTTON_MIDLEFT
335 #ifndef MINESWP_RIGHT
336 # define MINESWP_RIGHT BUTTON_MIDRIGHT
339 # define MINESWP_UP BUTTON_TOPMIDDLE
342 # define MINESWP_DOWN BUTTON_BOTTOMMIDDLE
344 #ifndef MINESWP_TOGGLE
345 # define MINESWP_TOGGLE BUTTON_CENTER
347 #ifndef MINESWP_DISCOVER
348 # define MINESWP_DISCOVER BUTTON_BOTTOMLEFT
351 # define MINESWP_INFO BUTTON_BOTTOMRIGHT
355 extern const fb_data minesweeper_tiles
[];
357 #ifdef HAVE_LCD_COLOR
358 # if ( LCD_HEIGHT * LCD_WIDTH ) / ( 16 * 16 ) >= 130
359 /* We want to have at least 130 tiles on the screen */
361 # elif ( LCD_HEIGHT * LCD_WIDTH ) / ( 12 * 12 ) >= 130
366 # define BackgroundColor LCD_RGBPACK( 128, 128, 128 )
376 #define ExplodedMine 12
378 #define CorrectFlag 14
380 #define draw_tile( num, x, y ) \
381 rb->lcd_bitmap_part( minesweeper_tiles, 0, num * TileSize, \
382 TileSize, left+x*TileSize, top+y*TileSize, \
385 #define invert_tile( x, y ) \
386 rb->lcd_set_drawmode(DRMODE_COMPLEMENT); \
387 rb->lcd_fillrect( left+x*TileSize, top+y*TileSize, TileSize, TileSize ); \
388 rb->lcd_set_drawmode(DRMODE_SOLID);
392 * if there is a mine, mine is true
393 * if tile is known by player, known is true
394 * if tile has a flag, flag is true
395 * neighbors is the total number of mines arround tile
399 unsigned char mine
: 1;
400 unsigned char known
: 1;
401 unsigned char flag
: 1;
402 unsigned char neighbors
: 4;
405 /* the height and width of the field */
406 #define MAX_HEIGHT (LCD_HEIGHT/TileSize)
407 #define MAX_WIDTH (LCD_WIDTH/TileSize)
408 static int height
= MAX_HEIGHT
;
409 static int width
= MAX_WIDTH
;
413 /* The Minefield. Caution it is defined as Y, X! Not the opposite. */
414 static tile minefield
[MAX_HEIGHT
][MAX_WIDTH
];
416 /* total number of mines on the game */
417 static int mine_num
= 0;
419 /* percentage of mines on minefield used during generation */
420 static int percent
= 16;
422 /* number of tiles left on the game */
423 static int tiles_left
;
425 /* Because mines are set after the first move... */
426 static bool no_mines
= true;
428 /* We need a stack (created on discover()) for the cascade algorithm. */
429 static int stack_pos
= 0;
431 #ifdef HAVE_TOUCHSCREEN
433 #include "lib/pluginlib_touchscreen.h"
434 static struct ts_raster mine_raster
= { 0, 0, MAX_WIDTH
, MAX_HEIGHT
, TileSize
, TileSize
};
438 static void push( int *stack
, int y
, int x
)
440 if( stack_pos
<= height
*width
)
442 stack
[++stack_pos
] = y
;
443 stack
[++stack_pos
] = x
;
447 /* Unveil tiles and push them to stack if they are empty. */
448 static void unveil( int *stack
, int y
, int x
)
450 if( x
< 0 || y
< 0 || x
> width
- 1 || y
> height
- 1
451 || minefield
[y
][x
].known
452 || minefield
[y
][x
].mine
|| minefield
[y
][x
].flag
) return;
454 minefield
[y
][x
].known
= 1;
456 if( minefield
[y
][x
].neighbors
== 0 )
460 static int is_flagged( int y
, int x
)
462 if( x
>= 0 && y
>= 0 && x
< width
&& y
< height
&& minefield
[y
][x
].flag
)
467 static int neighbors_flagged( int y
, int x
)
469 return is_flagged( y
-1, x
-1 ) +
470 is_flagged( y
-1, x
) +
471 is_flagged( y
-1, x
+1 ) +
472 is_flagged( y
, x
-1 ) +
474 is_flagged( y
, x
+1 ) +
475 is_flagged( y
+1, x
-1 ) +
476 is_flagged( y
+1, x
) +
477 is_flagged( y
+1, x
+1 );
480 static bool discover( int y
, int x
, bool explore_neighbors
)
483 if( x
< 0 || y
< 0 || x
> width
- 1 || y
> height
- 1)
486 if( minefield
[y
][x
].known
|| minefield
[y
][x
].mine
|| minefield
[y
][x
].flag
)
488 if( !minefield
[y
][x
].flag
&& minefield
[y
][x
].mine
)
491 if( explore_neighbors
&& minefield
[y
][x
].known
&&
492 minefield
[y
][x
].neighbors
== neighbors_flagged( y
, x
) )
494 return discover( y
-1, x
-1, false ) ||
495 discover( y
-1, x
, false ) ||
496 discover( y
-1, x
+1, false ) ||
497 discover( y
, x
-1, false ) ||
498 discover( y
, x
, false ) ||
499 discover( y
, x
+1, false ) ||
500 discover( y
+1, x
-1, false ) ||
501 discover( y
+1, x
, false ) ||
502 discover( y
+1, x
+1, false );
508 minefield
[y
][x
].known
= 1;
509 /* Exit if the tile is not empty. (no mines nearby) */
510 if( minefield
[y
][x
].neighbors
) return false;
512 int stack
[height
*width
];
516 /* Scan all nearby tiles. If we meet a tile with a number we just unveil
517 * it. If we meet an empty tile, we push the location in stack. For each
518 * location in stack we do the same thing. (scan again all nearby tiles)
522 /* Pop x, y from stack. */
523 x
= stack
[stack_pos
--];
524 y
= stack
[stack_pos
--];
526 unveil( stack
, y
-1, x
-1 );
527 unveil( stack
, y
-1, x
);
528 unveil( stack
, y
-1, x
+1 );
529 unveil( stack
, y
, x
+1 );
530 unveil( stack
, y
+1, x
+1 );
531 unveil( stack
, y
+1, x
);
532 unveil( stack
, y
+1, x
-1 );
533 unveil( stack
, y
, x
-1 );
539 /* Reset the whole board for a new game. */
540 static void minesweeper_init( void )
542 rb
->memset(minefield
, 0, sizeof(minefield
));
544 tiles_left
= width
*height
;
548 /* put mines on the mine field */
549 /* there is p% chance that a tile is a mine */
550 /* if the tile has coordinates (x,y), or is adjacent to those,
551 * then it can't be a mine because that would reduce the game
552 * from a logic game to a guessing game. */
553 static void minesweeper_putmines( int p
, int x
, int y
)
558 for( i
= 0; i
< height
; i
++ )
560 for( j
= 0; j
< width
; j
++ )
562 if( rb
->rand()%100 < p
563 && !( i
>=y
-1 && i
<=y
+1 && j
>=x
-1 && j
<=x
+1 ) )
565 minefield
[i
][j
].mine
= 1;
570 minefield
[i
][j
].mine
= 0;
572 minefield
[i
][j
].neighbors
= 0;
576 /* we need to compute the neighbor element for each tile */
577 for( i
= 0; i
< height
; i
++ )
579 for( j
= 0; j
< width
; j
++ )
584 minefield
[i
][j
].neighbors
+= minefield
[i
-1][j
-1].mine
;
585 minefield
[i
][j
].neighbors
+= minefield
[i
-1][j
].mine
;
587 minefield
[i
][j
].neighbors
+= minefield
[i
-1][j
+1].mine
;
590 minefield
[i
][j
].neighbors
+= minefield
[i
][j
-1].mine
;
592 minefield
[i
][j
].neighbors
+= minefield
[i
][j
+1].mine
;
596 minefield
[i
][j
].neighbors
+= minefield
[i
+1][j
-1].mine
;
597 minefield
[i
][j
].neighbors
+= minefield
[i
+1][j
].mine
;
599 minefield
[i
][j
].neighbors
+= minefield
[i
+1][j
+1].mine
;
606 /* In case the user is lucky and there are no mines positioned. */
607 if( !mine_num
&& height
*width
!= 1 )
609 minesweeper_putmines(p
, x
, y
);
613 /* A function that will uncover all the board, when the user wins or loses.
614 can easily be expanded, (just a call assigned to a button) as a solver. */
615 static void mine_show( void )
619 for( i
= 0; i
< height
; i
++ )
621 for( j
= 0; j
< width
; j
++ )
623 if( minefield
[i
][j
].mine
)
625 if( minefield
[i
][j
].known
)
626 draw_tile( ExplodedMine
, j
, i
);
627 else if( minefield
[i
][j
].flag
)
628 draw_tile( CorrectFlag
, j
, i
);
630 draw_tile( Mine
, j
, i
);
634 if( minefield
[i
][j
].flag
)
635 draw_tile( WrongFlag
, j
, i
);
637 draw_tile( minefield
[i
][j
].neighbors
, j
, i
);
644 button
= rb
->button_get(true);
645 while( ( button
== BUTTON_NONE
)
646 || ( button
& (BUTTON_REL
|BUTTON_REPEAT
) ) );
647 #ifdef HAVE_TOUCHSCREEN
648 button
= BUTTON_NONE
;
652 static int count_tiles_left( void )
656 for( i
= 0; i
< height
; i
++ )
657 for( j
= 0; j
< width
; j
++ )
658 if( minefield
[i
][j
].known
== 0 )
663 static int count_flags( void )
667 for( i
= 0; i
< height
; i
++ )
668 for( j
= 0; j
< width
; j
++ )
669 if( minefield
[i
][j
].flag
== 1 )
674 /* welcome screen where player can chose mine percentage */
675 static enum minesweeper_status
menu( void )
677 int selection
= 0, result
= MINESWEEPER_QUIT
;
678 bool menu_quit
= false;
680 MENUITEM_STRINGLIST( menu
, "Minesweeper Menu", NULL
, "Play Minesweeper",
681 "Mine Percentage", "Number of Rows",
682 "Number of Columns", "Playback Control", "Quit" );
684 #ifdef HAVE_LCD_COLOR
685 rb
->lcd_set_foreground( rb
->global_settings
->fg_color
);
686 rb
->lcd_set_background( rb
->global_settings
->bg_color
);
691 switch( rb
->do_menu( &menu
, &selection
, NULL
, false ) )
694 result
= MINESWEEPER_WIN
; /* start playing */
699 rb
->set_int( "Mine Percentage", "%", UNIT_INT
, &percent
, NULL
,
704 rb
->set_int( "Number of Rows", "", UNIT_INT
, &height
, NULL
,
705 1, 1, MAX_HEIGHT
, NULL
);
709 rb
->set_int( "Number of Columns", "", UNIT_INT
, &width
, NULL
,
710 1, 1, MAX_WIDTH
, NULL
);
714 playback_control( NULL
);
718 result
= MINESWEEPER_QUIT
; /* quit program */
727 /* the big and ugly game function */
728 static enum minesweeper_status
minesweeper( void )
732 #if defined(HAVE_TOUCHSCREEN) || defined(MINESWP_TOGGLE_PRE)
733 int lastbutton
= BUTTON_NONE
;
736 /* the cursor coordinates */
742 if( ( i
= menu() ) != MINESWEEPER_WIN
) return i
;
747 top
= (LCD_HEIGHT
-height
*TileSize
)/2;
748 left
= (LCD_WIDTH
-width
*TileSize
)/2;
750 #ifdef HAVE_TOUCHSCREEN
751 mine_raster
.tl_x
= left
;
752 mine_raster
.tl_y
= top
;
753 mine_raster
.width
= width
*TileSize
;
754 mine_raster
.height
= height
*TileSize
;
757 rb
->srand( *rb
->current_tick
);
768 /* clear the screen buffer */
769 #ifdef HAVE_LCD_COLOR
770 rb
->lcd_set_background( BackgroundColor
);
772 rb
->lcd_clear_display();
774 /* display the mine field */
775 for( i
= 0; i
< height
; i
++ )
777 for( j
= 0; j
< width
; j
++ )
779 if( minefield
[i
][j
].known
)
781 draw_tile( minefield
[i
][j
].neighbors
, j
, i
);
783 else if(minefield
[i
][j
].flag
)
785 draw_tile( Flag
, j
, i
);
789 draw_tile( Unknown
, j
, i
);
794 /* display the cursor */
797 /* update the screen */
800 button
= rb
->button_get(true);
801 #ifdef HAVE_TOUCHSCREEN
802 if(button
& BUTTON_TOUCHSCREEN
)
804 struct ts_raster_result res
;
805 if(touchscreen_map_raster(&mine_raster
, rb
->button_get_data() >> 16, rb
->button_get_data() & 0xffff, &res
) == 1)
807 button
&= ~BUTTON_TOUCHSCREEN
;
808 lastbutton
&= ~BUTTON_TOUCHSCREEN
;
810 if(button
& BUTTON_REPEAT
&& lastbutton
!= MINESWP_TOGGLE
&& lastbutton
^ BUTTON_REPEAT
)
811 button
= MINESWP_TOGGLE
;
812 else if(button
== BUTTON_REL
&& lastbutton
^ BUTTON_REPEAT
)
813 button
= MINESWP_DISCOVER
;
815 button
|= BUTTON_TOUCHSCREEN
;
824 /* quit minesweeper (you really shouldn't use this button ...) */
825 #ifdef MINESWP_RC_QUIT
826 case MINESWP_RC_QUIT
:
829 return MINESWEEPER_QUIT
;
831 /* move cursor left */
833 case MINESWP_LEFT
|BUTTON_REPEAT
:
838 /* move cursor right */
840 case MINESWP_RIGHT
|BUTTON_REPEAT
:
845 /* move cursor down */
847 case MINESWP_DOWN
|BUTTON_REPEAT
:
854 case MINESWP_UP
|BUTTON_REPEAT
:
859 /*move cursor though the entire field*/
860 #ifdef MINESWP_SCROLLWHEEL
862 case MINESWP_NEXT
|BUTTON_REPEAT
:
863 if (x
== width
-1 ) {
872 case MINESWP_PREV
|BUTTON_REPEAT
:
881 /* discover a tile (and it's neighbors if .neighbors == 0) */
882 case MINESWP_DISCOVER
:
883 #ifdef MINESWP_DISCOVER2
884 case MINESWP_DISCOVER2
:
886 if( minefield
[y
][x
].flag
) break;
887 /* we put the mines on the first "click" so that you don't
888 * lose on the first "click" */
889 if( tiles_left
== width
*height
&& no_mines
)
890 minesweeper_putmines(percent
,x
,y
);
892 if( discover( y
, x
, true ) )
894 minefield
[y
][x
].known
= 1;
895 return MINESWEEPER_LOSE
;
898 tiles_left
= count_tiles_left();
899 if( tiles_left
== mine_num
)
901 return MINESWEEPER_WIN
;
905 /* toggle flag under cursor */
907 #ifdef MINESWP_TOGGLE_PRE
908 if( lastbutton
!= MINESWP_TOGGLE_PRE
)
911 #ifdef MINESWP_TOGGLE2
912 case MINESWP_TOGGLE2
:
914 if( !minefield
[y
][x
].known
)
915 minefield
[y
][x
].flag
= !minefield
[y
][x
].flag
;
918 /* show how many mines you think you have found and how many
919 * there really are on the game */
923 int flags_used
= count_flags();
924 if (flags_used
== 1) {
925 rb
->splashf( HZ
*2, "You marked 1 field. There are %d mines.",
930 rb
->splashf( HZ
*2, "You marked %d fields. There are %d mines.",
931 flags_used
, mine_num
);
936 if( rb
->default_event_handler( button
) == SYS_USB_CONNECTED
)
937 return MINESWEEPER_USB
;
940 #if defined(HAVE_TOUCHSCREEN) || defined(MINESWP_TOGGLE_PRE)
941 if( button
!= BUTTON_NONE
)
948 /* plugin entry point */
949 enum plugin_status
plugin_start(const void* parameter
)
955 rb
->lcd_set_backdrop(NULL
);
960 switch( minesweeper() )
962 case MINESWEEPER_WIN
:
963 rb
->splash( HZ
, "You Win!" );
964 rb
->lcd_clear_display();
968 case MINESWEEPER_LOSE
:
969 rb
->splash( HZ
, "You Lose!" );
970 rb
->lcd_clear_display();
974 case MINESWEEPER_USB
:
975 return PLUGIN_USB_CONNECTED
;
977 case MINESWEEPER_QUIT
: