diff options
author | Adam Boot <rotator@gmail.com> | 2005-11-05 17:18:52 +0000 |
---|---|---|
committer | Adam Boot <rotator@gmail.com> | 2005-11-05 17:18:52 +0000 |
commit | 63fbc0729f66ad55413579da4cb93b9ea51db223 (patch) | |
tree | 78761703541d167e266ac0bb4011095d4f46c5af /apps/plugins | |
parent | 0bfcabeafdf31dacf60eb4d61085087dc4206e3e (diff) | |
download | rockbox-63fbc0729f66ad55413579da4cb93b9ea51db223.tar.gz rockbox-63fbc0729f66ad55413579da4cb93b9ea51db223.zip |
New plugin: Bejeweled game for Recorder, Ondio, and iRiver.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@7758 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/plugins')
-rw-r--r-- | apps/plugins/SOURCES | 1 | ||||
-rw-r--r-- | apps/plugins/jewels.c | 1055 |
2 files changed, 1056 insertions, 0 deletions
diff --git a/apps/plugins/SOURCES b/apps/plugins/SOURCES index efe6439bf0..6c5d6f243f 100644 --- a/apps/plugins/SOURCES +++ b/apps/plugins/SOURCES | |||
@@ -18,6 +18,7 @@ viewer.c | |||
18 | dict.c | 18 | dict.c |
19 | 19 | ||
20 | #ifdef HAVE_LCD_BITMAP /* Recorder/Ondio models only */ | 20 | #ifdef HAVE_LCD_BITMAP /* Recorder/Ondio models only */ |
21 | bejeweled.c | ||
21 | bounce.c | 22 | bounce.c |
22 | calculator.c | 23 | calculator.c |
23 | chip8.c | 24 | chip8.c |
diff --git a/apps/plugins/jewels.c b/apps/plugins/jewels.c new file mode 100644 index 0000000000..f5c1000183 --- /dev/null +++ b/apps/plugins/jewels.c | |||
@@ -0,0 +1,1055 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2005 Adam Boot | ||
11 | * | ||
12 | * All files in this archive are subject to the GNU General Public License. | ||
13 | * See the file COPYING in the source tree root for full license agreement. | ||
14 | * | ||
15 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
16 | * KIND, either express or implied. | ||
17 | * | ||
18 | ****************************************************************************/ | ||
19 | |||
20 | #include "plugin.h" | ||
21 | #include "button.h" | ||
22 | #include "lcd.h" | ||
23 | |||
24 | #ifdef HAVE_LCD_BITMAP | ||
25 | |||
26 | /* save files */ | ||
27 | #define SCORE_FILE PLUGIN_DIR "/bejeweled.score" | ||
28 | #define SAVE_FILE PLUGIN_DIR "/bejeweled.save" | ||
29 | |||
30 | /* final game return status */ | ||
31 | #define BJ_END 3 | ||
32 | #define BJ_USB 2 | ||
33 | #define BJ_QUIT 1 | ||
34 | #define BJ_LOSE 0 | ||
35 | |||
36 | /* button definitions */ | ||
37 | #if CONFIG_KEYPAD == RECORDER_PAD | ||
38 | #define BEJEWELED_QUIT BUTTON_OFF | ||
39 | #define BEJEWELED_START BUTTON_ON | ||
40 | #define BEJEWELED_SELECT BUTTON_PLAY | ||
41 | #define BEJEWELED_RESUME BUTTON_F1 | ||
42 | |||
43 | #elif CONFIG_KEYPAD == ONDIO_PAD | ||
44 | #define BEJEWELED_QUIT BUTTON_OFF | ||
45 | #define BEJEWELED_START BUTTON_RIGHT | ||
46 | #define BEJEWELED_SELECT (BUTTON_MENU|BUTTON_REL) | ||
47 | #define BEJEWELED_SELECT_PRE BUTTON_MENU | ||
48 | #define BEJEWELED_RESUME (BUTTON_MENU|BUTTON_OFF) | ||
49 | |||
50 | #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || (CONFIG_KEYPAD == IRIVER_H300_PAD) | ||
51 | #define BEJEWELED_QUIT BUTTON_OFF | ||
52 | #define BEJEWELED_START BUTTON_ON | ||
53 | #define BEJEWELED_SELECT BUTTON_SELECT | ||
54 | #define BEJEWELED_RESUME BUTTON_MODE | ||
55 | |||
56 | #elif | ||
57 | #error BEJEWELED: Unsupported keypad | ||
58 | #endif | ||
59 | |||
60 | /* swap directions */ | ||
61 | #define SWAP_UP 0 | ||
62 | #define SWAP_RIGHT 1 | ||
63 | #define SWAP_DOWN 2 | ||
64 | #define SWAP_LEFT 3 | ||
65 | |||
66 | /* play board dimension */ | ||
67 | #define BJ_HEIGHT 9 | ||
68 | #define BJ_WIDTH 8 | ||
69 | |||
70 | /* next level threshold */ | ||
71 | #define LEVEL_PTS 100 | ||
72 | |||
73 | /* sleep time for animations (1/x seconds) */ | ||
74 | #define FALL_TIMER 30 | ||
75 | #define SWAP_TIMER 30 | ||
76 | |||
77 | #if (LCD_HEIGHT == 128) && (LCD_WIDTH == 160) | ||
78 | /* Use 16x16 tiles */ | ||
79 | |||
80 | /* size of a tile */ | ||
81 | #define TILE_SZ 16 | ||
82 | |||
83 | /* number of high scores to save */ | ||
84 | #define NUM_SCORES 15 | ||
85 | |||
86 | /* bitmaps for the jewels */ | ||
87 | static unsigned char jewel[8][32] = { | ||
88 | /* empty */ | ||
89 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
90 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
91 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
92 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, | ||
93 | /* square */ | ||
94 | {0x00, 0x00, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, | ||
95 | 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0x00, 0x00, | ||
96 | 0x00, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, | ||
97 | 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0x00}, | ||
98 | /* plus */ | ||
99 | {0x00, 0xe0, 0xe0, 0x60, 0x60, 0x7e, 0x7e, 0x06, | ||
100 | 0x7e, 0x7e, 0x60, 0x60, 0xe0, 0xe0, 0x00, 0x00, | ||
101 | 0x00, 0x03, 0x03, 0x03, 0x03, 0x3f, 0x3f, 0x30, | ||
102 | 0x3f, 0x3f, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00}, | ||
103 | /* triangle */ | ||
104 | {0x00, 0x00, 0x00, 0x00, 0xc0, 0xf0, 0x7c, 0x1e, | ||
105 | 0x7c, 0xf0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
106 | 0x00, 0x30, 0x3c, 0x3f, 0x37, 0x31, 0x30, 0x30, | ||
107 | 0x30, 0x31, 0x37, 0x3f, 0x3c, 0x30, 0x00, 0x00}, | ||
108 | /* diamond */ | ||
109 | {0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, | ||
110 | 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00, 0x00, | ||
111 | 0x00, 0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, | ||
112 | 0x1f, 0x0f, 0x07, 0x03, 0x01, 0x00, 0x00, 0x00}, | ||
113 | /* star */ | ||
114 | {0x00, 0x40, 0xc0, 0xc0, 0xc0, 0xc0, 0xf8, 0xfe, | ||
115 | 0xf8, 0xc0, 0xc0, 0xc0, 0xc0, 0x40, 0x00, 0x00, | ||
116 | 0x00, 0x00, 0x00, 0x30, 0x1f, 0x1f, 0x0f, 0x07, | ||
117 | 0x0f, 0x1f, 0x1f, 0x30, 0x00, 0x00, 0x00, 0x00}, | ||
118 | /* circle */ | ||
119 | {0x00, 0xe0, 0xf8, 0xfc, 0x3c, 0x1e, 0x0e, 0x0e, | ||
120 | 0x0e, 0x1e, 0x3c, 0xfc, 0xf8, 0xe0, 0x00, 0x00, | ||
121 | 0x00, 0x03, 0x0f, 0x1f, 0x1e, 0x3c, 0x38, 0x38, | ||
122 | 0x38, 0x3c, 0x1e, 0x1f, 0x0f, 0x03, 0x00, 0x00}, | ||
123 | /* heart */ | ||
124 | {0x00, 0x78, 0xfc, 0xfe, 0xfe, 0xfc, 0xf8, 0xf0, | ||
125 | 0xf8, 0xfc, 0xfe, 0xfe, 0xfc, 0x78, 0x00, 0x00, | ||
126 | 0x00, 0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, | ||
127 | 0x1f, 0x0f, 0x07, 0x03, 0x01, 0x00, 0x00, 0x00} | ||
128 | }; | ||
129 | |||
130 | #elif (LCD_HEIGHT == 64) && (LCD_WIDTH == 112) | ||
131 | /* Use 8x8 tiles */ | ||
132 | |||
133 | /* size of a tile */ | ||
134 | #define TILE_SZ 8 | ||
135 | |||
136 | /* number of high scores to save */ | ||
137 | #define NUM_SCORES 8 | ||
138 | |||
139 | /* bitmaps for the jewels */ | ||
140 | static unsigned char jewel[8][8] = { | ||
141 | /* empty */ | ||
142 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, | ||
143 | /* square */ | ||
144 | {0x00, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x00}, | ||
145 | /* plus */ | ||
146 | {0x1c, 0x14, 0x77, 0x41, 0x77, 0x14, 0x1c, 0x00}, | ||
147 | /* triangle */ | ||
148 | {0x60, 0x78, 0x4e, 0x43, 0x4e, 0x78, 0x60, 0x00}, | ||
149 | /* diamond */ | ||
150 | {0x08, 0x1c, 0x3e, 0x7f, 0x3e, 0x1c, 0x08, 0x00}, | ||
151 | /* star */ | ||
152 | {0x08, 0x68, 0x3c, 0x1f, 0x3c, 0x68, 0x08, 0x00}, | ||
153 | /* circle */ | ||
154 | {0x1c, 0x3e, 0x63, 0x63, 0x63, 0x3e, 0x1c, 0x00}, | ||
155 | /* heart */ | ||
156 | {0x0e, 0x1f, 0x3e, 0x7c, 0x3e, 0x1f, 0x0e, 0x00} | ||
157 | }; | ||
158 | |||
159 | #elif | ||
160 | #error BEJEWELED: Unsupported LCD size | ||
161 | #endif | ||
162 | |||
163 | /* global rockbox api */ | ||
164 | static struct plugin_api* rb; | ||
165 | |||
166 | /* the tile struct | ||
167 | * type is the jewel number 0-7 | ||
168 | * falling if the jewel is falling | ||
169 | * delete marks the jewel for deletion | ||
170 | */ | ||
171 | struct tile { | ||
172 | int type; | ||
173 | bool falling; | ||
174 | bool delete; | ||
175 | }; | ||
176 | |||
177 | /* the game context struct | ||
178 | * score is the current level score | ||
179 | * segments is the number of cleared segments in the current run | ||
180 | * level is the current level | ||
181 | * highscores is the list of high scores | ||
182 | * resume denotes whether to resume the currently loaded game | ||
183 | * dirty denotes whether the high scores are out of sync with the saved file | ||
184 | * playboard is the game playing board (first row is hidden) | ||
185 | */ | ||
186 | struct game_context { | ||
187 | unsigned int score; | ||
188 | unsigned int segments; | ||
189 | unsigned int level; | ||
190 | unsigned short highscores[NUM_SCORES]; | ||
191 | bool resume; | ||
192 | bool dirty; | ||
193 | struct tile playboard[BJ_WIDTH][BJ_HEIGHT]; | ||
194 | }; | ||
195 | |||
196 | /***************************************************************************** | ||
197 | * bejeweled_init() initializes bejeweled data structures. | ||
198 | ******************************************************************************/ | ||
199 | void bejeweled_init(struct game_context* bj) { | ||
200 | /* seed the rand generator */ | ||
201 | rb->srand(*rb->current_tick); | ||
202 | |||
203 | /* check for resumed game */ | ||
204 | if(bj->resume) { | ||
205 | bj->resume = false; | ||
206 | return; | ||
207 | } | ||
208 | |||
209 | /* reset scoring */ | ||
210 | bj->level = 1; | ||
211 | bj->score = 0; | ||
212 | bj->segments = 0; | ||
213 | |||
214 | /* clear playing board */ | ||
215 | rb->memset(bj->playboard, 0, sizeof(bj->playboard)); | ||
216 | } | ||
217 | |||
218 | /***************************************************************************** | ||
219 | * bejeweled_drawboard() redraws the entire game board. | ||
220 | ******************************************************************************/ | ||
221 | void bejeweled_drawboard(struct game_context* bj) { | ||
222 | int i, j; | ||
223 | int w, h; | ||
224 | unsigned int tempscore; | ||
225 | char *title = "Level"; | ||
226 | char str[6]; | ||
227 | |||
228 | tempscore = (bj->score>LEVEL_PTS ? LEVEL_PTS : bj->score); | ||
229 | |||
230 | /* clear screen */ | ||
231 | rb->lcd_clear_display(); | ||
232 | |||
233 | /* draw separator lines */ | ||
234 | rb->lcd_vline(BJ_WIDTH*TILE_SZ, 0, LCD_HEIGHT); | ||
235 | rb->lcd_hline(BJ_WIDTH*TILE_SZ, LCD_WIDTH, 18); | ||
236 | rb->lcd_hline(BJ_WIDTH*TILE_SZ, LCD_WIDTH, LCD_HEIGHT-10); | ||
237 | |||
238 | /* draw progress bar */ | ||
239 | rb->lcd_fillrect(BJ_WIDTH*TILE_SZ+(LCD_WIDTH-BJ_WIDTH*TILE_SZ)/4, | ||
240 | (LCD_HEIGHT-10)-(((LCD_HEIGHT-10)-18)* | ||
241 | tempscore/LEVEL_PTS), | ||
242 | (LCD_WIDTH-BJ_WIDTH*TILE_SZ)/2, | ||
243 | ((LCD_HEIGHT-10)-18)*tempscore/LEVEL_PTS); | ||
244 | |||
245 | /* dispay playing board */ | ||
246 | for(i=0; i<BJ_HEIGHT-1; i++){ | ||
247 | for(j=0; j<BJ_WIDTH; j++){ | ||
248 | rb->lcd_mono_bitmap(jewel[bj->playboard[j][i+1].type], | ||
249 | j*TILE_SZ, i*TILE_SZ, TILE_SZ, TILE_SZ); | ||
250 | } | ||
251 | } | ||
252 | |||
253 | /* print text */ | ||
254 | rb->lcd_getstringsize(title, &w, &h); | ||
255 | rb->lcd_putsxy(LCD_WIDTH-(LCD_WIDTH-BJ_WIDTH*TILE_SZ)/2-w/2, 1, title); | ||
256 | |||
257 | rb->snprintf(str, 4, "%d", bj->level); | ||
258 | rb->lcd_getstringsize(str, &w, &h); | ||
259 | rb->lcd_putsxy(LCD_WIDTH-(LCD_WIDTH-BJ_WIDTH*TILE_SZ)/2-w/2, 10, str); | ||
260 | |||
261 | rb->snprintf(str, 6, "%d", (bj->level-1)*LEVEL_PTS+bj->score); | ||
262 | rb->lcd_getstringsize(str, &w, &h); | ||
263 | rb->lcd_putsxy(LCD_WIDTH-(LCD_WIDTH-BJ_WIDTH*TILE_SZ)/2-w/2, | ||
264 | LCD_HEIGHT-8, | ||
265 | str); | ||
266 | |||
267 | rb->lcd_update(); | ||
268 | } | ||
269 | |||
270 | /***************************************************************************** | ||
271 | * bejeweled_putjewels() makes the jewels fall to fill empty spots and adds | ||
272 | * new random jewels at the empty spots at the top of each row. | ||
273 | ******************************************************************************/ | ||
274 | void bejeweled_putjewels(struct game_context* bj){ | ||
275 | int i, j, k; | ||
276 | bool mark, done; | ||
277 | |||
278 | /* loop to make all the jewels fall */ | ||
279 | while(true) { | ||
280 | /* mark falling jewels and add new jewels to hidden top row*/ | ||
281 | mark = false; | ||
282 | done = true; | ||
283 | for(j=0; j<BJ_WIDTH; j++) { | ||
284 | if(bj->playboard[j][1].type == 0) { | ||
285 | bj->playboard[j][0].type = rb->rand()%7+1; | ||
286 | } | ||
287 | for(i=BJ_HEIGHT-2; i>=0; i--) { | ||
288 | if(!mark && bj->playboard[j][i+1].type == 0) { | ||
289 | mark = true; | ||
290 | done = false; | ||
291 | } | ||
292 | if(mark) bj->playboard[j][i].falling = true; | ||
293 | } | ||
294 | /*if(bj->playboard[1][j].falling) { | ||
295 | bj->playboard[0][j].type = rb->rand()%7+1; | ||
296 | bj->playboard[0][j].falling = true; | ||
297 | }*/ | ||
298 | mark = false; | ||
299 | } | ||
300 | |||
301 | /* break if there are no falling jewels */ | ||
302 | if(done) break; | ||
303 | |||
304 | /* animate falling jewels */ | ||
305 | for(k=TILE_SZ/8; k<=TILE_SZ; k+=TILE_SZ/8) { | ||
306 | rb->sleep(HZ/FALL_TIMER); | ||
307 | for(i=0; i<BJ_HEIGHT-1; i++) { | ||
308 | for(j=0; j<BJ_WIDTH; j++) { | ||
309 | if(bj->playboard[j][i].falling && | ||
310 | bj->playboard[j][i].type != 0) { | ||
311 | /* clear old position */ | ||
312 | rb->lcd_mono_bitmap(jewel[0], | ||
313 | j*TILE_SZ, | ||
314 | (i-1)*TILE_SZ+k-2, | ||
315 | TILE_SZ, TILE_SZ); | ||
316 | /* draw new position */ | ||
317 | rb->lcd_mono_bitmap(jewel[bj->playboard[j][i].type], | ||
318 | j*TILE_SZ, | ||
319 | (i-1)*TILE_SZ+k, | ||
320 | TILE_SZ, TILE_SZ); | ||
321 | } | ||
322 | } | ||
323 | } | ||
324 | rb->lcd_update(); | ||
325 | } | ||
326 | |||
327 | /* shift jewels down */ | ||
328 | for(j=0; j<BJ_WIDTH; j++) { | ||
329 | for(i=BJ_HEIGHT-1; i>=1; i--) { | ||
330 | if(bj->playboard[j][i-1].falling) { | ||
331 | bj->playboard[j][i].type = bj->playboard[j][i-1].type; | ||
332 | } | ||
333 | } | ||
334 | } | ||
335 | |||
336 | /* clear out top row */ | ||
337 | for(j=0; j<BJ_WIDTH; j++) { | ||
338 | bj->playboard[j][0].type = 0; | ||
339 | } | ||
340 | |||
341 | /* mark everything not falling */ | ||
342 | for(i=0; i<BJ_HEIGHT; i++) { | ||
343 | for(j=0; j<BJ_WIDTH; j++) { | ||
344 | bj->playboard[j][i].falling = false; | ||
345 | } | ||
346 | } | ||
347 | } | ||
348 | } | ||
349 | |||
350 | /***************************************************************************** | ||
351 | * bejeweled_clearjewels() finds all the connected rows and columns and | ||
352 | * calculates and returns the points earned. | ||
353 | ******************************************************************************/ | ||
354 | unsigned int bejeweled_clearjewels(struct game_context* bj) { | ||
355 | int i, j; | ||
356 | int last, run; | ||
357 | unsigned int points = 0; | ||
358 | |||
359 | /* check for connected rows */ | ||
360 | for(i=1; i<BJ_HEIGHT; i++) { | ||
361 | last = 0; | ||
362 | run = 1; | ||
363 | for(j=0; j<BJ_WIDTH; j++) { | ||
364 | if(bj->playboard[j][i].type == last && | ||
365 | bj->playboard[j][i].type != 0) { | ||
366 | run++; | ||
367 | |||
368 | if(run == 3) { | ||
369 | bj->segments++; | ||
370 | points += bj->segments; | ||
371 | bj->playboard[j][i].delete = true; | ||
372 | bj->playboard[j-1][i].delete = true; | ||
373 | bj->playboard[j-2][i].delete = true; | ||
374 | } else if(run > 3) { | ||
375 | points++; | ||
376 | bj->playboard[j][i].delete = true; | ||
377 | } | ||
378 | } else { | ||
379 | run = 1; | ||
380 | last = bj->playboard[j][i].type; | ||
381 | } | ||
382 | } | ||
383 | } | ||
384 | |||
385 | /* check for connected columns */ | ||
386 | for(j=0; j<BJ_WIDTH; j++) { | ||
387 | last = 0; | ||
388 | run = 1; | ||
389 | for(i=1; i<BJ_HEIGHT; i++) { | ||
390 | if(bj->playboard[j][i].type != 0 && | ||
391 | bj->playboard[j][i].type == last) { | ||
392 | run++; | ||
393 | |||
394 | if(run == 3) { | ||
395 | bj->segments++; | ||
396 | points += bj->segments; | ||
397 | bj->playboard[j][i].delete = true; | ||
398 | bj->playboard[j][i-1].delete = true; | ||
399 | bj->playboard[j][i-2].delete = true; | ||
400 | } else if(run > 3) { | ||
401 | points++; | ||
402 | bj->playboard[j][i].delete = true; | ||
403 | } | ||
404 | } else { | ||
405 | run = 1; | ||
406 | last = bj->playboard[j][i].type; | ||
407 | } | ||
408 | } | ||
409 | } | ||
410 | |||
411 | /* clear deleted jewels */ | ||
412 | for(i=1; i<BJ_HEIGHT; i++) { | ||
413 | for(j=0; j<BJ_WIDTH; j++) { | ||
414 | if(bj->playboard[j][i].delete) { | ||
415 | bj->playboard[j][i].delete = false; | ||
416 | bj->playboard[j][i].type = 0; | ||
417 | } | ||
418 | } | ||
419 | } | ||
420 | |||
421 | bejeweled_drawboard(bj); | ||
422 | return points; | ||
423 | } | ||
424 | |||
425 | /***************************************************************************** | ||
426 | * bejeweled_runboard() runs the board until it settles in a fixed state and | ||
427 | * returns points earned. | ||
428 | ******************************************************************************/ | ||
429 | unsigned int bejeweled_runboard(struct game_context* bj) { | ||
430 | unsigned int points = 0; | ||
431 | unsigned int ret; | ||
432 | |||
433 | bj->segments = 0; | ||
434 | |||
435 | while((ret = bejeweled_clearjewels(bj)) > 0) { | ||
436 | points += ret; | ||
437 | bejeweled_putjewels(bj); | ||
438 | } | ||
439 | |||
440 | return points; | ||
441 | } | ||
442 | |||
443 | /***************************************************************************** | ||
444 | * bejeweled_swapjewels() swaps two jewels as long as it results in points and | ||
445 | * returns points earned. | ||
446 | ******************************************************************************/ | ||
447 | unsigned int bejeweled_swapjewels(struct game_context* bj, | ||
448 | int x, int y, int direc) { | ||
449 | int k; | ||
450 | int horzmod, vertmod; | ||
451 | bool undo = false; | ||
452 | unsigned int points = 0; | ||
453 | |||
454 | /* check for invalid parameters */ | ||
455 | if(x < 0 || x >= BJ_WIDTH || y < 0 || y >= BJ_HEIGHT-1 || | ||
456 | direc < SWAP_UP || direc > SWAP_LEFT) return 0; | ||
457 | |||
458 | /* check for invalid directions */ | ||
459 | if((x == 0 && direc == SWAP_LEFT) || | ||
460 | (x == BJ_WIDTH-1 && direc == SWAP_RIGHT) || | ||
461 | (y == 0 && direc == SWAP_UP) || | ||
462 | (y == BJ_HEIGHT-2 && direc == SWAP_DOWN)) { | ||
463 | return 0; | ||
464 | } | ||
465 | |||
466 | /* set direction variables */ | ||
467 | horzmod = 0; | ||
468 | vertmod = 0; | ||
469 | switch(direc) { | ||
470 | case SWAP_UP: | ||
471 | vertmod = -1; break; | ||
472 | case SWAP_RIGHT: | ||
473 | horzmod = 1; break; | ||
474 | case SWAP_DOWN: | ||
475 | vertmod = 1; break; | ||
476 | case SWAP_LEFT: | ||
477 | horzmod = -1; break; | ||
478 | } | ||
479 | |||
480 | while(true) { | ||
481 | /* animate swapping jewels */ | ||
482 | for(k=TILE_SZ/8; k<=TILE_SZ; k+=TILE_SZ/8) { | ||
483 | rb->sleep(HZ/SWAP_TIMER); | ||
484 | /* clear old position */ | ||
485 | rb->lcd_mono_bitmap(jewel[0], | ||
486 | x*TILE_SZ+horzmod*(k-TILE_SZ/8), | ||
487 | y*TILE_SZ+vertmod*(k-TILE_SZ/8), | ||
488 | TILE_SZ, TILE_SZ); | ||
489 | rb->lcd_mono_bitmap(jewel[0], | ||
490 | (x+horzmod)*TILE_SZ+horzmod*(k-TILE_SZ/8)*-1, | ||
491 | (y+vertmod)*TILE_SZ+vertmod*(k-TILE_SZ/8)*-1, | ||
492 | TILE_SZ, TILE_SZ); | ||
493 | /* draw new position */ | ||
494 | rb->lcd_mono_bitmap(jewel[bj->playboard[x][y+1].type], | ||
495 | x*TILE_SZ+horzmod*k, | ||
496 | y*TILE_SZ+vertmod*k, | ||
497 | TILE_SZ, TILE_SZ); | ||
498 | rb->lcd_set_drawmode(DRMODE_FG); | ||
499 | rb->lcd_mono_bitmap(jewel[bj->playboard | ||
500 | [x+horzmod][y+1+vertmod].type], | ||
501 | (x+horzmod)*TILE_SZ+horzmod*k*-1, | ||
502 | (y+vertmod)*TILE_SZ+vertmod*k*-1, | ||
503 | TILE_SZ, TILE_SZ); | ||
504 | rb->lcd_set_drawmode(DRMODE_SOLID); | ||
505 | |||
506 | rb->lcd_update(); | ||
507 | } | ||
508 | |||
509 | /* swap jewels */ | ||
510 | int temp = bj->playboard[x][y+1].type; | ||
511 | bj->playboard[x][y+1].type = | ||
512 | bj->playboard[x+horzmod][y+1+vertmod].type; | ||
513 | bj->playboard[x+horzmod][y+1+vertmod].type = temp; | ||
514 | |||
515 | if(undo) break; | ||
516 | |||
517 | points = bejeweled_runboard(bj); | ||
518 | if(points == 0) {undo = true;} else {break;} | ||
519 | } | ||
520 | |||
521 | return points; | ||
522 | } | ||
523 | |||
524 | /***************************************************************************** | ||
525 | * bejeweled_movesavail() uses pattern matching to see if there are any | ||
526 | * available move left. | ||
527 | ******************************************************************************/ | ||
528 | bool bejeweled_movesavail(struct game_context* bj) { | ||
529 | int i, j; | ||
530 | bool moves = false; | ||
531 | int mytype; | ||
532 | |||
533 | for(i=1; i<BJ_HEIGHT; i++) { | ||
534 | for(j=0; j<BJ_WIDTH; j++) { | ||
535 | mytype = bj->playboard[j][i].type; | ||
536 | |||
537 | /* check horizontal patterns */ | ||
538 | if(j <= BJ_WIDTH-3) { | ||
539 | if(i > 1) { | ||
540 | if(bj->playboard[j+1][i-1].type == mytype) { | ||
541 | if(bj->playboard[j+2][i-1].type == mytype) | ||
542 | {moves = true; break;} | ||
543 | if(bj->playboard[j+2][i].type == mytype) | ||
544 | {moves = true; break;} | ||
545 | } | ||
546 | if(bj->playboard[j+1][i].type == mytype) { | ||
547 | if(bj->playboard[j+2][i-1].type == mytype) | ||
548 | {moves = true; break;} | ||
549 | } | ||
550 | } | ||
551 | |||
552 | if(j <= BJ_WIDTH-4) { | ||
553 | if(bj->playboard[j+3][i].type == mytype) { | ||
554 | if(bj->playboard[j+1][i].type == mytype) | ||
555 | {moves = true; break;} | ||
556 | if(bj->playboard[j+2][i].type == mytype) | ||
557 | {moves = true; break;} | ||
558 | } | ||
559 | } | ||
560 | |||
561 | if(i < BJ_HEIGHT-1) { | ||
562 | if(bj->playboard[j+1][i].type == mytype) { | ||
563 | if(bj->playboard[j+2][i+1].type == mytype) | ||
564 | {moves = true; break;} | ||
565 | } | ||
566 | if(bj->playboard[j+1][i+1].type == mytype) { | ||
567 | if(bj->playboard[j+2][i].type == mytype) | ||
568 | {moves = true; break;} | ||
569 | if(bj->playboard[j+2][i+1].type == mytype) | ||
570 | {moves = true; break;} | ||
571 | } | ||
572 | } | ||
573 | } | ||
574 | |||
575 | /* check vertical patterns */ | ||
576 | if(i <= BJ_HEIGHT-3) { | ||
577 | if(j > 0) { | ||
578 | if(bj->playboard[j-1][i+1].type == mytype) { | ||
579 | if(bj->playboard[j-1][i+2].type == mytype) | ||
580 | {moves = true; break;} | ||
581 | if(bj->playboard[j][i+2].type == mytype) | ||
582 | {moves = true; break;} | ||
583 | } | ||
584 | if(bj->playboard[j][i+1].type == mytype) { | ||
585 | if(bj->playboard[j-1][i+2].type == mytype) | ||
586 | {moves = true; break;} | ||
587 | } | ||
588 | } | ||
589 | |||
590 | if(i <= BJ_HEIGHT-4) { | ||
591 | if(bj->playboard[j][i+3].type == mytype) { | ||
592 | if(bj->playboard[j][i+1].type == mytype) | ||
593 | {moves = true; break;} | ||
594 | if(bj->playboard[j][i+2].type == mytype) | ||
595 | {moves = true; break;} | ||
596 | } | ||
597 | } | ||
598 | |||
599 | if(j < BJ_WIDTH-1) { | ||
600 | if(bj->playboard[j][i+1].type == mytype) { | ||
601 | if(bj->playboard[j+1][i+2].type == mytype) | ||
602 | {moves = true; break;} | ||
603 | } | ||
604 | if(bj->playboard[j+1][i+1].type == mytype) { | ||
605 | if(bj->playboard[j][i+2].type == mytype) | ||
606 | {moves = true; break;} | ||
607 | if (bj->playboard[j+1][i+2].type == mytype) | ||
608 | {moves = true; break;} | ||
609 | } | ||
610 | } | ||
611 | } | ||
612 | } | ||
613 | |||
614 | if(moves) break; | ||
615 | } | ||
616 | |||
617 | return moves; | ||
618 | } | ||
619 | |||
620 | /***************************************************************************** | ||
621 | * bejeweled_nextlevel() advances the game to the next level and returns | ||
622 | * points earned. | ||
623 | ******************************************************************************/ | ||
624 | unsigned int bejeweled_nextlevel(struct game_context* bj) { | ||
625 | int i, x, y; | ||
626 | unsigned int points = 0; | ||
627 | |||
628 | /* roll over score, change and display level */ | ||
629 | while(bj->score >= LEVEL_PTS) { | ||
630 | bj->score -= LEVEL_PTS; | ||
631 | bj->level++; | ||
632 | bejeweled_drawboard(bj); | ||
633 | rb->splash(HZ*2, true, "Level %d", bj->level); | ||
634 | bejeweled_drawboard(bj); | ||
635 | } | ||
636 | |||
637 | /* randomly clear some jewels */ | ||
638 | for(i=0; i<16; i++) { | ||
639 | x = rb->rand()%8; | ||
640 | y = rb->rand()%8; | ||
641 | |||
642 | if(bj->playboard[x][y].type != 0) { | ||
643 | points++; | ||
644 | bj->playboard[x][y].type = 0; | ||
645 | } | ||
646 | } | ||
647 | bejeweled_drawboard(bj); | ||
648 | |||
649 | /* run the play board */ | ||
650 | bejeweled_putjewels(bj); | ||
651 | points += bejeweled_runboard(bj); | ||
652 | return points; | ||
653 | } | ||
654 | |||
655 | /***************************************************************************** | ||
656 | * bejeweld_recordscore() inserts a high score into the high scores list and | ||
657 | * returns the high score position. | ||
658 | ******************************************************************************/ | ||
659 | int bejeweled_recordscore(struct game_context* bj) { | ||
660 | int i; | ||
661 | int position = 0; | ||
662 | unsigned short current, temp; | ||
663 | |||
664 | /* calculate total score */ | ||
665 | current = (bj->level-1)*LEVEL_PTS+bj->score; | ||
666 | if(current <= 0) return 0; | ||
667 | |||
668 | /* insert the current score into the high scores */ | ||
669 | for(i=0; i<NUM_SCORES; i++) { | ||
670 | if(current >= bj->highscores[i]) { | ||
671 | if(!position) { | ||
672 | position = i+1; | ||
673 | bj->dirty = true; | ||
674 | } | ||
675 | temp = bj->highscores[i]; | ||
676 | bj->highscores[i] = current; | ||
677 | current = temp; | ||
678 | } | ||
679 | } | ||
680 | |||
681 | return position; | ||
682 | } | ||
683 | |||
684 | /***************************************************************************** | ||
685 | * bejeweled_loadscores() loads the high scores saved file. | ||
686 | ******************************************************************************/ | ||
687 | void bejeweled_loadscores(struct game_context* bj) { | ||
688 | int fd; | ||
689 | |||
690 | bj->dirty = false; | ||
691 | |||
692 | /* clear high scores */ | ||
693 | rb->memset(bj->highscores, 0, sizeof(bj->highscores)); | ||
694 | |||
695 | /* open scores file */ | ||
696 | fd = rb->open(SCORE_FILE, O_RDONLY); | ||
697 | if(fd < 0) return; | ||
698 | |||
699 | /* read in high scores */ | ||
700 | if(rb->read(fd, bj->highscores, sizeof(bj->highscores)) <= 0) { | ||
701 | /* scores are bad, reset */ | ||
702 | rb->memset(bj->highscores, 0, sizeof(bj->highscores)); | ||
703 | } | ||
704 | |||
705 | rb->close(fd); | ||
706 | } | ||
707 | |||
708 | /***************************************************************************** | ||
709 | * bejeweled_savescores() saves the high scores. | ||
710 | ******************************************************************************/ | ||
711 | void bejeweled_savescores(struct game_context* bj) { | ||
712 | int fd; | ||
713 | |||
714 | /* write out the high scores to the save file */ | ||
715 | fd = rb->open(SCORE_FILE, O_WRONLY|O_CREAT); | ||
716 | rb->write(fd, bj->highscores, sizeof(bj->highscores)); | ||
717 | rb->close(fd); | ||
718 | bj->dirty = false; | ||
719 | } | ||
720 | |||
721 | /***************************************************************************** | ||
722 | * bejeweled_loadgame() loads the saved game and returns load success. | ||
723 | ******************************************************************************/ | ||
724 | bool bejeweled_loadgame(struct game_context* bj) { | ||
725 | int fd; | ||
726 | bool loaded = false; | ||
727 | |||
728 | /* open game file */ | ||
729 | fd = rb->open(SAVE_FILE, O_RDONLY); | ||
730 | if(fd < 0) return loaded; | ||
731 | |||
732 | /* read in saved game */ | ||
733 | while(true) { | ||
734 | if(rb->read(fd, &bj->score, sizeof(bj->score)) <= 0) break; | ||
735 | if(rb->read(fd, &bj->level, sizeof(bj->level)) <= 0) break; | ||
736 | if(rb->read(fd, bj->playboard, sizeof(bj->playboard)) <= 0) break; | ||
737 | bj->resume = true; | ||
738 | loaded = true; | ||
739 | break; | ||
740 | } | ||
741 | |||
742 | rb->close(fd); | ||
743 | |||
744 | /* delete saved file */ | ||
745 | rb->remove(SAVE_FILE); | ||
746 | return loaded; | ||
747 | } | ||
748 | |||
749 | /***************************************************************************** | ||
750 | * bejeweled_savegame() saves the current game state. | ||
751 | ******************************************************************************/ | ||
752 | void bejeweled_savegame(struct game_context* bj) { | ||
753 | int fd; | ||
754 | |||
755 | /* write out the game state to the save file */ | ||
756 | fd = rb->open(SAVE_FILE, O_WRONLY|O_CREAT); | ||
757 | rb->write(fd, &bj->score, sizeof(bj->score)); | ||
758 | rb->write(fd, &bj->level, sizeof(bj->level)); | ||
759 | rb->write(fd, bj->playboard, sizeof(bj->playboard)); | ||
760 | rb->close(fd); | ||
761 | |||
762 | bj->resume = true; | ||
763 | } | ||
764 | |||
765 | /***************************************************************************** | ||
766 | * bejeweled_callback() is the default event handler callback which is called | ||
767 | * on usb connect and shutdown. | ||
768 | ******************************************************************************/ | ||
769 | void bejeweled_callback(void* param) { | ||
770 | struct game_context* bj = (struct game_context*) param; | ||
771 | if(bj->dirty) { | ||
772 | rb->splash(HZ, true, "Saving high scores..."); | ||
773 | bejeweled_savescores(bj); | ||
774 | } | ||
775 | } | ||
776 | |||
777 | /***************************************************************************** | ||
778 | * bejeweled() is the main game subroutine, it returns the final game status. | ||
779 | ******************************************************************************/ | ||
780 | int bejeweled(struct game_context* bj) { | ||
781 | int i, j; | ||
782 | int w, h; | ||
783 | int button; | ||
784 | int lastbutton = BUTTON_NONE; | ||
785 | char str[18]; | ||
786 | char *title = "Bejeweled"; | ||
787 | bool breakout = false; | ||
788 | bool showscores = false; | ||
789 | bool selected = false; | ||
790 | |||
791 | /* the cursor coordinates */ | ||
792 | int x=0, y=0; | ||
793 | |||
794 | /* don't resume by deafult */ | ||
795 | bj->resume = false; | ||
796 | |||
797 | /******************** | ||
798 | * menu * | ||
799 | ********************/ | ||
800 | while(true){ | ||
801 | rb->lcd_clear_display(); | ||
802 | |||
803 | if(!showscores) { | ||
804 | /* welcome screen to display key bindings */ | ||
805 | rb->lcd_getstringsize(title, &w, &h); | ||
806 | rb->lcd_putsxy((LCD_WIDTH-w)/2, 0, title); | ||
807 | #if CONFIG_KEYPAD == RECORDER_PAD | ||
808 | rb->lcd_puts(0, 1, "ON to start"); | ||
809 | rb->lcd_puts(0, 2, "F1 to save/resume"); | ||
810 | rb->lcd_puts(0, 3, "OFF to exit"); | ||
811 | rb->lcd_puts(0, 4, "PLAY to select"); | ||
812 | rb->lcd_puts(0, 5, "& show high scores"); | ||
813 | rb->lcd_puts(0, 6, "Directions to move"); | ||
814 | rb->snprintf(str, 18, "High Score: %d", bj->highscores[0]); | ||
815 | rb->lcd_puts(0, 7, str); | ||
816 | #elif CONFIG_KEYPAD == ONDIO_PAD | ||
817 | rb->lcd_puts(0, 1, "RIGHT to start"); | ||
818 | rb->lcd_puts(0, 2, "MENU+OFF to sv/res"); | ||
819 | rb->lcd_puts(0, 3, "OFF to exit"); | ||
820 | rb->lcd_puts(0, 4, "MENU to select"); | ||
821 | rb->lcd_puts(0, 5, "& show high scores"); | ||
822 | rb->lcd_puts(0, 6, "Directions to move"); | ||
823 | rb->snprintf(str, 18, "High Score: %d", bj->highscores[0]); | ||
824 | rb->lcd_puts(0, 7, str); | ||
825 | #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || (CONFIG_KEYPAD == IRIVER_H300_PAD) | ||
826 | rb->lcd_puts(0, 2, "ON to start"); | ||
827 | rb->lcd_puts(0, 3, "MODE to save/resume"); | ||
828 | rb->lcd_puts(0, 4, "OFF to exit"); | ||
829 | rb->lcd_puts(0, 5, "SELECT to select"); | ||
830 | rb->lcd_puts(0, 6, " and show high scores"); | ||
831 | rb->lcd_puts(0, 7, "Directions to move"); | ||
832 | rb->snprintf(str, 18, "High Score: %d", bj->highscores[0]); | ||
833 | rb->lcd_puts(0, 9, str); | ||
834 | #endif | ||
835 | } else { | ||
836 | /* room for a title? */ | ||
837 | j = 0; | ||
838 | if(LCD_HEIGHT-NUM_SCORES*8 >= 8) { | ||
839 | rb->snprintf(str, 12, "%s", "High Scores"); | ||
840 | rb->lcd_getstringsize(str, &w, &h); | ||
841 | rb->lcd_putsxy((LCD_WIDTH-w)/2, 0, str); | ||
842 | j = 1; | ||
843 | } | ||
844 | |||
845 | /* print high scores */ | ||
846 | for(i=0; i<NUM_SCORES; i++) { | ||
847 | rb->snprintf(str, 11, "#%02d: %d", i+1, bj->highscores[i]); | ||
848 | rb->lcd_puts(0, i+j, str); | ||
849 | } | ||
850 | } | ||
851 | |||
852 | rb->lcd_update(); | ||
853 | |||
854 | /* handle menu button presses */ | ||
855 | button = rb->button_get(true); | ||
856 | switch(button){ | ||
857 | case BEJEWELED_START: /* start playing */ | ||
858 | breakout = true; | ||
859 | break; | ||
860 | |||
861 | case BEJEWELED_QUIT: /* quit program */ | ||
862 | if(showscores) { | ||
863 | showscores = 0; | ||
864 | break; | ||
865 | } | ||
866 | return BJ_QUIT; | ||
867 | |||
868 | case BEJEWELED_RESUME:/* resume game */ | ||
869 | if(!bejeweled_loadgame(bj)) { | ||
870 | rb->splash(HZ*2, true, "Nothing to resume"); | ||
871 | } else { | ||
872 | breakout = true; | ||
873 | } | ||
874 | break; | ||
875 | |||
876 | case BEJEWELED_SELECT:/* toggle high scores */ | ||
877 | #ifdef BEJEWELED_SELECT_PRE | ||
878 | if(lastbutton != BEJEWELED_SELECT_PRE) break; | ||
879 | #endif | ||
880 | showscores ^= 1; | ||
881 | break; | ||
882 | |||
883 | default: | ||
884 | if(rb->default_event_handler_ex(button, bejeweled_callback, | ||
885 | (void*) bj) == SYS_USB_CONNECTED) | ||
886 | return BJ_USB; | ||
887 | break; | ||
888 | } | ||
889 | |||
890 | if(breakout) break; | ||
891 | if(button != BUTTON_NONE) lastbutton = button; | ||
892 | } | ||
893 | |||
894 | lastbutton = BUTTON_NONE; | ||
895 | |||
896 | /******************** | ||
897 | * init * | ||
898 | ********************/ | ||
899 | bejeweled_init(bj); | ||
900 | |||
901 | /******************** | ||
902 | * setup the board * | ||
903 | ********************/ | ||
904 | bejeweled_drawboard(bj); | ||
905 | bejeweled_putjewels(bj); | ||
906 | bj->score += bejeweled_runboard(bj); | ||
907 | |||
908 | /********************** | ||
909 | * play * | ||
910 | **********************/ | ||
911 | while(true) { | ||
912 | /* refresh the board */ | ||
913 | bejeweled_drawboard(bj); | ||
914 | |||
915 | /* display the cursor */ | ||
916 | if(selected) { | ||
917 | rb->lcd_set_drawmode(DRMODE_COMPLEMENT); | ||
918 | rb->lcd_fillrect(x*TILE_SZ, y*TILE_SZ, TILE_SZ, TILE_SZ); | ||
919 | rb->lcd_set_drawmode(DRMODE_SOLID); | ||
920 | } else { | ||
921 | rb->lcd_drawrect(x*TILE_SZ, y*TILE_SZ, TILE_SZ, TILE_SZ); | ||
922 | } | ||
923 | rb->lcd_update_rect(x*TILE_SZ, y*TILE_SZ, TILE_SZ, TILE_SZ); | ||
924 | |||
925 | /* handle game button presses */ | ||
926 | button = rb->button_get(true); | ||
927 | switch(button){ | ||
928 | case BEJEWELED_RESUME: /* save and end game */ | ||
929 | rb->splash(HZ, true, "Saving game..."); | ||
930 | bejeweled_savegame(bj); | ||
931 | /* fall through to BEJEWELED_QUIT */ | ||
932 | |||
933 | case BEJEWELED_QUIT: /* end game */ | ||
934 | return BJ_END; | ||
935 | |||
936 | case BUTTON_LEFT: /* move cursor left */ | ||
937 | case (BUTTON_LEFT|BUTTON_REPEAT): | ||
938 | if(selected) { | ||
939 | bj->score += bejeweled_swapjewels(bj, x, y, SWAP_LEFT); | ||
940 | selected = false; | ||
941 | if (!bejeweled_movesavail(bj)) return BJ_LOSE; | ||
942 | } else { | ||
943 | x = (x+BJ_WIDTH-1)%BJ_WIDTH; | ||
944 | } | ||
945 | break; | ||
946 | |||
947 | case BUTTON_RIGHT: /* move cursor right */ | ||
948 | case (BUTTON_RIGHT|BUTTON_REPEAT): | ||
949 | if(selected) { | ||
950 | bj->score += bejeweled_swapjewels(bj, x, y, SWAP_RIGHT); | ||
951 | selected = false; | ||
952 | if (!bejeweled_movesavail(bj)) return BJ_LOSE; | ||
953 | } else { | ||
954 | x = (x+1)%BJ_WIDTH; | ||
955 | } | ||
956 | break; | ||
957 | |||
958 | case BUTTON_DOWN: /* move cursor down */ | ||
959 | case (BUTTON_DOWN|BUTTON_REPEAT): | ||
960 | if(selected) { | ||
961 | bj->score += bejeweled_swapjewels(bj, x, y, SWAP_DOWN); | ||
962 | selected = false; | ||
963 | if (!bejeweled_movesavail(bj)) return BJ_LOSE; | ||
964 | } else { | ||
965 | y = (y+1)%(BJ_HEIGHT-1); | ||
966 | } | ||
967 | break; | ||
968 | |||
969 | case BUTTON_UP: /* move cursor up */ | ||
970 | case (BUTTON_UP|BUTTON_REPEAT): | ||
971 | if(selected) { | ||
972 | bj->score += bejeweled_swapjewels(bj, x, y, SWAP_UP); | ||
973 | selected = false; | ||
974 | if (!bejeweled_movesavail(bj)) return BJ_LOSE; | ||
975 | } else { | ||
976 | y = (y+(BJ_HEIGHT-1)-1)%(BJ_HEIGHT-1); | ||
977 | } | ||
978 | break; | ||
979 | |||
980 | case BEJEWELED_SELECT: /* toggle selected */ | ||
981 | #ifdef BEJEWELED_SELECT_PRE | ||
982 | if(lastbutton != BEJEWELED_SELECT_PRE) break; | ||
983 | #endif | ||
984 | selected ^= 1; | ||
985 | break; | ||
986 | |||
987 | default: | ||
988 | if(rb->default_event_handler_ex(button, bejeweled_callback, | ||
989 | (void*) bj) == SYS_USB_CONNECTED) | ||
990 | return BJ_USB; | ||
991 | break; | ||
992 | } | ||
993 | |||
994 | if(button != BUTTON_NONE) lastbutton = button; | ||
995 | if(bj->score >= LEVEL_PTS) bj->score = bejeweled_nextlevel(bj); | ||
996 | } | ||
997 | } | ||
998 | |||
999 | /***************************************************************************** | ||
1000 | * plugin entry point. | ||
1001 | ******************************************************************************/ | ||
1002 | enum plugin_status plugin_start(struct plugin_api* api, void* parameter) { | ||
1003 | struct game_context bj; | ||
1004 | bool exit = false; | ||
1005 | int position; | ||
1006 | char str[19]; | ||
1007 | |||
1008 | /* plugin init */ | ||
1009 | TEST_PLUGIN_API(api); | ||
1010 | (void)parameter; | ||
1011 | rb = api; | ||
1012 | /* end of plugin init */ | ||
1013 | |||
1014 | /* load high scores */ | ||
1015 | bejeweled_loadscores(&bj); | ||
1016 | |||
1017 | rb->lcd_setfont(FONT_SYSFIXED); | ||
1018 | |||
1019 | while(!exit) { | ||
1020 | switch(bejeweled(&bj)){ | ||
1021 | case BJ_LOSE: | ||
1022 | rb->splash(HZ*2, true, "No more moves!"); | ||
1023 | /* fall through to BJ_END */ | ||
1024 | |||
1025 | case BJ_END: | ||
1026 | if(!bj.resume) { | ||
1027 | if((position = bejeweled_recordscore(&bj))) { | ||
1028 | rb->snprintf(str, 19, "New high score #%d!", position); | ||
1029 | rb->splash(HZ*2, true, str); | ||
1030 | } | ||
1031 | } | ||
1032 | break; | ||
1033 | |||
1034 | case BJ_USB: | ||
1035 | rb->lcd_setfont(FONT_UI); | ||
1036 | return PLUGIN_USB_CONNECTED; | ||
1037 | |||
1038 | case BJ_QUIT: | ||
1039 | if(bj.dirty) { | ||
1040 | rb->splash(HZ, true, "Saving high scores..."); | ||
1041 | bejeweled_savescores(&bj); | ||
1042 | } | ||
1043 | exit = true; | ||
1044 | break; | ||
1045 | |||
1046 | default: | ||
1047 | break; | ||
1048 | } | ||
1049 | } | ||
1050 | |||
1051 | rb->lcd_setfont(FONT_UI); | ||
1052 | return PLUGIN_OK; | ||
1053 | } | ||
1054 | |||
1055 | #endif | ||