1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2005 Adam Boot
12 * Color graphics from Gweled (http://sebdelestaing.free.fr/gweled/)
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
22 ****************************************************************************/
25 #include "lib/display_text.h"
26 #include "lib/highscore.h"
27 #include "lib/playback_control.h"
28 #include "pluginbitmaps/jewels.h"
30 /* button definitions */
31 #if CONFIG_KEYPAD == RECORDER_PAD
32 #define JEWELS_UP BUTTON_UP
33 #define JEWELS_DOWN BUTTON_DOWN
34 #define JEWELS_LEFT BUTTON_LEFT
35 #define JEWELS_RIGHT BUTTON_RIGHT
36 #define JEWELS_SELECT BUTTON_PLAY
37 #define JEWELS_CANCEL BUTTON_OFF
38 #define HK_SELECT "PLAY"
39 #define HK_CANCEL "OFF"
41 #elif CONFIG_KEYPAD == ARCHOS_AV300_PAD
42 #define JEWELS_UP BUTTON_UP
43 #define JEWELS_DOWN BUTTON_DOWN
44 #define JEWELS_LEFT BUTTON_LEFT
45 #define JEWELS_RIGHT BUTTON_RIGHT
46 #define JEWELS_SELECT BUTTON_SELECT
47 #define JEWELS_CANCEL BUTTON_OFF
48 #define HK_SELECT "SELECT"
49 #define HK_CANCEL "OFF"
51 #elif CONFIG_KEYPAD == ONDIO_PAD
52 #define JEWELS_UP BUTTON_UP
53 #define JEWELS_DOWN BUTTON_DOWN
54 #define JEWELS_LEFT BUTTON_LEFT
55 #define JEWELS_RIGHT BUTTON_RIGHT
56 #define JEWELS_SELECT BUTTON_MENU
57 #define JEWELS_CANCEL BUTTON_OFF
58 #define HK_SELECT "MENU"
59 #define HK_CANCEL "OFF"
61 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || (CONFIG_KEYPAD == IRIVER_H300_PAD)
62 #define JEWELS_UP BUTTON_UP
63 #define JEWELS_DOWN BUTTON_DOWN
64 #define JEWELS_LEFT BUTTON_LEFT
65 #define JEWELS_RIGHT BUTTON_RIGHT
66 #define JEWELS_SELECT BUTTON_SELECT
67 #define JEWELS_CANCEL BUTTON_OFF
68 #define JEWELS_RC_CANCEL BUTTON_RC_STOP
69 #define HK_SELECT "SELECT"
70 #define HK_CANCEL "OFF"
72 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
73 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
74 #define JEWELS_SCROLLWHEEL
75 #define JEWELS_UP BUTTON_MENU
76 #define JEWELS_DOWN BUTTON_PLAY
77 #define JEWELS_LEFT BUTTON_LEFT
78 #define JEWELS_RIGHT BUTTON_RIGHT
79 #define JEWELS_PREV BUTTON_SCROLL_BACK
80 #define JEWELS_NEXT BUTTON_SCROLL_FWD
81 #define JEWELS_SELECT BUTTON_SELECT
82 #define JEWELS_CANCEL (BUTTON_SELECT | BUTTON_MENU)
83 #define HK_SELECT "SELECT"
84 #define HK_CANCEL "SEL + MENU"
86 #elif (CONFIG_KEYPAD == IPOD_3G_PAD)
87 #define JEWELS_LEFT BUTTON_LEFT
88 #define JEWELS_RIGHT BUTTON_RIGHT
89 #define JEWELS_UP BUTTON_SCROLL_BACK
90 #define JEWELS_DOWN BUTTON_SCROLL_FWD
91 #define JEWELS_SELECT BUTTON_SELECT
92 #define JEWELS_CANCEL BUTTON_MENU
93 #define HK_SELECT "SELECT"
94 #define HK_CANCEL "MENU"
96 #elif CONFIG_KEYPAD == IRIVER_IFP7XX_PAD
97 #define JEWELS_UP BUTTON_UP
98 #define JEWELS_DOWN BUTTON_DOWN
99 #define JEWELS_LEFT BUTTON_LEFT
100 #define JEWELS_RIGHT BUTTON_RIGHT
101 #define JEWELS_SELECT BUTTON_SELECT
102 #define JEWELS_CANCEL BUTTON_PLAY
103 #define HK_SELECT "SELECT"
104 #define HK_CANCEL "PLAY"
106 #elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
107 #define JEWELS_UP BUTTON_UP
108 #define JEWELS_DOWN BUTTON_DOWN
109 #define JEWELS_LEFT BUTTON_LEFT
110 #define JEWELS_RIGHT BUTTON_RIGHT
111 #define JEWELS_SELECT BUTTON_SELECT
112 #define JEWELS_CANCEL BUTTON_POWER
113 #define HK_SELECT "SELECT"
114 #define HK_CANCEL "POWER"
116 #elif CONFIG_KEYPAD == GIGABEAT_PAD
117 #define JEWELS_UP BUTTON_UP
118 #define JEWELS_DOWN BUTTON_DOWN
119 #define JEWELS_LEFT BUTTON_LEFT
120 #define JEWELS_RIGHT BUTTON_RIGHT
121 #define JEWELS_SELECT BUTTON_SELECT
122 #define JEWELS_CANCEL BUTTON_POWER
123 #define HK_SELECT "SELECT"
124 #define HK_CANCEL "POWER"
126 #elif (CONFIG_KEYPAD == SANSA_E200_PAD) || \
127 (CONFIG_KEYPAD == SANSA_CONNECT_PAD)
128 #define JEWELS_SCROLLWHEEL
129 #define JEWELS_UP BUTTON_UP
130 #define JEWELS_DOWN BUTTON_DOWN
131 #define JEWELS_LEFT BUTTON_LEFT
132 #define JEWELS_RIGHT BUTTON_RIGHT
133 #define JEWELS_PREV BUTTON_SCROLL_BACK
134 #define JEWELS_NEXT BUTTON_SCROLL_FWD
135 #define JEWELS_SELECT BUTTON_SELECT
136 #define JEWELS_CANCEL BUTTON_POWER
137 #define HK_SELECT "SELECT"
138 #define HK_CANCEL "POWER"
140 #elif (CONFIG_KEYPAD == SANSA_FUZE_PAD)
141 #define JEWELS_SCROLLWHEEL
142 #define JEWELS_UP BUTTON_UP
143 #define JEWELS_DOWN BUTTON_DOWN
144 #define JEWELS_LEFT BUTTON_LEFT
145 #define JEWELS_RIGHT BUTTON_RIGHT
146 #define JEWELS_PREV BUTTON_SCROLL_BACK
147 #define JEWELS_NEXT BUTTON_SCROLL_FWD
148 #define JEWELS_SELECT BUTTON_SELECT
149 #define JEWELS_CANCEL (BUTTON_HOME|BUTTON_REPEAT)
150 #define HK_SELECT "SELECT"
151 #define HK_CANCEL "HOME"
153 #elif CONFIG_KEYPAD == SANSA_C200_PAD || \
154 CONFIG_KEYPAD == SANSA_CLIP_PAD || \
155 CONFIG_KEYPAD == SANSA_M200_PAD
156 #define JEWELS_UP BUTTON_UP
157 #define JEWELS_DOWN BUTTON_DOWN
158 #define JEWELS_LEFT BUTTON_LEFT
159 #define JEWELS_RIGHT BUTTON_RIGHT
160 #define JEWELS_SELECT BUTTON_SELECT
161 #define JEWELS_CANCEL BUTTON_POWER
162 #define HK_SELECT "SELECT"
163 #define HK_CANCEL "POWER"
165 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
166 #define JEWELS_UP BUTTON_SCROLL_UP
167 #define JEWELS_DOWN BUTTON_SCROLL_DOWN
168 #define JEWELS_LEFT BUTTON_LEFT
169 #define JEWELS_RIGHT BUTTON_RIGHT
170 #define JEWELS_SELECT BUTTON_PLAY
171 #define JEWELS_CANCEL BUTTON_POWER
172 #define HK_SELECT "PLAY"
173 #define HK_CANCEL "POWER"
175 #elif CONFIG_KEYPAD == GIGABEAT_S_PAD || \
176 CONFIG_KEYPAD == SAMSUNG_YPR0_PAD
177 #define JEWELS_UP BUTTON_UP
178 #define JEWELS_DOWN BUTTON_DOWN
179 #define JEWELS_LEFT BUTTON_LEFT
180 #define JEWELS_RIGHT BUTTON_RIGHT
181 #define JEWELS_SELECT BUTTON_SELECT
182 #define JEWELS_CANCEL BUTTON_BACK
183 #define HK_SELECT "SELECT"
184 #define HK_CANCEL "BACK"
186 #elif CONFIG_KEYPAD == MROBE100_PAD
187 #define JEWELS_UP BUTTON_UP
188 #define JEWELS_DOWN BUTTON_DOWN
189 #define JEWELS_LEFT BUTTON_LEFT
190 #define JEWELS_RIGHT BUTTON_RIGHT
191 #define JEWELS_SELECT BUTTON_SELECT
192 #define JEWELS_CANCEL BUTTON_POWER
193 #define HK_SELECT "SELECT"
194 #define HK_CANCEL "POWER"
196 #elif CONFIG_KEYPAD == IAUDIO_M3_PAD
197 #define JEWELS_UP BUTTON_RC_VOL_UP
198 #define JEWELS_DOWN BUTTON_RC_VOL_DOWN
199 #define JEWELS_LEFT BUTTON_RC_REW
200 #define JEWELS_RIGHT BUTTON_RC_FF
201 #define JEWELS_SELECT BUTTON_RC_PLAY
202 #define JEWELS_CANCEL BUTTON_RC_REC
203 #define HK_SELECT "PLAY"
204 #define HK_CANCEL "REC"
206 #define JEWELS_RC_CANCEL BUTTON_REC
208 #elif CONFIG_KEYPAD == COWON_D2_PAD
209 #define JEWELS_CANCEL BUTTON_POWER
210 #define HK_CANCEL "POWER"
212 #elif CONFIG_KEYPAD == IAUDIO67_PAD
213 #define JEWELS_UP BUTTON_STOP
214 #define JEWELS_DOWN BUTTON_PLAY
215 #define JEWELS_LEFT BUTTON_LEFT
216 #define JEWELS_RIGHT BUTTON_RIGHT
217 #define JEWELS_SELECT BUTTON_MENU
218 #define JEWELS_CANCEL BUTTON_POWER
219 #define HK_SELECT "MENU"
220 #define HK_CANCEL "POWER"
222 #elif CONFIG_KEYPAD == CREATIVEZVM_PAD
223 #define JEWELS_UP BUTTON_UP
224 #define JEWELS_DOWN BUTTON_DOWN
225 #define JEWELS_LEFT BUTTON_LEFT
226 #define JEWELS_RIGHT BUTTON_RIGHT
227 #define JEWELS_SELECT BUTTON_SELECT
228 #define JEWELS_CANCEL BUTTON_BACK
229 #define HK_SELECT "MIDDLE"
230 #define HK_CANCEL "BACK"
232 #elif CONFIG_KEYPAD == PHILIPS_HDD1630_PAD
233 #define JEWELS_UP BUTTON_UP
234 #define JEWELS_DOWN BUTTON_DOWN
235 #define JEWELS_LEFT BUTTON_LEFT
236 #define JEWELS_RIGHT BUTTON_RIGHT
237 #define JEWELS_SELECT BUTTON_SELECT
238 #define JEWELS_CANCEL BUTTON_POWER
239 #define HK_SELECT "SELECT"
240 #define HK_CANCEL "POWER"
242 #elif CONFIG_KEYPAD == PHILIPS_HDD6330_PAD
243 #define JEWELS_UP BUTTON_UP
244 #define JEWELS_DOWN BUTTON_DOWN
245 #define JEWELS_LEFT BUTTON_LEFT
246 #define JEWELS_RIGHT BUTTON_RIGHT
247 #define JEWELS_SELECT BUTTON_PLAY
248 #define JEWELS_CANCEL BUTTON_POWER
249 #define HK_SELECT "PLAY"
250 #define HK_CANCEL "POWER"
252 #elif CONFIG_KEYPAD == PHILIPS_SA9200_PAD
253 #define JEWELS_UP BUTTON_UP
254 #define JEWELS_DOWN BUTTON_DOWN
255 #define JEWELS_LEFT BUTTON_PREV
256 #define JEWELS_RIGHT BUTTON_NEXT
257 #define JEWELS_SELECT BUTTON_PLAY
258 #define JEWELS_CANCEL BUTTON_POWER
259 #define HK_SELECT "PLAY"
260 #define HK_CANCEL "POWER"
262 #elif CONFIG_KEYPAD == ONDAVX747_PAD || \
263 CONFIG_KEYPAD == ONDAVX777_PAD || \
264 CONFIG_KEYPAD == MROBE500_PAD
265 #define JEWELS_CANCEL BUTTON_POWER
266 #define HK_CANCEL "POWER"
268 #elif CONFIG_KEYPAD == SAMSUNG_YH_PAD
269 #define JEWELS_UP BUTTON_UP
270 #define JEWELS_DOWN BUTTON_DOWN
271 #define JEWELS_LEFT BUTTON_LEFT
272 #define JEWELS_RIGHT BUTTON_RIGHT
273 #define JEWELS_SELECT BUTTON_PLAY
274 #define JEWELS_CANCEL BUTTON_REW
275 #define HK_SELECT "PLAY"
276 #define HK_CANCEL "REWIND"
278 #elif CONFIG_KEYPAD == PBELL_VIBE500_PAD
279 #define JEWELS_UP BUTTON_UP
280 #define JEWELS_DOWN BUTTON_DOWN
281 #define JEWELS_LEFT BUTTON_PREV
282 #define JEWELS_RIGHT BUTTON_NEXT
283 #define JEWELS_SELECT BUTTON_OK
284 #define JEWELS_CANCEL BUTTON_REC
285 #define HK_SELECT "OK"
286 #define HK_CANCEL "REC"
288 #elif CONFIG_KEYPAD == MPIO_HD200_PAD
289 #define JEWELS_LEFT BUTTON_VOL_DOWN
290 #define JEWELS_RIGHT BUTTON_VOL_UP
291 #define JEWELS_UP BUTTON_REW
292 #define JEWELS_DOWN BUTTON_FF
293 #define JEWELS_SELECT BUTTON_FUNC
294 #define JEWELS_CANCEL BUTTON_REC
295 #define HK_SELECT "FUNC"
296 #define HK_CANCEL "REC"
298 #elif CONFIG_KEYPAD == MPIO_HD300_PAD
299 #define JEWELS_LEFT BUTTON_REW
300 #define JEWELS_RIGHT BUTTON_FF
301 #define JEWELS_UP BUTTON_UP
302 #define JEWELS_DOWN BUTTON_DOWN
303 #define JEWELS_SELECT BUTTON_ENTER
304 #define JEWELS_CANCEL BUTTON_MENU
305 #define HK_SELECT "ENTER"
306 #define HK_CANCEL "MENU"
308 #elif CONFIG_KEYPAD == SANSA_FUZEPLUS_PAD
309 #define JEWELS_LEFT BUTTON_LEFT
310 #define JEWELS_RIGHT BUTTON_RIGHT
311 #define JEWELS_UP BUTTON_UP
312 #define JEWELS_DOWN BUTTON_DOWN
313 #define JEWELS_SELECT BUTTON_SELECT
314 #define JEWELS_CANCEL BUTTON_BACK
315 #define HK_SELECT "SELECT"
316 #define HK_CANCEL "BACK"
319 #error No keymap defined!
322 #ifdef HAVE_TOUCHSCREEN
324 #define JEWELS_UP BUTTON_TOPMIDDLE
327 #define JEWELS_DOWN BUTTON_BOTTOMMIDDLE
330 #define JEWELS_LEFT BUTTON_MIDLEFT
333 #define JEWELS_RIGHT BUTTON_MIDRIGHT
335 #ifndef JEWELS_SELECT
336 #define JEWELS_SELECT BUTTON_CENTER
337 #define HK_SELECT "CENTER"
339 #ifndef JEWELS_CANCEL
340 #define JEWELS_CANCEL BUTTON_TOPLEFT
341 #define HK_CANCEL "TOPLEFT"
345 #define TILE_WIDTH BMPWIDTH_jewels
346 #define TILE_HEIGHT (BMPHEIGHT_jewels/23)
348 #if LCD_HEIGHT < LCD_WIDTH
349 /* This calculation assumes integer division w/ LCD_HEIGHT/TILE_HEIGHT */
350 #define YOFS LCD_HEIGHT-((LCD_HEIGHT/TILE_HEIGHT)*TILE_HEIGHT)
357 /* swap directions */
363 /* play board dimension */
367 /* next level threshold */
368 #define LEVEL_PTS 100
370 /* animation frame rate */
382 /* external bitmaps */
383 extern const fb_data jewels
[];
385 /* tile background colors */
386 #ifdef HAVE_LCD_COLOR
387 static const unsigned jewels_bkgd
[2] = {
388 LCD_RGBPACK(104, 63, 63),
389 LCD_RGBPACK(83, 44, 44)
394 * type is the jewel number 0-7
395 * falling if the jewel is falling
396 * delete marks the jewel for deletion
404 /* the game context struct
405 * score is the current level score
406 * segments is the number of cleared segments in the current run
407 * level is the current level
408 * tmp_type is the select type in the menu
409 * type is the game type (normal or puzzle)
410 * playboard is the game playing board (first row is hidden)
411 * num_jewels is the number of different jewels to use
413 struct game_context
{
415 unsigned int segments
;
418 unsigned int tmp_type
;
419 struct tile playboard
[BJ_HEIGHT
][BJ_WIDTH
];
420 unsigned int num_jewels
;
423 #define MAX_NUM_JEWELS 7
425 #define MAX_PUZZLE_TILES 4
426 #define NUM_PUZZLE_LEVELS 10
434 struct puzzle_level
{
435 unsigned int num_jewels
;
436 unsigned int num_tiles
;
437 struct puzzle_tile tiles
[MAX_PUZZLE_TILES
];
440 #define PUZZLE_TILE_UP 1
441 #define PUZZLE_TILE_DOWN 2
442 #define PUZZLE_TILE_LEFT 4
443 #define PUZZLE_TILE_RIGHT 8
445 struct puzzle_level puzzle_levels
[NUM_PUZZLE_LEVELS
] = {
446 { 5, 2, { {3, 3, PUZZLE_TILE_RIGHT
},
447 {4, 2, PUZZLE_TILE_LEFT
} } },
448 { 5, 2, { {3, 2, PUZZLE_TILE_DOWN
},
449 {3, 4, PUZZLE_TILE_UP
} } },
450 { 6, 3, { {3, 2, PUZZLE_TILE_DOWN
},
451 {3, 4, PUZZLE_TILE_UP
|PUZZLE_TILE_DOWN
},
452 {3, 6, PUZZLE_TILE_UP
} } },
453 { 6, 3, { {3, 2, PUZZLE_TILE_RIGHT
},
454 {4, 3, PUZZLE_TILE_LEFT
|PUZZLE_TILE_RIGHT
},
455 {5, 4, PUZZLE_TILE_LEFT
} } },
456 { 6, 2, { {3, 4, PUZZLE_TILE_RIGHT
},
457 {4, 2, PUZZLE_TILE_LEFT
} } },
458 { 6, 2, { {3, 2, PUZZLE_TILE_DOWN
},
459 {4, 4, PUZZLE_TILE_UP
} } },
460 { 7, 4, { {3, 2, PUZZLE_TILE_RIGHT
|PUZZLE_TILE_DOWN
},
461 {4, 3, PUZZLE_TILE_LEFT
|PUZZLE_TILE_DOWN
},
462 {3, 4, PUZZLE_TILE_RIGHT
|PUZZLE_TILE_UP
},
463 {4, 4, PUZZLE_TILE_LEFT
|PUZZLE_TILE_UP
} } },
464 { 6, 3, { {3, 2, PUZZLE_TILE_DOWN
},
465 {4, 4, PUZZLE_TILE_UP
|PUZZLE_TILE_DOWN
},
466 {3, 6, PUZZLE_TILE_UP
} } },
467 { 7, 3, { {2, 2, PUZZLE_TILE_RIGHT
},
468 {4, 1, PUZZLE_TILE_LEFT
|PUZZLE_TILE_RIGHT
},
469 {5, 4, PUZZLE_TILE_LEFT
} } },
470 { 7, 4, { {3, 0, PUZZLE_TILE_RIGHT
|PUZZLE_TILE_DOWN
},
471 {5, 0, PUZZLE_TILE_LEFT
|PUZZLE_TILE_DOWN
},
472 {2, 7, PUZZLE_TILE_RIGHT
|PUZZLE_TILE_UP
},
473 {4, 7, PUZZLE_TILE_LEFT
|PUZZLE_TILE_UP
} } },
476 #define SAVE_FILE PLUGIN_GAMES_DATA_DIR "/jewels.save"
477 #define SCORE_FILE PLUGIN_GAMES_DATA_DIR "/jewels.score"
478 struct highscore highscores
[NUM_SCORES
];
480 static bool resume_file
= false;
482 /*****************************************************************************
483 * jewels_setcolors() set the foreground and background colors.
484 ******************************************************************************/
485 static inline void jewels_setcolors(void) {
486 #ifdef HAVE_LCD_COLOR
487 rb
->lcd_set_background(LCD_RGBPACK(49, 26, 26));
488 rb
->lcd_set_foreground(LCD_RGBPACK(210, 181, 181));
492 /*****************************************************************************
493 * jewels_loadgame() loads the saved game and returns load success.
494 ******************************************************************************/
495 static bool jewels_loadgame(struct game_context
* bj
)
501 fd
= rb
->open(SAVE_FILE
, O_RDONLY
);
502 if(fd
< 0) return loaded
;
504 /* read in saved game */
506 if(rb
->read(fd
, &bj
->tmp_type
, sizeof(bj
->tmp_type
)) <= 0) break;
507 if(rb
->read(fd
, &bj
->type
, sizeof(bj
->type
)) <= 0) break;
508 if(rb
->read(fd
, &bj
->score
, sizeof(bj
->score
)) <= 0) break;
509 if(rb
->read(fd
, &bj
->level
, sizeof(bj
->level
)) <= 0) break;
510 if(rb
->read(fd
, &bj
->segments
, sizeof(bj
->segments
)) <= 0) break;
511 if(rb
->read(fd
, &bj
->num_jewels
, sizeof(bj
->num_jewels
)) <= 0) break;
512 if(rb
->read(fd
, bj
->playboard
, sizeof(bj
->playboard
)) <= 0) break;
522 /*****************************************************************************
523 * jewels_savegame() saves the current game state.
524 ******************************************************************************/
525 static void jewels_savegame(struct game_context
* bj
)
528 /* write out the game state to the save file */
529 fd
= rb
->open(SAVE_FILE
, O_WRONLY
|O_CREAT
, 0666);
532 rb
->write(fd
, &bj
->tmp_type
, sizeof(bj
->tmp_type
));
533 rb
->write(fd
, &bj
->type
, sizeof(bj
->type
));
534 rb
->write(fd
, &bj
->score
, sizeof(bj
->score
));
535 rb
->write(fd
, &bj
->level
, sizeof(bj
->level
));
536 rb
->write(fd
, &bj
->segments
, sizeof(bj
->segments
));
537 rb
->write(fd
, &bj
->num_jewels
, sizeof(bj
->num_jewels
));
538 rb
->write(fd
, bj
->playboard
, sizeof(bj
->playboard
));
542 /*****************************************************************************
543 * jewels_drawboard() redraws the entire game board.
544 ******************************************************************************/
545 static void jewels_drawboard(struct game_context
* bj
) {
548 unsigned int tempscore
;
550 char *title
= "Level";
553 if (bj
->type
== GAME_TYPE_NORMAL
) {
554 tempscore
= (bj
->score
>LEVEL_PTS
? LEVEL_PTS
: bj
->score
);
557 tempscore
= (bj
->level
>NUM_PUZZLE_LEVELS
? NUM_PUZZLE_LEVELS
: bj
->level
);
558 size
= NUM_PUZZLE_LEVELS
;
562 rb
->lcd_clear_display();
564 /* dispay playing board */
565 for(i
=0; i
<BJ_HEIGHT
-1; i
++){
566 for(j
=0; j
<BJ_WIDTH
; j
++){
567 #ifdef HAVE_LCD_COLOR
568 rb
->lcd_set_foreground(jewels_bkgd
[(i
+j
)%2]);
569 rb
->lcd_fillrect(j
*TILE_WIDTH
, i
*TILE_HEIGHT
+YOFS
,
570 TILE_WIDTH
, TILE_HEIGHT
);
571 rb
->lcd_bitmap_transparent_part(jewels
,
572 0, TILE_HEIGHT
*(bj
->playboard
[i
+1][j
].type
),
574 BMPWIDTH_jewels
, BMPHEIGHT_jewels
),
575 j
*TILE_WIDTH
, i
*TILE_HEIGHT
+YOFS
,
576 TILE_WIDTH
, TILE_HEIGHT
);
578 rb
->lcd_bitmap_part(jewels
,
579 0, TILE_HEIGHT
*(bj
->playboard
[i
+1][j
].type
),
581 BMPWIDTH_jewels
, BMPHEIGHT_jewels
),
582 j
*TILE_WIDTH
, i
*TILE_HEIGHT
+YOFS
,
583 TILE_WIDTH
, TILE_HEIGHT
);
588 #if LCD_WIDTH > LCD_HEIGHT /* horizontal layout */
590 /* draw separator lines */
592 rb
->lcd_vline(BJ_WIDTH
*TILE_WIDTH
, 0, LCD_HEIGHT
-1);
594 rb
->lcd_hline(BJ_WIDTH
*TILE_WIDTH
, LCD_WIDTH
-1, 18);
595 rb
->lcd_hline(BJ_WIDTH
*TILE_WIDTH
, LCD_WIDTH
-1, LCD_HEIGHT
-10);
597 /* draw progress bar */
598 #ifdef HAVE_LCD_COLOR
599 rb
->lcd_set_foreground(LCD_RGBPACK(104, 63, 63));
601 rb
->lcd_fillrect(BJ_WIDTH
*TILE_WIDTH
+(LCD_WIDTH
-BJ_WIDTH
*TILE_WIDTH
)/4,
602 (LCD_HEIGHT
-10)-(((LCD_HEIGHT
-10)-18)*
604 (LCD_WIDTH
-BJ_WIDTH
*TILE_WIDTH
)/2,
605 ((LCD_HEIGHT
-10)-18)*tempscore
/size
);
606 #ifdef HAVE_LCD_COLOR
607 rb
->lcd_set_foreground(LCD_RGBPACK(83, 44, 44));
608 rb
->lcd_drawrect(BJ_WIDTH
*TILE_WIDTH
+(LCD_WIDTH
-BJ_WIDTH
*TILE_WIDTH
)/4+1,
609 (LCD_HEIGHT
-10)-(((LCD_HEIGHT
-10)-18)*
611 (LCD_WIDTH
-BJ_WIDTH
*TILE_WIDTH
)/2-2,
612 ((LCD_HEIGHT
-10)-18)*tempscore
/size
-1);
614 rb
->lcd_drawrect(BJ_WIDTH
*TILE_WIDTH
+(LCD_WIDTH
-BJ_WIDTH
*TILE_WIDTH
)/4,
615 (LCD_HEIGHT
-10)-(((LCD_HEIGHT
-10)-18)*tempscore
/size
),
616 (LCD_WIDTH
-BJ_WIDTH
*TILE_WIDTH
)/2,
617 ((LCD_HEIGHT
-10)-18)*tempscore
/size
+1);
621 rb
->lcd_getstringsize(title
, &w
, &h
);
622 rb
->lcd_putsxy(LCD_WIDTH
-(LCD_WIDTH
-BJ_WIDTH
*TILE_WIDTH
)/2-w
/2, 1, title
);
623 rb
->snprintf(str
, 4, "%d", bj
->level
);
624 rb
->lcd_getstringsize(str
, &w
, &h
);
625 rb
->lcd_putsxy(LCD_WIDTH
-(LCD_WIDTH
-BJ_WIDTH
*TILE_WIDTH
)/2-w
/2, 10, str
);
627 if (bj
->type
== GAME_TYPE_NORMAL
) {
628 rb
->snprintf(str
, 6, "%d", (bj
->level
-1)*LEVEL_PTS
+bj
->score
);
629 rb
->lcd_getstringsize(str
, &w
, &h
);
630 rb
->lcd_putsxy(LCD_WIDTH
-(LCD_WIDTH
-BJ_WIDTH
*TILE_WIDTH
)/2-w
/2,
634 #elif LCD_WIDTH < LCD_HEIGHT /* vertical layout */
636 /* draw separator lines */
638 rb
->lcd_hline(0, LCD_WIDTH
-1, 8*TILE_HEIGHT
+YOFS
);
639 rb
->lcd_hline(0, LCD_WIDTH
-1, LCD_HEIGHT
-14);
640 rb
->lcd_vline(LCD_WIDTH
/2, LCD_HEIGHT
-14, LCD_HEIGHT
-1);
642 /* draw progress bar */
643 #ifdef HAVE_LCD_COLOR
644 rb
->lcd_set_foreground(LCD_RGBPACK(104, 63, 63));
646 rb
->lcd_fillrect(0, (8*TILE_HEIGHT
+YOFS
)
647 +(LCD_HEIGHT
-14-(8*TILE_HEIGHT
+YOFS
))/4,
648 LCD_WIDTH
*tempscore
/size
,
649 (LCD_HEIGHT
-14-(8*TILE_HEIGHT
+YOFS
))/2);
650 #ifdef HAVE_LCD_COLOR
651 rb
->lcd_set_foreground(LCD_RGBPACK(83, 44, 44));
652 rb
->lcd_drawrect(1, (8*TILE_HEIGHT
+YOFS
)
653 +(LCD_HEIGHT
-14-(8*TILE_HEIGHT
+YOFS
))/4+1,
654 LCD_WIDTH
*tempscore
/size
-1,
655 (LCD_HEIGHT
-14-(8*TILE_HEIGHT
+YOFS
))/2-2);
657 rb
->lcd_drawrect(0, (8*TILE_HEIGHT
+YOFS
)
658 +(LCD_HEIGHT
-14-(8*TILE_HEIGHT
+YOFS
))/4,
659 LCD_WIDTH
*tempscore
/size
+1,
660 (LCD_HEIGHT
-14-(8*TILE_HEIGHT
+YOFS
))/2);
664 rb
->lcd_putsxyf(1, LCD_HEIGHT
-10, "%s %d", title
, bj
->level
);
666 if (bj
->type
== GAME_TYPE_NORMAL
) {
667 rb
->snprintf(str
, 6, "%d", (bj
->level
-1)*LEVEL_PTS
+bj
->score
);
668 rb
->lcd_getstringsize(str
, &w
, &h
);
669 rb
->lcd_putsxy((LCD_WIDTH
-2)-w
, LCD_HEIGHT
-10, str
);
673 #else /* square layout */
675 /* draw separator lines */
677 rb
->lcd_hline(0, LCD_WIDTH
-1, 8*TILE_HEIGHT
+YOFS
);
678 rb
->lcd_vline(BJ_WIDTH
*TILE_WIDTH
, 0, 8*TILE_HEIGHT
+YOFS
);
679 rb
->lcd_vline(LCD_WIDTH
/2, 8*TILE_HEIGHT
+YOFS
, LCD_HEIGHT
-1);
681 /* draw progress bar */
682 #ifdef HAVE_LCD_COLOR
683 rb
->lcd_set_foreground(LCD_RGBPACK(104, 63, 63));
685 rb
->lcd_fillrect(BJ_WIDTH
*TILE_WIDTH
+(LCD_WIDTH
-BJ_WIDTH
*TILE_WIDTH
)/4,
686 (8*TILE_HEIGHT
+YOFS
)-(8*TILE_HEIGHT
+YOFS
)*tempscore
/size
,
687 (LCD_WIDTH
-BJ_WIDTH
*TILE_WIDTH
)/2,
688 (8*TILE_HEIGHT
+YOFS
)*tempscore
/size
);
689 #ifdef HAVE_LCD_COLOR
690 rb
->lcd_set_foreground(LCD_RGBPACK(83, 44, 44));
691 rb
->lcd_drawrect(BJ_WIDTH
*TILE_WIDTH
+(LCD_WIDTH
-BJ_WIDTH
*TILE_WIDTH
)/4+1,
692 (8*TILE_HEIGHT
+YOFS
)-(8*TILE_HEIGHT
+YOFS
)
694 (LCD_WIDTH
-BJ_WIDTH
*TILE_WIDTH
)/2-2,
695 (8*TILE_HEIGHT
+YOFS
)*tempscore
/size
-1);
697 rb
->lcd_drawrect(BJ_WIDTH
*TILE_WIDTH
+(LCD_WIDTH
-BJ_WIDTH
*TILE_WIDTH
)/4,
698 (8*TILE_HEIGHT
+YOFS
)-(8*TILE_HEIGHT
+YOFS
)
700 (LCD_WIDTH
-BJ_WIDTH
*TILE_WIDTH
)/2,
701 (8*TILE_HEIGHT
+YOFS
)*tempscore
/size
+1);
705 rb
->lcd_putsxyf(1, LCD_HEIGHT
-(LCD_HEIGHT
-(8*TILE_HEIGHT
+YOFS
))/2-3,"%s %d",
708 if (bj
->type
== GAME_TYPE_NORMAL
) {
709 rb
->snprintf(str
, 6, "%d", (bj
->level
-1)*LEVEL_PTS
+bj
->score
);
710 rb
->lcd_getstringsize(str
, &w
, &h
);
711 rb
->lcd_putsxy((LCD_WIDTH
-2)-w
,
712 LCD_HEIGHT
-(LCD_HEIGHT
-(8*TILE_HEIGHT
+YOFS
))/2-3, str
);
720 /*****************************************************************************
721 * jewels_putjewels() makes the jewels fall to fill empty spots and adds
722 * new random jewels at the empty spots at the top of each row.
723 ******************************************************************************/
724 static void jewels_putjewels(struct game_context
* bj
){
727 long lasttick
, currenttick
;
729 /* loop to make all the jewels fall */
731 /* mark falling jewels and add new jewels to hidden top row*/
734 for(j
=0; j
<BJ_WIDTH
; j
++) {
735 if(bj
->playboard
[1][j
].type
== 0) {
736 bj
->playboard
[0][j
].type
= rb
->rand()%bj
->num_jewels
+1;
738 for(i
=BJ_HEIGHT
-2; i
>=0; i
--) {
739 if(!mark
&& bj
->playboard
[i
+1][j
].type
== 0) {
743 if(mark
) bj
->playboard
[i
][j
].falling
= true;
745 /*if(bj->playboard[1][j].falling) {
746 bj->playboard[0][j].type = rb->rand()%bj->num_jewels+1;
747 bj->playboard[0][j].falling = true;
752 /* break if there are no falling jewels */
755 /* animate falling jewels */
756 lasttick
= *rb
->current_tick
;
758 for(k
=1; k
<=8; k
++) {
759 for(i
=BJ_HEIGHT
-2; i
>=0; i
--) {
760 for(j
=0; j
<BJ_WIDTH
; j
++) {
761 if(bj
->playboard
[i
][j
].falling
&&
762 bj
->playboard
[i
][j
].type
!= 0) {
763 /* clear old position */
764 #ifdef HAVE_LCD_COLOR
766 rb
->lcd_set_foreground(rb
->lcd_get_background());
768 rb
->lcd_set_foreground(jewels_bkgd
[(i
-1+j
)%2]);
770 rb
->lcd_fillrect(j
*TILE_WIDTH
, (i
-1)*TILE_HEIGHT
+YOFS
,
771 TILE_WIDTH
, TILE_HEIGHT
);
772 if(bj
->playboard
[i
+1][j
].type
== 0) {
773 rb
->lcd_set_foreground(jewels_bkgd
[(i
+j
)%2]);
774 rb
->lcd_fillrect(j
*TILE_WIDTH
, i
*TILE_HEIGHT
+YOFS
,
775 TILE_WIDTH
, TILE_HEIGHT
);
778 rb
->lcd_set_drawmode(DRMODE_SOLID
|DRMODE_INVERSEVID
);
779 rb
->lcd_fillrect(j
*TILE_WIDTH
, (i
-1)*TILE_HEIGHT
+YOFS
,
780 TILE_WIDTH
, TILE_HEIGHT
);
781 if(bj
->playboard
[i
+1][j
].type
== 0) {
782 rb
->lcd_fillrect(j
*TILE_WIDTH
, i
*TILE_HEIGHT
+YOFS
,
783 TILE_WIDTH
, TILE_HEIGHT
);
785 rb
->lcd_set_drawmode(DRMODE_SOLID
);
788 /* draw new position */
789 #ifdef HAVE_LCD_COLOR
790 rb
->lcd_bitmap_transparent_part(jewels
, 0,
791 TILE_HEIGHT
*(bj
->playboard
[i
][j
].type
),
796 (i
-1)*TILE_HEIGHT
+YOFS
+
797 ((((TILE_HEIGHT
<<10)*k
)/8)>>10),
798 TILE_WIDTH
, TILE_HEIGHT
);
800 rb
->lcd_bitmap_part(jewels
, 0,
801 TILE_HEIGHT
*(bj
->playboard
[i
][j
].type
),
806 (i
-1)*TILE_HEIGHT
+YOFS
+
807 ((((TILE_HEIGHT
<<10)*k
)/8)>>10),
808 TILE_WIDTH
, TILE_HEIGHT
);
814 rb
->lcd_update_rect(0, 0, TILE_WIDTH
*8, LCD_HEIGHT
);
817 /* framerate limiting */
818 currenttick
= *rb
->current_tick
;
819 if(currenttick
-lasttick
< HZ
/MAX_FPS
) {
820 rb
->sleep((HZ
/MAX_FPS
)-(currenttick
-lasttick
));
824 lasttick
= currenttick
;
827 /* shift jewels down */
828 for(j
=0; j
<BJ_WIDTH
; j
++) {
829 for(i
=BJ_HEIGHT
-1; i
>=1; i
--) {
830 if(bj
->playboard
[i
-1][j
].falling
) {
831 bj
->playboard
[i
][j
].type
= bj
->playboard
[i
-1][j
].type
;
836 /* clear out top row */
837 for(j
=0; j
<BJ_WIDTH
; j
++) {
838 bj
->playboard
[0][j
].type
= 0;
841 /* mark everything not falling */
842 for(i
=0; i
<BJ_HEIGHT
; i
++) {
843 for(j
=0; j
<BJ_WIDTH
; j
++) {
844 bj
->playboard
[i
][j
].falling
= false;
850 /*****************************************************************************
851 * jewels_clearjewels() finds all the connected rows and columns and
852 * calculates and returns the points earned.
853 ******************************************************************************/
854 static unsigned int jewels_clearjewels(struct game_context
* bj
) {
857 unsigned int points
= 0;
859 /* check for connected rows */
860 for(i
=1; i
<BJ_HEIGHT
; i
++) {
863 for(j
=0; j
<BJ_WIDTH
; j
++) {
864 if(bj
->playboard
[i
][j
].type
== last
&&
865 bj
->playboard
[i
][j
].type
!= 0 &&
866 bj
->playboard
[i
][j
].type
<= MAX_NUM_JEWELS
) {
871 points
+= bj
->segments
;
872 bj
->playboard
[i
][j
].delete = true;
873 bj
->playboard
[i
][j
-1].delete = true;
874 bj
->playboard
[i
][j
-2].delete = true;
877 bj
->playboard
[i
][j
].delete = true;
881 last
= bj
->playboard
[i
][j
].type
;
886 /* check for connected columns */
887 for(j
=0; j
<BJ_WIDTH
; j
++) {
890 for(i
=1; i
<BJ_HEIGHT
; i
++) {
891 if(bj
->playboard
[i
][j
].type
!= 0 &&
892 bj
->playboard
[i
][j
].type
== last
&&
893 bj
->playboard
[i
][j
].type
<= MAX_NUM_JEWELS
) {
898 points
+= bj
->segments
;
899 bj
->playboard
[i
][j
].delete = true;
900 bj
->playboard
[i
-1][j
].delete = true;
901 bj
->playboard
[i
-2][j
].delete = true;
904 bj
->playboard
[i
][j
].delete = true;
908 last
= bj
->playboard
[i
][j
].type
;
913 /* clear deleted jewels */
914 for(i
=1; i
<BJ_HEIGHT
; i
++) {
915 for(j
=0; j
<BJ_WIDTH
; j
++) {
916 if(bj
->playboard
[i
][j
].delete) {
917 bj
->playboard
[i
][j
].delete = false;
918 bj
->playboard
[i
][j
].type
= 0;
926 /*****************************************************************************
927 * jewels_runboard() runs the board until it settles in a fixed state and
928 * returns points earned.
929 ******************************************************************************/
930 static unsigned int jewels_runboard(struct game_context
* bj
) {
931 unsigned int points
= 0;
936 while((ret
= jewels_clearjewels(bj
)) > 0) {
938 jewels_drawboard(bj
);
939 jewels_putjewels(bj
);
945 /*****************************************************************************
946 * jewels_swapjewels() swaps two jewels as long as it results in points and
947 * returns points earned.
948 ******************************************************************************/
949 static unsigned int jewels_swapjewels(struct game_context
* bj
,
950 int x
, int y
, int direc
) {
952 int horzmod
, vertmod
;
955 unsigned int points
= 0;
956 long lasttick
, currenttick
;
958 /* check for invalid parameters */
959 if(x
< 0 || x
>= BJ_WIDTH
|| y
< 0 || y
>= BJ_HEIGHT
-1 ||
960 direc
< SWAP_UP
|| direc
> SWAP_LEFT
) {
964 /* check for invalid directions */
965 if((x
== 0 && direc
== SWAP_LEFT
) ||
966 (x
== BJ_WIDTH
-1 && direc
== SWAP_RIGHT
) ||
967 (y
== 0 && direc
== SWAP_UP
) ||
968 (y
== BJ_HEIGHT
-2 && direc
== SWAP_DOWN
)) {
972 /* set direction variables */
978 movelen
= TILE_HEIGHT
;
982 movelen
= TILE_WIDTH
;
986 movelen
= TILE_HEIGHT
;
990 movelen
= TILE_WIDTH
;
995 lasttick
= *rb
->current_tick
;
997 /* animate swapping jewels */
998 for(k
=0; k
<=8; k
++) {
999 /* clear old position */
1000 #ifdef HAVE_LCD_COLOR
1001 rb
->lcd_set_foreground(jewels_bkgd
[(x
+y
)%2]);
1002 rb
->lcd_fillrect(x
*TILE_WIDTH
,
1004 TILE_WIDTH
, TILE_HEIGHT
);
1005 rb
->lcd_set_foreground(jewels_bkgd
[(x
+horzmod
+y
+vertmod
)%2]);
1006 rb
->lcd_fillrect((x
+horzmod
)*TILE_WIDTH
,
1007 (y
+vertmod
)*TILE_HEIGHT
+YOFS
,
1008 TILE_WIDTH
, TILE_HEIGHT
);
1010 rb
->lcd_set_drawmode(DRMODE_SOLID
|DRMODE_INVERSEVID
);
1011 rb
->lcd_fillrect(x
*TILE_WIDTH
,
1013 TILE_WIDTH
, TILE_HEIGHT
);
1014 rb
->lcd_fillrect((x
+horzmod
)*TILE_WIDTH
,
1015 (y
+vertmod
)*TILE_HEIGHT
+YOFS
,
1016 TILE_WIDTH
, TILE_HEIGHT
);
1017 rb
->lcd_set_drawmode(DRMODE_SOLID
);
1019 /* draw new position */
1020 #ifdef HAVE_LCD_COLOR
1021 rb
->lcd_bitmap_transparent_part(jewels
,
1022 0, TILE_HEIGHT
*(bj
->playboard
1023 [y
+1+vertmod
][x
+horzmod
].type
),
1024 STRIDE( SCREEN_MAIN
,
1025 BMPWIDTH_jewels
, BMPHEIGHT_jewels
),
1026 (x
+horzmod
)*TILE_WIDTH
-horzmod
*
1027 ((((movelen
<<10)*k
)/8)>>10),
1028 (y
+vertmod
)*TILE_HEIGHT
-vertmod
*
1029 ((((movelen
<<10)*k
)/8)>>10)+YOFS
,
1030 TILE_WIDTH
, TILE_HEIGHT
);
1031 rb
->lcd_bitmap_transparent_part(jewels
,
1032 0, TILE_HEIGHT
*(bj
->playboard
[y
+1][x
].type
),
1033 STRIDE( SCREEN_MAIN
,
1034 BMPWIDTH_jewels
, BMPHEIGHT_jewels
),
1035 x
*TILE_WIDTH
+horzmod
*
1036 ((((movelen
<<10)*k
)/8)>>10),
1037 y
*TILE_HEIGHT
+vertmod
*
1038 ((((movelen
<<10)*k
)/8)>>10)+YOFS
,
1039 TILE_WIDTH
, TILE_HEIGHT
);
1041 rb
->lcd_bitmap_part(jewels
,
1042 0, TILE_HEIGHT
*(bj
->playboard
1043 [y
+1+vertmod
][x
+horzmod
].type
),
1044 STRIDE( SCREEN_MAIN
,
1045 BMPWIDTH_jewels
, BMPHEIGHT_jewels
),
1046 (x
+horzmod
)*TILE_WIDTH
-horzmod
*
1047 ((((movelen
<<10)*k
)/8)>>10),
1048 (y
+vertmod
)*TILE_HEIGHT
-vertmod
*
1049 ((((movelen
<<10)*k
)/8)>>10)+YOFS
,
1050 TILE_WIDTH
, TILE_HEIGHT
);
1051 rb
->lcd_set_drawmode(DRMODE_FG
);
1052 rb
->lcd_bitmap_part(jewels
,
1053 0, TILE_HEIGHT
*(bj
->playboard
[y
+1][x
].type
),
1054 STRIDE( SCREEN_MAIN
,
1055 BMPWIDTH_jewels
, BMPHEIGHT_jewels
),
1056 x
*TILE_WIDTH
+horzmod
*
1057 ((((movelen
<<10)*k
)/8)>>10),
1058 y
*TILE_HEIGHT
+vertmod
*
1059 ((((movelen
<<10)*k
)/8)>>10)+YOFS
,
1060 TILE_WIDTH
, TILE_HEIGHT
);
1061 rb
->lcd_set_drawmode(DRMODE_SOLID
);
1064 rb
->lcd_update_rect(0, 0, TILE_WIDTH
*8, LCD_HEIGHT
);
1067 /* framerate limiting */
1068 currenttick
= *rb
->current_tick
;
1069 if(currenttick
-lasttick
< HZ
/MAX_FPS
) {
1070 rb
->sleep((HZ
/MAX_FPS
)-(currenttick
-lasttick
));
1074 lasttick
= currenttick
;
1078 int temp
= bj
->playboard
[y
+1][x
].type
;
1079 bj
->playboard
[y
+1][x
].type
=
1080 bj
->playboard
[y
+1+vertmod
][x
+horzmod
].type
;
1081 bj
->playboard
[y
+1+vertmod
][x
+horzmod
].type
= temp
;
1085 points
= jewels_runboard(bj
);
1096 /*****************************************************************************
1097 * jewels_movesavail() uses pattern matching to see if there are any
1098 * available move left.
1099 ******************************************************************************/
1100 static bool jewels_movesavail(struct game_context
* bj
) {
1105 for(i
=1; i
<BJ_HEIGHT
; i
++) {
1106 for(j
=0; j
<BJ_WIDTH
; j
++) {
1107 mytype
= bj
->playboard
[i
][j
].type
;
1108 if(mytype
== 0 || mytype
> MAX_NUM_JEWELS
) continue;
1110 /* check horizontal patterns */
1111 if(j
<= BJ_WIDTH
-3) {
1113 if(bj
->playboard
[i
-1][j
+1].type
== mytype
) {
1114 if(bj
->playboard
[i
-1][j
+2].type
== mytype
)
1115 {moves
= true; break;}
1116 if(bj
->playboard
[i
][j
+2].type
== mytype
)
1117 {moves
= true; break;}
1119 if(bj
->playboard
[i
][j
+1].type
== mytype
) {
1120 if(bj
->playboard
[i
-1][j
+2].type
== mytype
)
1121 {moves
= true; break;}
1125 if(j
<= BJ_WIDTH
-4) {
1126 if(bj
->playboard
[i
][j
+3].type
== mytype
) {
1127 if(bj
->playboard
[i
][j
+1].type
== mytype
)
1128 {moves
= true; break;}
1129 if(bj
->playboard
[i
][j
+2].type
== mytype
)
1130 {moves
= true; break;}
1134 if(i
< BJ_HEIGHT
-1) {
1135 if(bj
->playboard
[i
][j
+1].type
== mytype
) {
1136 if(bj
->playboard
[i
+1][j
+2].type
== mytype
)
1137 {moves
= true; break;}
1139 if(bj
->playboard
[i
+1][j
+1].type
== mytype
) {
1140 if(bj
->playboard
[i
][j
+2].type
== mytype
)
1141 {moves
= true; break;}
1142 if(bj
->playboard
[i
+1][j
+2].type
== mytype
)
1143 {moves
= true; break;}
1148 /* check vertical patterns */
1149 if(i
<= BJ_HEIGHT
-3) {
1151 if(bj
->playboard
[i
+1][j
-1].type
== mytype
) {
1152 if(bj
->playboard
[i
+2][j
-1].type
== mytype
)
1153 {moves
= true; break;}
1154 if(bj
->playboard
[i
+2][j
].type
== mytype
)
1155 {moves
= true; break;}
1157 if(bj
->playboard
[i
+1][j
].type
== mytype
) {
1158 if(bj
->playboard
[i
+2][j
-1].type
== mytype
)
1159 {moves
= true; break;}
1163 if(i
<= BJ_HEIGHT
-4) {
1164 if(bj
->playboard
[i
+3][j
].type
== mytype
) {
1165 if(bj
->playboard
[i
+1][j
].type
== mytype
)
1166 {moves
= true; break;}
1167 if(bj
->playboard
[i
+2][j
].type
== mytype
)
1168 {moves
= true; break;}
1172 if(j
< BJ_WIDTH
-1) {
1173 if(bj
->playboard
[i
+1][j
].type
== mytype
) {
1174 if(bj
->playboard
[i
+2][j
+1].type
== mytype
)
1175 {moves
= true; break;}
1177 if(bj
->playboard
[i
+1][j
+1].type
== mytype
) {
1178 if(bj
->playboard
[i
+2][j
].type
== mytype
)
1179 {moves
= true; break;}
1180 if (bj
->playboard
[i
+2][j
+1].type
== mytype
)
1181 {moves
= true; break;}
1191 /*****************************************************************************
1192 * jewels_puzzle_is_finished() checks if the puzzle is finished.
1193 ******************************************************************************/
1194 static bool jewels_puzzle_is_finished(struct game_context
* bj
) {
1196 for(i
=0; i
<BJ_HEIGHT
; i
++) {
1197 for(j
=0; j
<BJ_WIDTH
; j
++) {
1198 int mytype
= bj
->playboard
[i
][j
].type
;
1199 if(mytype
>MAX_NUM_JEWELS
) {
1200 mytype
-= MAX_NUM_JEWELS
;
1201 if(mytype
&PUZZLE_TILE_UP
) {
1202 if(i
==0 || bj
->playboard
[i
-1][j
].type
<=MAX_NUM_JEWELS
||
1203 !((bj
->playboard
[i
-1][j
].type
-MAX_NUM_JEWELS
)
1207 if(mytype
&PUZZLE_TILE_DOWN
) {
1208 if(i
==BJ_HEIGHT
-1 ||
1209 bj
->playboard
[i
+1][j
].type
<=MAX_NUM_JEWELS
||
1210 !((bj
->playboard
[i
+1][j
].type
-MAX_NUM_JEWELS
)
1214 if(mytype
&PUZZLE_TILE_LEFT
) {
1215 if(j
==0 || bj
->playboard
[i
][j
-1].type
<=MAX_NUM_JEWELS
||
1216 !((bj
->playboard
[i
][j
-1].type
-MAX_NUM_JEWELS
)
1217 &PUZZLE_TILE_RIGHT
))
1220 if(mytype
&PUZZLE_TILE_RIGHT
) {
1222 bj
->playboard
[i
][j
+1].type
<=MAX_NUM_JEWELS
||
1223 !((bj
->playboard
[i
][j
+1].type
-MAX_NUM_JEWELS
)
1233 /*****************************************************************************
1234 * jewels_initlevel() initialises a level.
1235 ******************************************************************************/
1236 static unsigned int jewels_initlevel(struct game_context
* bj
) {
1237 unsigned int points
= 0;
1240 case GAME_TYPE_NORMAL
:
1241 bj
->num_jewels
= MAX_NUM_JEWELS
;
1244 case GAME_TYPE_PUZZLE
:
1247 struct puzzle_tile
*tile
;
1249 bj
->num_jewels
= puzzle_levels
[bj
->level
-1].num_jewels
;
1251 for(i
=0; i
<BJ_HEIGHT
; i
++) {
1252 for(j
=0; j
<BJ_WIDTH
; j
++) {
1253 bj
->playboard
[i
][j
].type
= (rb
->rand()%bj
->num_jewels
)+1;
1254 bj
->playboard
[i
][j
].falling
= false;
1255 bj
->playboard
[i
][j
].delete = false;
1258 jewels_runboard(bj
);
1259 tile
= puzzle_levels
[bj
->level
-1].tiles
;
1260 for(i
=0; i
<puzzle_levels
[bj
->level
-1].num_tiles
; i
++, tile
++) {
1261 bj
->playboard
[tile
->y
+1][tile
->x
].type
= MAX_NUM_JEWELS
1268 jewels_drawboard(bj
);
1270 /* run the play board */
1271 jewels_putjewels(bj
);
1272 points
+= jewels_runboard(bj
);
1276 /*****************************************************************************
1277 * jewels_init() initializes jewels data structures.
1278 ******************************************************************************/
1279 static void jewels_init(struct game_context
* bj
) {
1280 /* seed the rand generator */
1281 rb
->srand(*rb
->current_tick
);
1283 bj
->type
= bj
->tmp_type
;
1290 /* clear playing board */
1291 rb
->memset(bj
->playboard
, 0, sizeof(bj
->playboard
));
1293 bj
->score
+= jewels_initlevel(bj
);
1294 } while(!jewels_movesavail(bj
));
1297 /*****************************************************************************
1298 * jewels_nextlevel() advances the game to the next bj->level and returns
1300 ******************************************************************************/
1301 static void jewels_nextlevel(struct game_context
* bj
) {
1303 unsigned int points
= 0;
1306 case GAME_TYPE_NORMAL
:
1307 /* roll over score, change and display level */
1308 while(bj
->score
>= LEVEL_PTS
) {
1309 bj
->score
-= LEVEL_PTS
;
1311 rb
->splashf(HZ
*2, "Level %d", bj
->level
);
1312 jewels_drawboard(bj
);
1315 /* randomly clear some jewels */
1316 for(i
=0; i
<16; i
++) {
1320 if(bj
->playboard
[y
][x
].type
!= 0) {
1322 bj
->playboard
[y
][x
].type
= 0;
1327 case GAME_TYPE_PUZZLE
:
1329 rb
->splashf(HZ
*2, "Level %d", bj
->level
);
1333 points
+= jewels_initlevel(bj
);
1334 bj
->score
+= points
;
1337 static bool jewels_help(void)
1339 static char *help_text
[] = {
1340 "Jewels", "", "Aim", "",
1341 "Swap", "pairs", "of", "jewels", "to", "form", "connected",
1342 "segments", "of", "three", "or", "more", "of", "the", "same",
1344 "The", "goal", "of", "the", "game", "is", "to", "score", "as", "many",
1345 "points", "as", "possible", "before", "running", "out", "of",
1346 "available", "moves.", "", "",
1349 #ifdef JEWELS_SCROLLWHEEL
1353 HK_SELECT
, "to", "select", "",
1354 HK_CANCEL
, "to", "go", "to", "menu"
1356 static struct style_text formation
[]={
1357 { 0, TEXT_CENTER
|TEXT_UNDERLINE
},
1363 rb
->lcd_setfont(FONT_UI
);
1364 if (display_text(ARRAYLEN(help_text
), help_text
, formation
, NULL
, true))
1366 rb
->lcd_setfont(FONT_SYSFIXED
);
1371 static bool _ingame
;
1372 static int jewels_menu_cb(int action
, const struct menu_item_ex
*this_item
)
1374 int i
= ((intptr_t)this_item
);
1375 if(action
== ACTION_REQUEST_MENUITEM
1376 && !_ingame
&& (i
==0 || i
==6))
1377 return ACTION_EXIT_MENUITEM
;
1380 /*****************************************************************************
1381 * jewels_game_menu() shows the game menu.
1382 ******************************************************************************/
1383 static int jewels_game_menu(struct game_context
* bj
, bool ingame
)
1385 rb
->button_clear_queue();
1390 static struct opt_items mode
[] = {
1395 MENUITEM_STRINGLIST (main_menu
, "Jewels Menu", jewels_menu_cb
,
1402 "Quit without Saving",
1406 switch (rb
->do_menu(&main_menu
, &choice
, NULL
, false)) {
1410 rb
->remove(SAVE_FILE
);
1416 rb
->set_option("Mode", &bj
->tmp_type
, INT
, mode
, 2, NULL
);
1423 highscore_show(-1, highscores
, NUM_SCORES
, true);
1426 playback_control(NULL
);
1432 rb
->splash(HZ
*1, "Saving game ...");
1433 jewels_savegame(bj
);
1436 case MENU_ATTACHED_USB
:
1444 static int jewels_main(struct game_context
* bj
) {
1447 bool selected
= false;
1450 bool loaded
= jewels_loadgame(bj
);
1451 resume_file
= loaded
;
1452 if (jewels_game_menu(bj
, loaded
)!=0)
1455 resume_file
= false;
1457 /* refresh the board */
1458 jewels_drawboard(bj
);
1460 /* display the cursor */
1462 rb
->lcd_set_drawmode(DRMODE_COMPLEMENT
);
1463 rb
->lcd_fillrect(x
*TILE_WIDTH
, y
*TILE_HEIGHT
+YOFS
,
1464 TILE_WIDTH
, TILE_HEIGHT
);
1465 rb
->lcd_set_drawmode(DRMODE_SOLID
);
1467 rb
->lcd_drawrect(x
*TILE_WIDTH
, y
*TILE_HEIGHT
+YOFS
,
1468 TILE_WIDTH
, TILE_HEIGHT
);
1470 rb
->lcd_update_rect(x
*TILE_WIDTH
, y
*TILE_HEIGHT
+YOFS
,
1471 TILE_WIDTH
, TILE_HEIGHT
);
1473 /* handle game button presses */
1475 button
= rb
->button_get(true);
1477 case JEWELS_LEFT
: /* move cursor left */
1478 case (JEWELS_LEFT
|BUTTON_REPEAT
):
1480 bj
->score
+= jewels_swapjewels(bj
, x
, y
, SWAP_LEFT
);
1483 x
= (x
+BJ_WIDTH
-1)%BJ_WIDTH
;
1487 case JEWELS_RIGHT
: /* move cursor right */
1488 case (JEWELS_RIGHT
|BUTTON_REPEAT
):
1490 bj
->score
+= jewels_swapjewels(bj
, x
, y
, SWAP_RIGHT
);
1497 case JEWELS_DOWN
: /* move cursor down */
1498 case (JEWELS_DOWN
|BUTTON_REPEAT
):
1500 bj
->score
+= jewels_swapjewels(bj
, x
, y
, SWAP_DOWN
);
1503 y
= (y
+1)%(BJ_HEIGHT
-1);
1507 case JEWELS_UP
: /* move cursor up */
1508 case (JEWELS_UP
|BUTTON_REPEAT
):
1510 bj
->score
+= jewels_swapjewels(bj
, x
, y
, SWAP_UP
);
1513 y
= (y
+(BJ_HEIGHT
-1)-1)%(BJ_HEIGHT
-1);
1517 #ifdef JEWELS_SCROLLWHEEL
1518 case JEWELS_PREV
: /* scroll backwards */
1519 case (JEWELS_PREV
|BUTTON_REPEAT
):
1522 y
= (y
+(BJ_HEIGHT
-1)-1)%(BJ_HEIGHT
-1);
1524 x
= (x
+BJ_WIDTH
-1)%BJ_WIDTH
;
1528 case JEWELS_NEXT
: /* scroll forwards */
1529 case (JEWELS_NEXT
|BUTTON_REPEAT
):
1531 if(x
== BJ_WIDTH
-1) {
1532 y
= (y
+1)%(BJ_HEIGHT
-1);
1539 case JEWELS_SELECT
: /* toggle selected */
1540 selected
= !selected
;
1543 #ifdef JEWELS_RC_CANCEL
1544 case JEWELS_RC_CANCEL
:
1546 case JEWELS_CANCEL
: /* end game */
1547 if (jewels_game_menu(bj
, true)!=0)
1552 if (rb
->default_event_handler (button
) == SYS_USB_CONNECTED
)
1553 return PLUGIN_USB_CONNECTED
;
1558 case GAME_TYPE_NORMAL
:
1559 if(bj
->score
>= LEVEL_PTS
)
1560 jewels_nextlevel(bj
);
1562 case GAME_TYPE_PUZZLE
:
1563 if (jewels_puzzle_is_finished(bj
)) {
1564 if (bj
->level
< NUM_PUZZLE_LEVELS
) {
1565 jewels_nextlevel(bj
);
1567 rb
->splash(2*HZ
, "Congratulations!");
1568 rb
->splash(2*HZ
, "You have finished the game!");
1569 if (jewels_game_menu(bj
, false)!=0) {
1577 if (!jewels_movesavail(bj
)) {
1579 case GAME_TYPE_NORMAL
:
1580 rb
->splash(HZ
*2, "Game Over!");
1581 rb
->lcd_clear_display();
1582 bj
->score
+= (bj
->level
-1)*LEVEL_PTS
;
1583 position
=highscore_update(bj
->score
, bj
->level
, "",
1584 highscores
, NUM_SCORES
);
1588 rb
->splash(HZ
*2, "New High Score");
1589 highscore_show(position
, highscores
, NUM_SCORES
, true);
1592 case GAME_TYPE_PUZZLE
:
1593 rb
->splash(2*HZ
, "Game Over");
1596 if (jewels_game_menu(bj
, false)!=0) {
1603 /* this is the plugin entry point */
1604 enum plugin_status
plugin_start(const void* parameter
)
1608 /* load high scores */
1609 highscore_load(SCORE_FILE
, highscores
, NUM_SCORES
);
1611 rb
->lcd_setfont(FONT_SYSFIXED
);
1613 rb
->lcd_set_backdrop(NULL
);
1616 struct game_context bj
;
1617 bj
.tmp_type
= GAME_TYPE_NORMAL
;
1619 highscore_save(SCORE_FILE
, highscores
, NUM_SCORES
);
1620 rb
->lcd_setfont(FONT_UI
);