keyboard: some random cleanup.
[kugel-rb.git] / apps / plugins / bubbles.c
blobba28808e65b253baa6a664716fbc9a1827310317
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2005 Adam Boot
12 * Color graphics from Frozen Bubble (http://www.frozen-bubble.org/)
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 ****************************************************************************/
24 #include "plugin.h"
26 #ifdef HAVE_LCD_BITMAP
28 #include "lib/xlcd.h"
29 #include "lib/pluginlib_actions.h"
30 #include "lib/fixedpoint.h"
31 #include "lib/playback_control.h"
32 #include "lib/highscore.h"
34 PLUGIN_HEADER
36 /* files */
37 #define SCORE_FILE PLUGIN_GAMES_DIR "/bubbles.score"
38 #define SAVE_FILE PLUGIN_GAMES_DIR "/bubbles.save"
39 #define DATA_FILE PLUGIN_GAMES_DIR "/bubbles.data"
41 /* final game return status */
42 enum {
43 BB_LOSE,
44 BB_QUIT_WITHOUT_SAVING,
45 BB_QUIT,
46 BB_USB,
47 BB_END,
48 BB_WIN,
49 BB_NONE,
52 /* play board dimension */
53 #define BB_HEIGHT 12
54 #define BB_WIDTH 8
55 #define BB_LEVEL_HEIGHT 10
57 /* various amounts */
58 #define NUM_SCORES 5
59 #define NUM_LEVELS 100
60 #define NUM_QUEUE 2
61 #define NUM_BUBBLES 8
62 #define MIN_ANGLE -76
63 #define MAX_ANGLE 76
64 #define NUM_COMPRESS 9
65 #define MAX_SHOTTIME 1000
67 /* keyboard layouts */
69 #if (CONFIG_KEYPAD != SANSA_E200_PAD) && \
70 (CONFIG_KEYPAD != SANSA_FUZE_PAD)
71 /* sansas use the wheel instead of left/right if available */
72 #define BUBBLES_LEFT PLA_LEFT
73 #define BUBBLES_LEFT_REP PLA_LEFT_REPEAT
74 #define BUBBLES_RIGHT PLA_RIGHT
75 #define BUBBLES_RIGHT_REP PLA_RIGHT_REPEAT
76 #define ANGLE_STEP 4
77 #define ANGLE_STEP_REP 4
78 #else
79 #define BUBBLES_LEFT PLA_UP
80 #define BUBBLES_LEFT_REP PLA_UP_REPEAT
81 #define BUBBLES_RIGHT PLA_DOWN
82 #define BUBBLES_RIGHT_REP PLA_DOWN_REPEAT
83 #define ANGLE_STEP 2
84 #define ANGLE_STEP_REP 4
85 #endif
87 #define BUBBLES_QUIT PLA_QUIT
88 #define BUBBLES_START PLA_START
89 #define BUBBLES_SELECT PLA_FIRE
90 #define BUBBLES_RESUME PLA_MENU
92 #if CONFIG_KEYPAD != ONDIO_PAD
94 #define BUBBLES_LVLINC PLA_UP
95 #define BUBBLES_LVLINC_REP PLA_UP_REPEAT
96 #define BUBBLES_LVLDEC PLA_DOWN
97 #define BUBBLES_LVLDEC_REP PLA_DOWN_REPEAT
99 #else /* ondio keys */
101 #define BUBBLES_LVLINC PLA_RIGHT
102 #define BUBBLES_LVLINC_REP PLA_RIGHT_REPEAT
103 #define BUBBLES_LVLDEC PLA_LEFT
104 #define BUBBLES_LVLDEC_REP PLA_LEFT_REPEAT
106 #endif
108 /* external bitmaps */
109 #ifdef HAVE_LCD_COLOR
110 #include "pluginbitmaps/bubbles_background.h"
111 #endif
112 #include "pluginbitmaps/bubbles_bubble.h"
113 #include "pluginbitmaps/bubbles_emblem.h"
115 #define BUBBLE_WIDTH BMPWIDTH_bubbles_bubble
116 #define BUBBLE_HEIGHT BMPHEIGHT_bubbles_bubble
117 #define EMBLEM_WIDTH BMPWIDTH_bubbles_emblem
118 #define EMBLEM_HEIGHT (BMPHEIGHT_bubbles_emblem/8)
120 /* bubbles will consume height of ROW_HEIGHT*(BB_HEIGHT-1)+BUBBLE_HEIGHT*3/2 */
121 /* 44x44 bubbles (m:robe 500) */
122 #if (LCD_WIDTH == 640) && (LCD_HEIGHT == 480)
123 #define XOFS 144
124 #define MAX_FPS 40
126 #elif (LCD_WIDTH == 480) && (LCD_HEIGHT == 640)
127 #define XOFS 128
128 #define MAX_FPS 40
130 /* 22x22 bubbles (iPod Video) */
131 #elif (LCD_HEIGHT == 240) && (LCD_WIDTH == 320)
132 #define XOFS 72
133 #define MAX_FPS 40
135 /* 22x22 bubbles (Gigabeat, Onda VX747) */
136 #elif ((LCD_HEIGHT == 320) || (LCD_HEIGHT == 400)) && (LCD_WIDTH == 240)
137 #define XOFS 64
138 #define MAX_FPS 30
140 /* 16x16 bubbles (H300, iPod Color) */
141 #elif (LCD_HEIGHT == 176) && (LCD_WIDTH == 220)
142 #define XOFS 46
143 #define MAX_FPS 30
145 /* 16x16 bubbles (Sansa E200) */
146 #elif (LCD_HEIGHT == 220) && (LCD_WIDTH == 176)
147 #define XOFS 24
148 #define MAX_FPS 30
149 #define YOFS 45
151 /* custom text positioning */
152 #define LEVEL_TXT_X 24
153 #define LEVEL_TXT_WIDTH 31
154 #define LEVEL_TXT_Y 5
155 #define SCORE_TXT_X 58
156 #define SCORE_TXT_WIDTH 31
157 #define SCORE_TXT_Y 5
158 #define NEXT_BB_X 112
159 #define NEXT_BB_WIDTH 31
160 #define NEXT_BB_Y 3
162 /* 12x12 bubbles (iPod Nano) */
163 #elif (LCD_HEIGHT == 132) && (LCD_WIDTH == 176)
164 #define XOFS 40
165 #define MAX_FPS 40
167 /* 12x12 bubbles (H100, H10, iAudio X5, iPod 3G, iPod 4G grayscale) */
168 #elif (LCD_HEIGHT == 128) && ((LCD_WIDTH == 160) || (LCD_WIDTH == 128))
169 #define XOFS 33
170 #define MAX_FPS 30
172 /* 10x10 bubbles (iPod Mini) */
173 #elif (LCD_HEIGHT == 110) && (LCD_WIDTH == 138)
174 #define XOFS 33
175 #define MAX_FPS 30
177 /* 9x9 bubbles (iAudio M3) */
178 #elif (LCD_HEIGHT == 96) && (LCD_WIDTH == 128)
179 #define XOFS 45
180 #define MAX_FPS 30
182 /* 8x8 bubbles (Sansa C200) */
183 #elif ((LCD_HEIGHT == 80) && (LCD_WIDTH == 132))
184 #define XOFS 45
185 #define ROW_HEIGHT 6
186 #define MAX_FPS 30
188 /* 7x7 bubbles (Sansa Clip/m200) */
189 #elif (LCD_HEIGHT == 64 && LCD_WIDTH == 128)
190 #define XOFS 33
191 #define ROW_HEIGHT 5
192 #define MAX_FPS 30
194 /* 8x7 bubbles (Archos recorder, Ondio) */
195 #elif (LCD_HEIGHT == 64) && (LCD_WIDTH == 112)
196 #define XOFS 33
197 #define ROW_HEIGHT 5
198 #define MAX_FPS 20
200 #else
201 #error BUBBLES: Unsupported LCD type
202 #endif
204 #if !defined(ROW_HEIGHT)
205 #define ROW_HEIGHT (BUBBLE_WIDTH-(BUBBLE_WIDTH-EMBLEM_WIDTH)/2)
206 #endif
208 #define ROW_INDENT (BUBBLE_WIDTH/2)
210 #define TEXT_LINES (LCD_HEIGHT/8)
212 #ifndef YOFS
213 #define YOFS 0
214 #endif
216 /* shot position */
217 #define SHOTX XOFS+ROW_INDENT+BUBBLE_WIDTH*3
218 #define SHOTY (YOFS+ROW_HEIGHT*(BB_HEIGHT-1)+BUBBLE_HEIGHT/2)
220 /* collision distance squared */
221 #define MIN_DISTANCE ((BUBBLE_WIDTH*8)/10)*((BUBBLE_HEIGHT*8)/10)
223 /* levels */
224 char level[NUM_LEVELS][BB_LEVEL_HEIGHT][BB_WIDTH] = {
225 {{ 6, 6, 4, 4, 2, 2, 3, 3},
226 { 6, 6, 4, 4, 2, 2, 3, -1},
227 { 2, 2, 3, 3, 6, 6, 4, 4},
228 { 2, 3, 3, 6, 6, 4, 4, -1},
229 {-1, -1, -1, -1, -1, -1, -1, -1},
230 {-1, -1, -1, -1, -1, -1, -1, -1},
231 {-1, -1, -1, -1, -1, -1, -1, -1},
232 {-1, -1, -1, -1, -1, -1, -1, -1},
233 {-1, -1, -1, -1, -1, -1, -1, -1},
234 {-1, -1, -1, -1, -1, -1, -1, -1}},
235 {{-1, 7, 7, 7, 7, 7, 7, -1},
236 {-1, 1, 1, 1, 1, 1, -1, -1},
237 {-1, -1, 2, 2, 2, 2, -1, -1},
238 {-1, -1, -1, 2, -1, -1, -1, -1},
239 {-1, -1, -1, 2, 2, -1, -1, -1},
240 {-1, -1, -1, 5, -1, -1, -1, -1},
241 {-1, -1, -1, 5, 5, -1, -1, -1},
242 {-1, -1, -1, -1, -1, -1, -1, -1},
243 {-1, -1, -1, -1, -1, -1, -1, -1},
244 {-1, -1, -1, -1, -1, -1, -1, -1}},
245 {{-1, -1, 7, -1, -1, 7, -1, -1},
246 {-1, -1, 7, 1, 7, -1, -1, -1},
247 {-1, -1, -1, 1, 2, -1, -1, -1},
248 {-1, -1, 1, 2, 1, -1, -1, -1},
249 {-1, -1, -1, 2, 5, -1, -1, -1},
250 {-1, -1, 3, 5, 3, -1, -1, -1},
251 {-1, -1, -1, 5, 3, -1, -1, -1},
252 {-1, -1, -1, 3, -1, -1, -1, -1},
253 {-1, -1, -1, -1, -1, -1, -1, -1},
254 {-1, -1, -1, -1, -1, -1, -1, -1}},
255 {{-1, -1, -1, 0, 0, -1, -1, -1},
256 {-1, -1, 5, 0, 1, -1, -1, -1},
257 {-1, -1, 3, 5, 1, 6, -1, -1},
258 {-1, 4, 3, -1, 6, 7, -1, -1},
259 {-1, 7, 4, -1, -1, 7, 4, -1},
260 { 6, 7, -1, -1, -1, 4, 3, -1},
261 { 1, 6, -1, -1, -1, -1, 3, 5},
262 { 1, -1, -1, -1, -1, -1, 5, -1},
263 {-1, -1, -1, -1, -1, -1, -1, -1},
264 {-1, -1, -1, -1, -1, -1, -1, -1}},
265 {{-1, -1, 0, 0, 0, 0, -1, -1},
266 {-1, 0, 1, 1, 1, 0, -1, -1},
267 {-1, 0, 1, 0, 0, 1, 0, -1},
268 {-1, 0, 1, 1, 1, 0, -1, -1},
269 {-1, -1, 0, 0, 0, 0, -1, -1},
270 {-1, -1, 7, -1, 7, -1, -1, -1},
271 {-1, -1, 7, 7, 7, 7, -1, -1},
272 {-1, -1, -1, -1, -1, -1, -1, -1},
273 {-1, -1, -1, -1, -1, -1, -1, -1},
274 {-1, -1, -1, -1, -1, -1, -1, -1}},
275 {{-1, 4, 4, 4, 6, 6, 6, -1},
276 { 4, -1, -1, -1, -1, -1, 6, -1},
277 {-1, 4, -1, -1, -1, -1, 6, -1},
278 { 4, 2, 3, 1, 2, 3, 6, -1},
279 {-1, 3, 1, 2, 3, 1, 2, -1},
280 {-1, -1, -1, -1, -1, -1, -1, -1},
281 {-1, -1, -1, -1, -1, -1, -1, -1},
282 {-1, -1, -1, -1, -1, -1, -1, -1},
283 {-1, -1, -1, -1, -1, -1, -1, -1},
284 {-1, -1, -1, -1, -1, -1, -1, -1}},
285 {{-1, 4, 4, 4, 6, 6, 6, -1},
286 { 4, -1, -1, -1, -1, -1, 6, -1},
287 {-1, 4, -1, -1, -1, -1, 6, -1},
288 { 4, 2, 3, 1, 2, 3, 6, -1},
289 {-1, 3, 1, 2, 3, 1, 2, -1},
290 {-1, 2, 3, 1, 2, 3, -1, -1},
291 {-1, -1, -1, -1, -1, -1, -1, -1},
292 {-1, -1, -1, -1, -1, -1, -1, -1},
293 {-1, -1, -1, -1, -1, -1, -1, -1},
294 {-1, -1, -1, -1, -1, -1, -1, -1}},
295 {{-1, 0, 0, -1, -1, 2, 2, -1},
296 {-1, 5, -1, -1, -1, 3, -1, -1},
297 {-1, 0, -1, -1, -1, 6, -1, -1},
298 {-1, 3, -1, -1, -1, 0, -1, -1},
299 {-1, 4, -1, -1, -1, 5, -1, -1},
300 {-1, 2, -1, -1, -1, 3, -1, -1},
301 {-1, 2, -1, -1, -1, 1, -1, -1},
302 {-1, 3, -1, -1, -1, 4, -1, -1},
303 {-1, -1, -1, -1, -1, -1, -1, -1},
304 {-1, -1, -1, -1, -1, -1, -1, -1}},
305 {{ 3, -1, -1, -1, -1, -1, -1, 3},
306 { 6, 3, 2, 4, 6, 3, 2, -1},
307 { 4, -1, -1, -1, -1, -1, -1, 4},
308 { 2, 4, 6, 3, 2, 4, 6, -1},
309 {-1, -1, -1, 6, -1, -1, -1, -1},
310 {-1, -1, -1, 3, -1, -1, -1, -1},
311 {-1, -1, -1, -1, -1, -1, -1, -1},
312 {-1, -1, -1, -1, -1, -1, -1, -1},
313 {-1, -1, -1, -1, -1, -1, -1, -1},
314 {-1, -1, -1, -1, -1, -1, -1, -1}},
315 {{-1, 2, -1, 1, -1, 1, -1, 2},
316 { 1, 2, -1, 2, 1, -1, 1, -1},
317 { 1, -1, 1, -1, 2, -1, 2, -1},
318 { 2, 1, -1, 1, 2, -1, 2, -1},
319 {-1, 2, -1, 2, -1, 2, -1, 2},
320 { 1, 2, -1, 2, 1, -1, 1, -1},
321 { 1, -1, 1, -1, 2, -1, 1, -1},
322 { 2, 2, -1, 1, 1, -1, 2, -1},
323 {-1, 2, -1, 1, -1, 1, -1, 1},
324 {-1, -1, -1, -1, -1, -1, -1, -1}},
325 {{-1, 7, 7, -1, -1, 5, 5, -1},
326 { 1, -1, -1, -1, -1, -1, 4, -1},
327 { 2, 1, -1, -1, -1, -1, 4, 3},
328 { 2, -1, -1, -1, -1, -1, 3, -1},
329 { 1, 2, -1, -1, -1, -1, 3, 4},
330 { 1, -1, -1, -1, -1, -1, 4, -1},
331 { 7, 1, -1, -1, -1, -1, 4, 5},
332 { 7, 7, -1, -1, -1, 5, 5, -1},
333 {-1, -1, -1, -1, -1, -1, -1, -1},
334 {-1, -1, -1, -1, -1, -1, -1, -1}},
335 {{ 7, 7, -1, -1, -1, -1, 5, 5},
336 { 1, 5, -1, -1, -1, 7, 4, -1},
337 { 2, 1, -1, -1, -1, -1, 4, 3},
338 { 2, -1, -1, -1, -1, -1, 3, -1},
339 { 1, 5, -1, -1, -1, -1, 7, 4},
340 { 1, -1, -1, -1, -1, -1, 4, -1},
341 { 7, 1, -1, -1, -1, -1, 4, 5},
342 { 7, 5, -1, -1, -1, 7, 5, -1},
343 {-1, -1, -1, -1, -1, -1, -1, -1},
344 {-1, -1, -1, -1, -1, -1, -1, -1}},
345 {{-1, -1, -1, 0, 0, -1, -1, -1},
346 {-1, -1, 5, 0, 1, -1, -1, -1},
347 {-1, -1, 3, 5, 1, 6, -1, -1},
348 {-1, 4, 3, 2, 6, 2, -1, -1},
349 {-1, 7, 4, 7, 2, 2, 4, -1},
350 { 6, 7, 7, 3, 3, 4, 3, -1},
351 { 1, 6, 1, 1, 1, 3, 3, 5},
352 { 1, 1, -1, -1, -1, -1, 5, -1},
353 {-1, -1, -1, -1, -1, -1, -1, -1},
354 {-1, -1, -1, -1, -1, -1, -1, -1}},
355 {{-1, -1, 0, -1, -1, 0, -1, -1},
356 {-1, 3, 3, -1, 3, 3, -1, -1},
357 {-1, 0, 2, 0, 0, 2, 0, -1},
358 {-1, 3, 3, -1, 3, 3, -1, -1},
359 {-1, -1, 0, -1, -1, 0, -1, -1},
360 {-1, -1, -1, -1, -1, -1, -1, -1},
361 {-1, -1, -1, -1, -1, -1, -1, -1},
362 {-1, -1, -1, -1, -1, -1, -1, -1},
363 {-1, -1, -1, -1, -1, -1, -1, -1},
364 {-1, -1, -1, -1, -1, -1, -1, -1}},
365 {{-1, -1, -1, 1, 1, -1, -1, -1},
366 {-1, -1, 2, 2, 2, -1, -1, -1},
367 {-1, -1, 3, 3, 3, 3, -1, -1},
368 {-1, 4, 4, 4, 4, 4, -1, -1},
369 {-1, 5, 5, 5, 5, 5, 5, -1},
370 {-1, -1, -1, 6, -1, -1, -1, -1},
371 {-1, -1, -1, 7, 7, -1, -1, -1},
372 {-1, -1, -1, 0, -1, -1, -1, -1},
373 {-1, -1, -1, -1, -1, -1, -1, -1},
374 {-1, -1, -1, -1, -1, -1, -1, -1}},
375 {{-1, -1, -1, 2, 5, -1, -1, -1},
376 {-1, 4, 3, -1, -1, -1, -1, -1},
377 { 6, 7, -1, 5, 2, -1, -1, -1},
378 {-1, -1, -1, -1, 3, 4, -1, -1},
379 {-1, -1, -1, 2, 5, -1, 7, 6},
380 {-1, 4, 3, -1, -1, -1, -1, -1},
381 { 6, 7, -1, 5, 2, -1, -1, -1},
382 {-1, -1, -1, -1, 3, 4, -1, -1},
383 {-1, -1, -1, -1, -1, -1, 7, 6},
384 {-1, -1, -1, -1, -1, -1, -1, -1}},
385 {{-1, -1, -1, 5, 5, -1, -1, -1},
386 {-1, -1, -1, 3, -1, -1, -1, -1},
387 {-1, -1, -1, 1, -1, -1, -1, -1},
388 {-1, -1, -1, 7, -1, -1, -1, -1},
389 {-1, -1, -1, 2, -1, -1, -1, -1},
390 {-1, -1, -1, 4, -1, -1, -1, -1},
391 {-1, -1, -1, 5, -1, -1, -1, -1},
392 {-1, -1, -1, 3, -1, -1, -1, -1},
393 {-1, -1, -1, -1, -1, -1, -1, -1},
394 {-1, -1, -1, -1, -1, -1, -1, -1}},
395 {{-1, -1, -1, 0, 1, -1, -1, -1},
396 {-1, -1, 0, 2, 7, 7, -1, -1},
397 {-1, -1, -1, 0, 1, 7, -1, -1},
398 {-1, 0, 0, 0, 0, -1, -1, -1},
399 {-1, 0, 0, 0, 1, 1, -1, -1},
400 { 0, 0, 0, 1, 1, 1, -1, -1},
401 {-1, 0, 0, 1, 1, 1, -1, -1},
402 {-1, 0, 0, 0, 7, 7, -1, -1},
403 {-1, -1, 7, 7, -1, -1, -1, -1},
404 {-1, -1, -1, -1, -1, -1, -1, -1}},
405 {{-1, 1, -1, -1, -1, -1, -1, -1},
406 { 1, -1, -1, -1, -1, -1, -1, -1},
407 {-1, 2, 3, 4, 7, 6, 5, -1},
408 {-1, -1, -1, -1, -1, -1, 1, -1},
409 {-1, -1, -1, -1, -1, -1, 1, -1},
410 {-1, 2, 3, 4, 7, 6, -1, -1},
411 {-1, 1, -1, -1, -1, -1, -1, -1},
412 { 1, -1, -1, -1, -1, -1, -1, -1},
413 {-1, 2, 3, 4, 7, 6, 5, -1},
414 {-1, -1, -1, -1, -1, -1, -1, -1}},
415 {{-1, 6, -1, -1, -1, -1, -1, -1},
416 { 5, -1, -1, -1, -1, -1, -1, -1},
417 { 2, 3, 4, 7, 6, 5, 2, 3},
418 {-1, -1, -1, -1, -1, -1, 4, -1},
419 {-1, -1, -1, -1, -1, -1, 7, -1},
420 {-1, 4, 3, 2, 5, 6, -1, -1},
421 {-1, 7, -1, -1, -1, -1, -1, -1},
422 { 6, -1, -1, -1, -1, -1, -1, -1},
423 { 5, 2, 3, 4, 7, 6, 5, -1},
424 {-1, -1, -1, -1, -1, -1, -1, -1}},
425 {{ 3, 2, 1, 0, 0, 1, 2, 3},
426 { 3, 2, 1, 0, 1, 2, 3, -1},
427 { 4, 3, 2, 1, 1, 2, 3, 4},
428 { 4, 3, 2, 1, 2, 3, 4, -1},
429 { 5, 4, 3, 2, 2, 3, 4, 5},
430 { 5, 4, 3, 2, 3, 4, 5, -1},
431 { 6, 5, 4, 3, 3, 4, 5, 6},
432 { 6, 5, 4, 3, 4, 5, 6, -1},
433 { 7, 6, 5, 4, 4, 5, 6, 7},
434 {-1, -1, -1, -1, -1, -1, -1, -1}},
435 {{-1, -1, -1, 5, 5, -1, -1, -1},
436 {-1, -1, -1, 3, -1, -1, -1, -1},
437 {-1, -1, -1, 2, 4, -1, -1, -1},
438 {-1, -1, -1, 6, -1, -1, -1, -1},
439 {-1, -1, -1, 2, 4, -1, -1, -1},
440 {-1, 2, -1, 5, -1, 4, -1, -1},
441 { 1, 0, 1, 0, 1, 0, 1, 0},
442 { 3, -1, 3, -1, 2, -1, 6, -1},
443 {-1, -1, -1, -1, -1, -1, -1, -1},
444 {-1, -1, -1, -1, -1, -1, -1, -1}},
445 {{-1, -1, -1, -1, 1, -1, -1, -1},
446 { 7, 4, 3, 5, -1, -1, -1, -1},
447 { 6, -1, -1, 1, -1, -1, -1, -1},
448 {-1, -1, -1, 5, 3, 4, 7, -1},
449 { 6, -1, -1, -1, 1, -1, -1, 6},
450 { 7, 4, 3, 5, -1, -1, -1, -1},
451 {-1, -1, -1, 1, -1, -1, -1, 6},
452 {-1, -1, -1, 5, 3, 4, 7, -1},
453 {-1, -1, -1, -1, -1, -1, -1, -1},
454 {-1, -1, -1, -1, -1, -1, -1, -1}},
455 {{-1, -1, -1, -1, 7, 3, 6, -1},
456 {-1, -1, 3, 7, 3, 6, 3, -1},
457 {-1, -1, 5, 7, 3, 6, 3, -1},
458 {-1, 6, 7, 3, 6, 7, -1, -1},
459 {-1, 7, 7, 3, 6, 1, -1, -1},
460 { 3, 7, 3, 6, 3, -1, -1, -1},
461 { 5, 6, 2, 7, 1, -1, -1, -1},
462 {-1, -1, -1, -1, -1, -1, -1, -1},
463 {-1, -1, -1, -1, -1, -1, -1, -1},
464 {-1, -1, -1, -1, -1, -1, -1, -1}},
465 {{ 5, -1, -1, -1, -1, -1, -1, 5},
466 { 5, -1, 6, 6, 6, -1, 5, -1},
467 {-1, 5, 4, -1, -1, 4, 5, -1},
468 {-1, 3, -1, -1, -1, 3, -1, -1},
469 {-1, 6, 0, -1, -1, 0, 6, -1},
470 {-1, 3, -1, -1, -1, 3, -1, -1},
471 {-1, -1, 4, -1, -1, 4, -1, -1},
472 {-1, -1, 6, 6, 6, -1, -1, -1},
473 {-1, -1, -1, -1, -1, -1, -1, -1},
474 {-1, -1, -1, -1, -1, -1, -1, -1}},
475 {{-1, 7, 0, -1, -1, 0, 7, -1},
476 { 7, -1, 0, -1, 0, -1, 7, -1},
477 { 7, 1, -1, 0, 0, -1, 1, 7},
478 { 7, 1, 2, 0, 2, 1, 7, -1},
479 { 7, 6, 3, 2, 2, 3, 6, 7},
480 { 7, -1, 3, 2, 3, -1, 7, -1},
481 {-1, 7, 7, 3, 3, 7, 7, -1},
482 {-1, -1, -1, 3, -1, -1, -1, -1},
483 {-1, -1, -1, -1, -1, -1, -1, -1},
484 {-1, -1, -1, -1, -1, -1, -1, -1}},
485 {{-1, 3, -1, 1, -1, 7, -1, 6},
486 { 5, -1, 7, -1, 7, -1, 6, -1},
487 { 6, -1, 0, -1, 5, -1, 3, -1},
488 {-1, 2, -1, 1, -1, 5, -1, -1},
489 {-1, 4, -1, 3, -1, 4, -1, -1},
490 { 2, -1, 3, -1, 2, -1, -1, -1},
491 {-1, -1, 4, -1, 6, -1, -1, -1},
492 {-1, -1, -1, 5, -1, -1, -1, -1},
493 {-1, -1, -1, -1, -1, -1, -1, -1},
494 {-1, -1, -1, -1, -1, -1, -1, -1}},
495 {{-1, -1, -1, -1, 1, -1, -1, -1},
496 {-1, -1, -1, -1, 3, -1, -1, -1},
497 { 6, 1, 3, 1, 2, 1, 4, 1},
498 {-1, -1, -1, -1, 6, -1, -1, -1},
499 {-1, -1, -1, 4, 1, -1, -1, -1},
500 {-1, -1, 1, -1, 3, -1, -1, -1},
501 {-1, -1, -1, 2, 1, -1, -1, -1},
502 {-1, -1, -1, -1, 4, -1, -1, -1},
503 {-1, -1, -1, 6, 1, -1, -1, -1},
504 {-1, -1, -1, 6, -1, -1, -1, -1}},
505 {{-1, -1, -1, 5, 4, -1, -1, -1},
506 {-1, -1, 4, 1, 0, -1, -1, -1},
507 {-1, -1, -1, 2, 3, -1, -1, -1},
508 {-1, 1, 4, -1, 2, 2, -1, -1},
509 {-1, 3, 1, 2, 5, 1, 4, -1},
510 {-1, 4, 2, -1, 0, 4, -1, -1},
511 {-1, -1, -1, -1, -1, -1, -1, -1},
512 {-1, -1, -1, -1, -1, -1, -1, -1},
513 {-1, -1, -1, -1, -1, -1, -1, -1},
514 {-1, -1, -1, -1, -1, -1, -1, -1}},
515 {{-1, -1, -1, -1, 1, -1, -1, -1},
516 {-1, -1, -1, 1, -1, -1, -1, -1},
517 {-1, 2, -1, -1, 1, -1, 5, -1},
518 { 5, -1, -1, 1, -1, -1, 0, -1},
519 {-1, 6, -1, -1, 1, -1, 4, -1},
520 {-1, 0, -1, 1, -1, 5, -1, -1},
521 {-1, -1, 5, 5, 0, 1, -1, -1},
522 {-1, -1, -1, -1, -1, -1, -1, -1},
523 {-1, -1, -1, -1, -1, -1, -1, -1},
524 {-1, -1, -1, -1, -1, -1, -1, -1}},
525 {{-1, -1, -1, 6, 3, -1, -1, -1},
526 {-1, -1, 3, 2, 6, -1, -1, -1},
527 {-1, -1, 2, 6, 3, 2, -1, -1},
528 {-1, 6, 3, 2, 6, 3, -1, -1},
529 {-1, 3, 2, 6, 3, 2, 6, -1},
530 { 2, 6, 3, 2, 6, 3, 2, -1},
531 { 6, 3, 2, 6, 3, 2, 6, 3},
532 {-1, -1, -1, -1, -1, -1, -1, -1},
533 {-1, -1, -1, -1, -1, -1, -1, -1},
534 {-1, -1, -1, -1, -1, -1, -1, -1}},
535 {{ 6, 6, 6, 6, 6, 6, 6, 6},
536 { 4, -1, -1, -1, -1, -1, -1, -1},
537 {-1, 3, 2, 5, 7, 6, 4, 3},
538 {-1, 5, -1, -1, -1, -1, -1, -1},
539 {-1, -1, 7, 6, 4, 3, 2, 5},
540 {-1, -1, 4, -1, -1, -1, -1, -1},
541 {-1, -1, -1, 3, 2, 5, 7, 6},
542 {-1, -1, -1, -1, -1, -1, -1, -1},
543 {-1, -1, -1, -1, -1, -1, -1, -1},
544 {-1, -1, -1, -1, -1, -1, -1, -1}},
545 {{ 1, -1, 7, -1, -1, 6, -1, 2},
546 { 6, -1, 1, -1, 6, 1, 3, -1},
547 {-1, 4, -1, 7, 2, -1, 7, -1},
548 { 2, 7, -1, -1, -1, 4, -1, -1},
549 { 6, -1, 3, 5, 0, 2, -1, 7},
550 { 1, -1, -1, -1, -1, -1, 1, -1},
551 {-1, 1, 4, 5, 7, 5, 1, -1},
552 {-1, -1, -1, -1, -1, -1, -1, -1},
553 {-1, -1, -1, -1, -1, -1, -1, -1},
554 {-1, -1, -1, -1, -1, -1, -1, -1}},
555 {{ 6, 6, 6, -1, -1, 6, 6, 6},
556 {-1, -1, 6, -1, 6, -1, -1, -1},
557 {-1, -1, 2, 3, 3, 2, -1, -1},
558 {-1, 3, -1, 5, -1, 3, -1, -1},
559 {-1, -1, 5, 3, 3, 5, -1, -1},
560 {-1, -1, 6, 1, 6, -1, -1, -1},
561 {-1, 4, 2, -1, -1, 2, 4, -1},
562 {-1, -1, -1, -1, -1, -1, -1, -1},
563 {-1, -1, -1, -1, -1, -1, -1, -1},
564 {-1, -1, -1, -1, -1, -1, -1, -1}},
565 {{-1, -1, -1, 5, 5, -1, -1, -1},
566 {-1, -1, 5, -1, -1, -1, -1, -1},
567 {-1, 3, 4, 6, 6, -1, -1, 5},
568 { 3, 3, 4, 6, 5, -1, 5, -1},
569 { 3, 2, 3, 6, 6, 5, 5, -1},
570 { 3, 3, 4, 6, 5, -1, 5, -1},
571 {-1, 3, 4, 6, 6, -1, -1, 5},
572 {-1, -1, 5, -1, -1, -1, -1, -1},
573 {-1, -1, -1, 5, 5, -1, -1, -1},
574 {-1, -1, -1, -1, -1, -1, -1, -1}},
575 {{ 1, -1, -1, -1, -1, -1, -1, 1},
576 { 1, -1, 2, 2, 2, -1, 1, -1},
577 {-1, 1, 2, 3, 3, 2, 1, -1},
578 { 6, 2, 3, -1, 3, 2, 6, -1},
579 { 6, 2, 3, -1, -1, 3, 2, 6},
580 { 6, 2, 3, -1, 3, 2, 6, -1},
581 { 3, 3, 3, 7, 7, 3, 3, 3},
582 { 0, 5, 0, 2, 0, 5, 0, -1},
583 {-1, -1, -1, -1, -1, -1, -1, -1},
584 {-1, -1, -1, -1, -1, -1, -1, -1}},
585 {{-1, -1, 7, 7, 7, -1, -1, -1},
586 {-1, 7, 2, 2, 7, -1, -1, -1},
587 {-1, 7, 5, 5, 5, 7, -1, -1},
588 { 7, 7, 7, 7, 7, 7, -1, -1},
589 {-1, -1, 6, -1, 6, -1, -1, -1},
590 {-1, 6, -1, -1, 6, -1, -1, -1},
591 {-1, 6, 4, 4, -1, 6, 4, 4},
592 {-1, -1, -1, -1, -1, -1, -1, -1},
593 {-1, -1, -1, -1, -1, -1, -1, -1},
594 {-1, -1, -1, -1, -1, -1, -1, -1}},
595 {{-1, 3, 3, -1, 3, 3, 3, -1},
596 { 3, 7, 5, 4, 6, 5, 3, -1},
597 { 1, 3, 3, 3, -1, 3, 3, 1},
598 { 2, 1, 2, 1, 2, 1, 2, -1},
599 { 1, 3, 3, -1, 3, 3, 3, 1},
600 { 3, 5, 6, 4, 5, 7, 3, -1},
601 { 2, 3, 3, 3, -1, 3, 3, 2},
602 { 1, 1, 2, 2, 2, 1, 1, -1},
603 {-1, -1, -1, -1, -1, -1, -1, -1},
604 {-1, -1, -1, -1, -1, -1, -1, -1}},
605 {{-1, 6, 5, -1, -1, -1, -1, -1},
606 { 3, 1, 3, -1, -1, -1, -1, -1},
607 {-1, 5, 6, -1, -1, -1, -1, -1},
608 {-1, -1, 5, 3, -1, -1, -1, -1},
609 {-1, -1, 6, 1, 6, -1, -1, -1},
610 {-1, -1, 3, 5, -1, -1, -1, -1},
611 {-1, -1, -1, -1, 3, 6, -1, -1},
612 {-1, -1, -1, 5, 6, 5, -1, -1},
613 {-1, -1, -1, -1, 6, 3, -1, -1},
614 {-1, -1, -1, -1, -1, -1, -1, -1}},
615 {{ 6, 3, 7, 4, 5, 1, 6, 3},
616 { 5, 1, 6, 3, 7, 4, 5, -1},
617 { 6, 3, 7, 4, 5, 1, 6, 3},
618 {-1, -1, -1, -1, -1, -1, -1, -1},
619 {-1, -1, -1, -1, -1, -1, -1, -1},
620 {-1, -1, -1, -1, -1, -1, -1, -1},
621 {-1, -1, -1, -1, -1, -1, -1, -1},
622 {-1, -1, -1, -1, -1, -1, -1, -1},
623 {-1, -1, -1, -1, -1, -1, -1, -1},
624 {-1, -1, -1, -1, -1, -1, -1, -1}},
625 {{-1, -1, -1, -1, -1, -1, 4, 4},
626 {-1, -1, 7, 7, 7, 4, 4, -1},
627 {-1, -1, -1, -1, -1, -1, 4, 4},
628 {-1, 1, -1, -1, -1, 7, -1, -1},
629 {-1, 1, 1, -1, -1, 7, -1, -1},
630 { 3, 3, 3, -1, 7, -1, -1, -1},
631 { 3, -1, 2, 3, 3, 3, -1, 3},
632 {-1, 2, -1, 3, -1, 3, 3, -1},
633 {-1, 2, -1, -1, -1, -1, -1, -1},
634 {-1, -1, -1, -1, -1, -1, -1, -1}},
635 {{-1, -1, 4, -1, -1, -1, -1, -1},
636 {-1, 7, 4, -1, -1, -1, -1, -1},
637 {-1, -1, 7, 4, -1, -1, -1, -1},
638 {-1, 4, 7, 4, -1, -1, -1, -1},
639 { 1, 1, 1, 1, 1, 1, 1, -1},
640 { 1, 2, 1, 2, 1, 1, -1, -1},
641 { 2, 2, 2, 2, 2, 2, 2, 2},
642 {-1, -1, -1, -1, -1, -1, -1, -1},
643 {-1, -1, -1, -1, -1, -1, -1, -1},
644 {-1, -1, -1, -1, -1, -1, -1, -1}},
645 {{ 0, -1, -1, -1, -1, -1, -1, 6},
646 { 6, 1, 4, 3, 7, 5, 0, -1},
647 { 0, -1, -1, -1, -1, -1, -1, 6},
648 { 6, 1, 4, 3, 7, 5, 0, -1},
649 { 0, -1, -1, -1, -1, -1, -1, 6},
650 { 6, 1, 4, 3, 7, 5, 0, -1},
651 {-1, -1, -1, -1, -1, -1, -1, -1},
652 {-1, -1, -1, -1, -1, -1, -1, -1},
653 {-1, -1, -1, -1, -1, -1, -1, -1},
654 {-1, -1, -1, -1, -1, -1, -1, -1}},
655 {{ 3, 3, 4, 6, 6, 4, 3, 3},
656 { 0, 3, 4, 6, 4, 3, 1, -1},
657 { 5, 1, 3, 4, 4, 3, 0, 1},
658 { 0, 1, 3, 4, 3, 1, 0, -1},
659 { 2, 1, 6, 3, 3, 0, 0, 1},
660 { 0, 3, 4, 3, 6, 1, 5, -1},
661 { 6, 1, 2, 6, 4, 0, 0, 2},
662 {-1, -1, -1, -1, -1, -1, -1, -1},
663 {-1, -1, -1, -1, -1, -1, -1, -1},
664 {-1, -1, -1, -1, -1, -1, -1, -1}},
665 {{ 6, 6, -1, -1, -1, -1, 4, 4},
666 { 4, 0, -1, -1, -1, 3, 6, -1},
667 { 0, 6, -1, -1, -1, -1, 4, 2},
668 { 7, -1, -1, -1, -1, -1, 7, -1},
669 { 4, 4, -1, -1, -1, -1, 5, 6},
670 { 6, 4, 7, 7, 5, 6, 4, -1},
671 {-1, 7, 6, 4, 6, 4, 7, -1},
672 {-1, 0, -1, 7, -1, 7, -1, -1},
673 {-1, -1, -1, -1, -1, -1, -1, -1},
674 {-1, -1, -1, -1, -1, -1, -1, -1}},
675 {{-1, 5, -1, -1, -1, -1, 4, -1},
676 {-1, 5, -1, -1, -1, 4, -1, -1},
677 {-1, -1, 5, 6, 6, 4, -1, -1},
678 {-1, -1, 2, -1, 2, -1, -1, -1},
679 { 0, 0, 6, -1, -1, 6, 1, 1},
680 {-1, -1, 2, -1, 2, -1, -1, -1},
681 {-1, -1, 7, 6, 6, 3, -1, -1},
682 {-1, 7, -1, -1, -1, 3, -1, -1},
683 {-1, 7, -1, -1, -1, -1, 3, -1},
684 {-1, -1, -1, -1, -1, -1, -1, -1}},
685 {{-1, 6, -1, -1, -1, -1, 2, -1},
686 { 1, 7, 1, 1, 1, 3, 1, -1},
687 {-1, -1, 4, 1, 1, 4, -1, -1},
688 {-1, 1, 3, 1, 7, 1, -1, -1},
689 {-1, -1, -1, 2, 6, -1, -1, -1},
690 {-1, -1, 1, 5, 1, -1, -1, -1},
691 {-1, -1, -1, -1, -1, -1, -1, -1},
692 {-1, -1, -1, -1, -1, -1, -1, -1},
693 {-1, -1, -1, -1, -1, -1, -1, -1},
694 {-1, -1, -1, -1, -1, -1, -1, -1}},
695 {{ 7, 7, 7, 7, 7, 7, 7, 7},
696 { 7, -1, -1, -1, -1, -1, 7, -1},
697 { 7, -1, -1, 2, 0, 5, 2, 2},
698 { 7, -1, -1, -1, 0, 3, 6, -1},
699 { 7, -1, -1, -1, -1, -1, 4, 0},
700 { 5, 5, -1, -1, -1, -1, -1, -1},
701 { 4, 3, 6, 2, -1, -1, -1, -1},
702 { 0, 2, 0, 4, -1, -1, -1, -1},
703 {-1, -1, -1, -1, -1, -1, -1, -1},
704 {-1, -1, -1, -1, -1, -1, -1, -1}},
705 {{-1, -1, 1, -1, -1, 1, -1, -1},
706 {-1, 4, -1, -1, 5, -1, -1, -1},
707 {-1, 7, -1, -1, 1, 1, 1, -1},
708 { 6, -1, -1, -1, -1, 7, -1, -1},
709 { 1, 1, 1, 1, -1, 4, -1, -1},
710 {-1, -1, 5, -1, -1, -1, -1, -1},
711 {-1, -1, 0, -1, -1, -1, -1, -1},
712 {-1, 3, -1, -1, -1, -1, -1, -1},
713 {-1, 1, -1, -1, -1, -1, -1, -1},
714 {-1, -1, -1, -1, -1, -1, -1, -1}},
715 {{-1, 7, 7, -1, -1, 7, 7, -1},
716 { 6, -1, 4, -1, 4, -1, 6, -1},
717 { 5, -1, -1, 3, 3, -1, -1, 5},
718 { 6, -1, -1, -1, -1, -1, 6, -1},
719 {-1, 7, -1, -1, -1, -1, 7, -1},
720 {-1, 4, -1, -1, -1, 4, -1, -1},
721 {-1, -1, 3, -1, -1, 3, -1, -1},
722 {-1, -1, 2, -1, 2, -1, -1, -1},
723 {-1, -1, -1, 5, 5, -1, -1, -1},
724 {-1, -1, -1, -1, -1, -1, -1, -1}},
725 {{-1, 0, 0, -1, -1, 0, 0, -1},
726 { 7, 4, 6, 6, 6, 4, 3, -1},
727 { 5, 6, 6, 6, 2, 6, 6, 3},
728 { 7, 4, 6, 6, 6, 4, 3, -1},
729 {-1, 0, 0, -1, -1, 0, 0, -1},
730 {-1, -1, -1, -1, -1, -1, -1, -1},
731 {-1, -1, -1, -1, -1, -1, -1, -1},
732 {-1, -1, -1, -1, -1, -1, -1, -1},
733 {-1, -1, -1, -1, -1, -1, -1, -1},
734 {-1, -1, -1, -1, -1, -1, -1, -1}},
735 {{-1, -1, -1, -1, -1, 7, 7, 7},
736 {-1, -1, -1, -1, 2, 7, 7, -1},
737 {-1, 0, 7, 7, 7, -1, 7, 7},
738 { 6, 7, 7, 7, -1, -1, -1, -1},
739 { 6, -1, -1, -1, 7, 7, 7, 7},
740 { 6, -1, -1, -1, -1, -1, -1, -1},
741 { 4, 2, 2, 2, 4, -1, 3, -1},
742 { 4, 4, 4, 4, 3, 3, 3, -1},
743 {-1, -1, -1, -1, -1, -1, -1, -1},
744 {-1, -1, -1, -1, -1, -1, -1, -1}},
745 {{ 4, -1, -1, 7, -1, 6, -1, 7},
746 { 7, 6, 7, -1, -1, 7, 4, -1},
747 {-1, -1, 7, -1, -1, 7, -1, -1},
748 {-1, 0, 0, 0, 0, 0, 3, -1},
749 {-1, -1, 0, 2, 2, 0, 6, 4},
750 {-1, -1, 0, 0, 0, 1, 3, -1},
751 {-1, -1, -1, 0, 0, -1, 3, 4},
752 {-1, -1, -1, 6, -1, 5, 6, -1},
753 {-1, -1, -1, -1, -1, -1, 1, 0},
754 {-1, -1, -1, -1, -1, -1, -1, -1}},
755 {{-1, 5, -1, -1, -1, -1, 5, -1},
756 { 0, -1, -1, 0, -1, -1, 0, -1},
757 { 0, 0, 0, 2, 2, 0, 0, 0},
758 { 0, -1, -1, 0, -1, -1, 0, -1},
759 {-1, 7, -1, 3, -1, -1, 7, -1},
760 {-1, -1, 3, 6, -1, -1, -1, -1},
761 {-1, -1, -1, 6, -1, -1, -1, -1},
762 {-1, 3, 6, -1, -1, -1, -1, -1},
763 {-1, 3, -1, -1, -1, -1, -1, -1},
764 {-1, -1, -1, -1, -1, -1, -1, -1}},
765 {{-1, -1, -1, 6, 5, -1, -1, -1},
766 {-1, -1, 2, 6, 3, -1, -1, -1},
767 {-1, -1, 5, 4, 7, 1, -1, -1},
768 {-1, 6, 2, 2, 3, 4, -1, -1},
769 {-1, -1, 3, 7, 3, 6, -1, -1},
770 {-1, -1, 1, 3, 2, -1, -1, -1},
771 {-1, -1, -1, 4, 5, -1, -1, -1},
772 {-1, -1, -1, 4, -1, -1, -1, -1},
773 {-1, -1, -1, -1, -1, -1, -1, -1},
774 {-1, -1, -1, -1, -1, -1, -1, -1}},
775 {{ 7, 7, -1, 2, 2, -1, 6, 6},
776 { 6, -1, -1, 6, -1, -1, 3, -1},
777 { 2, -1, -1, 1, -1, -1, 2, -1},
778 { 5, -1, -1, 3, -1, -1, 2, -1},
779 { 1, -1, -1, 2, -1, -1, 1, -1},
780 { 5, -1, -1, 2, -1, -1, 2, -1},
781 { 6, -1, -1, 1, -1, -1, 7, -1},
782 { 5, -1, -1, 5, -1, -1, 4, -1},
783 {-1, -1, -1, -1, -1, -1, -1, -1},
784 {-1, -1, -1, -1, -1, -1, -1, -1}},
785 {{-1, -1, -1, 6, 6, -1, -1, -1},
786 {-1, 0, 4, 4, 4, 0, -1, -1},
787 {-1, -1, -1, 6, 6, -1, -1, -1},
788 {-1, -1, 2, 7, 2, -1, -1, -1},
789 {-1, -1, -1, 6, 6, -1, -1, -1},
790 {-1, 0, 5, 5, 5, 0, -1, -1},
791 {-1, -1, -1, 3, 3, -1, -1, -1},
792 {-1, -1, -1, -1, -1, -1, -1, -1},
793 {-1, -1, -1, -1, -1, -1, -1, -1},
794 {-1, -1, -1, -1, -1, -1, -1, -1}},
795 {{-1, -1, 4, 1, 3, -1, -1, -1},
796 {-1, 1, -1, -1, 1, -1, -1, -1},
797 {-1, -1, 4, 1, 3, 4, 1, -1},
798 {-1, 1, 3, 4, -1, -1, 4, -1},
799 {-1, 3, -1, -1, 3, 4, 1, -1},
800 {-1, 1, 3, 4, 1, 3, -1, -1},
801 {-1, -1, 4, 1, -1, -1, -1, -1},
802 {-1, -1, -1, -1, -1, -1, -1, -1},
803 {-1, -1, -1, -1, -1, -1, -1, -1},
804 {-1, -1, -1, -1, -1, -1, -1, -1}},
805 {{-1, 6, 4, -1, 3, 2, 5, -1},
806 { 0, -1, -1, -1, -1, -1, 1, -1},
807 {-1, 2, 3, 5, -1, 4, 6, -1},
808 { 0, -1, -1, -1, -1, -1, 1, -1},
809 {-1, 4, 6, -1, 2, 5, 3, -1},
810 { 0, -1, -1, -1, -1, -1, 1, -1},
811 {-1, 5, 2, 3, -1, 4, 6, -1},
812 {-1, -1, -1, -1, -1, -1, -1, -1},
813 {-1, -1, -1, -1, -1, -1, -1, -1},
814 {-1, -1, -1, -1, -1, -1, -1, -1}},
815 {{-1, -1, -1, 6, 6, -1, -1, -1},
816 {-1, -1, 7, 6, 4, -1, -1, -1},
817 {-1, 2, 1, 7, 4, 1, 3, -1},
818 { 2, 1, 1, 1, 1, 1, 3, -1},
819 {-1, 2, 2, 2, 3, 3, 3, -1},
820 {-1, -1, -1, 5, -1, -1, -1, -1},
821 {-1, -1, -1, 2, 3, -1, -1, -1},
822 {-1, -1, -1, 5, -1, -1, -1, -1},
823 {-1, -1, 2, 2, 3, 3, -1, -1},
824 {-1, -1, -1, -1, -1, -1, -1, -1}},
825 {{ 4, -1, 5, -1, -1, 3, -1, 6},
826 { 2, -1, 3, -1, 2, -1, 4, -1},
827 { 4, -1, -1, 1, 0, -1, -1, 6},
828 { 6, -1, 2, 3, 5, -1, 4, -1},
829 { 4, -1, -1, 0, 1, -1, -1, 6},
830 { 2, -1, 5, -1, 3, -1, 4, -1},
831 { 4, -1, 3, -1, -1, 2, -1, 6},
832 { 6, -1, -1, -1, -1, -1, 4, -1},
833 {-1, -1, -1, -1, -1, -1, -1, -1},
834 {-1, -1, -1, -1, -1, -1, -1, -1}},
835 {{ 2, 6, 0, 5, 5, 1, 3, 4},
836 { 1, -1, -1, 2, -1, -1, 0, -1},
837 { 4, -1, -1, 3, 6, -1, -1, 2},
838 {-1, -1, -1, 0, -1, -1, -1, -1},
839 {-1, -1, -1, 1, 4, -1, -1, -1},
840 {-1, -1, -1, 2, -1, -1, -1, -1},
841 {-1, -1, -1, 6, 3, -1, -1, -1},
842 {-1, -1, -1, 5, -1, -1, -1, -1},
843 {-1, -1, -1, 4, 1, -1, -1, -1},
844 {-1, -1, -1, -1, -1, -1, -1, -1}},
845 {{-1, -1, -1, -1, 5, 1, 1, 3},
846 { 0, 5, 1, 0, 5, 3, 3, -1},
847 { 5, 1, 0, 5, 1, 0, 5, 1},
848 { 0, 5, 1, 0, 5, 1, 6, -1},
849 {-1, -1, -1, -1, 1, 6, 5, 1},
850 {-1, -1, -1, -1, 5, 1, 6, -1},
851 {-1, -1, -1, -1, 1, 0, 5, 1},
852 {-1, -1, -1, -1, 5, 1, 0, -1},
853 {-1, -1, -1, -1, -1, -1, -1, -1},
854 {-1, -1, -1, -1, -1, -1, -1, -1}},
855 {{-1, 0, 7, 3, -1, -1, 2, 2},
856 {-1, 0, 7, 3, -1, -1, 2, -1},
857 {-1, 0, 7, 3, -1, -1, 2, 2},
858 {-1, 0, 7, 3, -1, 3, 1, -1},
859 {-1, 0, 7, 3, -1, 6, 4, 5},
860 {-1, 0, 7, 3, -1, 7, 0, -1},
861 {-1, 0, 7, 3, -1, 2, 3, 4},
862 {-1, 0, 7, 3, -1, 5, 6, -1},
863 {-1, -1, -1, -1, -1, 7, 0, 1},
864 {-1, -1, -1, -1, -1, -1, -1, -1}},
865 {{-1, -1, -1, 7, 7, 7, 7, -1},
866 { 3, 4, 5, -1, -1, -1, 7, -1},
867 { 2, -1, -1, -1, -1, -1, -1, 3},
868 { 7, -1, -1, -1, -1, -1, 4, -1},
869 { 7, -1, -1, -1, 3, 4, 5, 6},
870 { 7, -1, -1, 2, 0, 1, 2, -1},
871 { 6, -1, -1, -1, 3, 4, 5, 6},
872 { 0, 1, -1, -1, -1, -1, -1, -1},
873 { 2, 3, 4, -1, -1, -1, -1, -1},
874 { 5, 6, 0, -1, -1, -1, -1, -1}},
875 {{-1, 7, -1, -1, -1, -1, 2, -1},
876 { 1, 1, -1, -1, -1, 3, 3, -1},
877 {-1, 2, -1, -1, -1, -1, 4, -1},
878 { 3, 3, -1, -1, -1, 5, 5, -1},
879 {-1, 4, -1, -1, -1, -1, 6, -1},
880 { 5, 5, -1, -1, -1, 1, 1, -1},
881 {-1, 6, -1, -1, -1, -1, 7, -1},
882 {-1, -1, -1, -1, -1, -1, -1, -1},
883 {-1, -1, -1, -1, -1, -1, -1, -1},
884 {-1, -1, -1, -1, -1, -1, -1, -1}},
885 {{-1, 4, -1, -1, -1, -1, 4, -1},
886 { 2, -1, -1, 1, -1, -1, 2, -1},
887 { 5, -1, -1, 0, 0, -1, -1, 5},
888 { 5, -1, -1, 1, -1, -1, 6, -1},
889 {-1, 4, 2, 7, 7, 5, 4, -1},
890 {-1, -1, -1, 6, -1, -1, -1, -1},
891 {-1, -1, -1, 3, 3, -1, -1, -1},
892 {-1, -1, -1, 7, -1, -1, -1, -1},
893 {-1, -1, -1, -1, -1, -1, -1, -1},
894 {-1, -1, -1, -1, -1, -1, -1, -1}},
895 {{-1, 1, -1, -1, 2, 3, 4, -1},
896 { 2, -1, -1, 3, 0, 4, -1, -1},
897 { 4, -1, -1, 2, 3, 1, -1, -1},
898 { 3, -1, 4, 3, 0, -1, -1, -1},
899 { 4, -1, -1, 2, 5, 1, -1, -1},
900 { 3, -1, 4, 5, 0, 4, -1, -1},
901 {-1, -1, -1, -1, -1, -1, -1, -1},
902 {-1, -1, -1, -1, -1, -1, -1, -1},
903 {-1, -1, -1, -1, -1, -1, -1, -1},
904 {-1, -1, -1, -1, -1, -1, -1, -1}},
905 {{ 2, -1, -1, 1, 1, -1, -1, 2},
906 { 2, -1, 3, 3, 3, -1, 2, -1},
907 {-1, 2, -1, 4, 4, -1, 2, -1},
908 {-1, 7, 7, 0, 7, 7, -1, -1},
909 {-1, -1, -1, 4, 4, -1, -1, -1},
910 {-1, -1, 5, 7, 5, -1, -1, -1},
911 { 6, 3, 2, 6, 4, 2, 3, 6},
912 { 5, -1, -1, -1, -1, -1, 1, -1},
913 {-1, -1, -1, -1, -1, -1, -1, -1},
914 {-1, -1, -1, -1, -1, -1, -1, -1}},
915 {{ 4, 2, 3, 5, 7, 1, 3, 6},
916 { 1, -1, -1, 1, -1, -1, 1, -1},
917 { 3, 0, 1, 3, 2, 4, 3, 5},
918 { 4, -1, -1, 4, -1, -1, 4, -1},
919 {-1, 5, -1, -1, 5, -1, -1, 5},
920 { 0, 3, 2, 0, 4, 5, 0, -1},
921 {-1, 6, -1, -1, 6, -1, -1, 6},
922 { 7, -1, -1, 7, -1, -1, 7, -1},
923 {-1, -1, -1, -1, -1, -1, -1, -1},
924 {-1, -1, -1, -1, -1, -1, -1, -1}},
925 {{-1, 5, 4, -1, 1, 1, -1, -1},
926 { 5, -1, 4, 1, -1, 1, -1, -1},
927 { 0, -1, -1, -1, -1, -1, 0, -1},
928 { 0, 6, 4, -1, -1, 4, 2, -1},
929 {-1, 4, 3, 5, 2, 6, 3, 6},
930 {-1, 2, 6, -1, -1, 5, 4, -1},
931 {-1, -1, -1, -1, -1, -1, -1, -1},
932 {-1, -1, -1, -1, -1, -1, -1, -1},
933 {-1, -1, -1, -1, -1, -1, -1, -1},
934 {-1, -1, -1, -1, -1, -1, -1, -1}},
935 {{-1, -1, -1, 6, 6, -1, -1, -1},
936 {-1, -1, 5, 5, 4, -1, -1, -1},
937 {-1, -1, 1, 6, 6, 4, -1, -1},
938 {-1, 1, 7, 2, 5, 3, -1, -1},
939 {-1, 2, 7, 2, 1, 5, 3, -1},
940 { 2, 1, 3, 1, 4, 2, 7, -1},
941 {-1, 3, 1, 3, 4, 2, 7, -1},
942 {-1, 3, 5, 5, 6, 6, -1, -1},
943 {-1, -1, -1, -1, -1, -1, -1, -1},
944 {-1, -1, -1, -1, -1, -1, -1, -1}},
945 {{-1, -1, 7, 3, -1, -1, -1, -1},
946 {-1, 1, 7, 6, -1, -1, -1, -1},
947 {-1, 3, 7, 5, 1, 5, -1, -1},
948 { 7, 7, 0, 2, 4, 0, 4, -1},
949 { 7, 1, 4, 6, 5, 6, 5, 7},
950 { 1, 7, 7, 1, 7, 7, 1, -1},
951 {-1, -1, -1, -1, -1, -1, -1, -1},
952 {-1, -1, -1, -1, -1, -1, -1, -1},
953 {-1, -1, -1, -1, -1, -1, -1, -1},
954 {-1, -1, -1, -1, -1, -1, -1, -1}},
955 {{-1, -1, 1, -1, -1, 1, -1, -1},
956 {-1, 5, 6, 1, 5, 6, -1, -1},
957 {-1, 1, 1, 2, 2, 1, 1, -1},
958 { 4, 7, 1, 0, 1, 7, 4, -1},
959 {-1, 3, 7, 5, 7, 5, 3, -1},
960 {-1, 1, 1, 1, 1, 1, -1, -1},
961 {-1, -1, -1, -1, -1, -1, -1, -1},
962 {-1, -1, -1, -1, -1, -1, -1, -1},
963 {-1, -1, -1, -1, -1, -1, -1, -1},
964 {-1, -1, -1, -1, -1, -1, -1, -1}},
965 {{ 4, -1, -1, -1, 5, -1, -1, 4},
966 { 6, 6, 7, 6, -1, 4, 5, -1},
967 { 4, 2, 7, 5, 2, 2, 6, 4},
968 {-1, -1, 4, 1, -1, 5, 2, -1},
969 {-1, 5, 2, 7, 7, -1, 7, 4},
970 { 4, 6, 5, 4, -1, 4, 2, -1},
971 {-1, -1, -1, 4, -1, 4, 1, -1},
972 { 0, 0, 0, 5, -1, -1, -1, -1},
973 {-1, -1, -1, -1, 0, 0, 0, 0},
974 {-1, -1, -1, -1, -1, -1, -1, -1}},
975 {{ 1, -1, -1, -1, 0, 0, -1, -1},
976 { 2, -1, -1, 0, 1, 0, -1, -1},
977 { 3, -1, -1, 0, 2, 2, 0, -1},
978 { 4, -1, 0, 1, 1, 1, 0, -1},
979 { 5, -1, -1, 0, 4, 4, 0, -1},
980 { 6, -1, -1, 4, 4, 4, -1, -1},
981 { 7, -1, -1, -1, 4, 4, -1, -1},
982 {-1, -1, -1, 0, 1, 0, -1, -1},
983 {-1, -1, -1, 0, 1, 1, 0, -1},
984 {-1, -1, -1, -1, -1, -1, -1, -1}},
985 {{-1, -1, 3, -1, -1, 1, 7, -1},
986 {-1, 7, 4, -1, -1, 4, 3, -1},
987 { 1, -1, -1, 0, 2, 0, -1, -1},
988 { 5, 4, -1, 3, -1, -1, -1, -1},
989 { 4, -1, 3, 6, 1, 1, 6, -1},
990 {-1, 1, -1, -1, 4, -1, 1, -1},
991 {-1, 7, 5, -1, -1, -1, 3, -1},
992 {-1, -1, 3, -1, -1, -1, -1, -1},
993 {-1, -1, -1, -1, -1, -1, -1, -1},
994 {-1, -1, -1, -1, -1, -1, -1, -1}},
995 {{ 1, -1, -1, -1, 1, -1, -1, -1},
996 { 2, -1, -1, -1, 2, -1, -1, -1},
997 {-1, 3, -1, -1, 3, 3, -1, -1},
998 {-1, 4, -1, 4, -1, 4, -1, -1},
999 {-1, 5, -1, -1, 5, 5, -1, -1},
1000 { 6, -1, -1, 7, 1, 7, -1, -1},
1001 { 7, -1, -1, -1, 6, 6, -1, -1},
1002 {-1, -1, -1, -1, -1, -1, -1, -1},
1003 {-1, -1, -1, -1, -1, -1, -1, -1},
1004 {-1, -1, -1, -1, -1, -1, -1, -1}},
1005 {{ 2, -1, -1, 6, -1, 2, 5, 1},
1006 { 5, -1, 4, -1, 4, -1, 4, -1},
1007 { 6, -1, -1, 3, -1, -1, -1, 3},
1008 { 4, 2, 0, -1, -1, -1, 5, -1},
1009 {-1, -1, -1, 6, -1, 3, 6, -1},
1010 {-1, -1, 5, -1, 5, -1, -1, -1},
1011 {-1, -1, -1, 3, -1, 4, 2, 5},
1012 {-1, -1, -1, -1, -1, -1, -1, -1},
1013 {-1, -1, -1, -1, -1, -1, -1, -1},
1014 {-1, -1, -1, -1, -1, -1, -1, -1}},
1015 {{ 6, -1, -1, -1, 4, -1, -1, 3},
1016 { 0, 3, -1, -1, 6, -1, 0, -1},
1017 {-1, -1, 7, -1, 1, -1, 3, -1},
1018 { 7, -1, 4, 7, -1, 2, -1, -1},
1019 { 5, 2, 3, 2, 1, 6, -1, 3},
1020 {-1, -1, 0, 4, 3, 5, 4, -1},
1021 {-1, 7, 6, -1, -1, 0, -1, -1},
1022 { 4, 3, -1, -1, -1, 4, 2, -1},
1023 { 0, -1, -1, -1, -1, -1, 6, -1},
1024 {-1, -1, -1, -1, -1, -1, -1, -1}},
1025 {{ 6, 1, 2, 5, 1, 6, 3, 0},
1026 {-1, -1, -1, -1, -1, -1, 4, -1},
1027 { 0, 5, 2, 7, 1, 6, 2, -1},
1028 { 3, -1, -1, -1, -1, -1, -1, -1},
1029 { 6, 7, 6, 4, 0, 5, 2, 6},
1030 {-1, -1, -1, -1, -1, -1, 1, -1},
1031 { 6, 1, 4, 0, 6, 2, 3, -1},
1032 { 0, -1, -1, -1, -1, -1, -1, -1},
1033 {-1, 0, 4, 5, 3, 7, 6, 0},
1034 {-1, -1, -1, -1, -1, -1, -1, -1}},
1035 {{-1, -1, -1, 0, 1, -1, -1, -1},
1036 {-1, -1, 0, 7, 0, -1, -1, -1},
1037 {-1, -1, 1, 2, 2, 0, -1, -1},
1038 {-1, 0, 7, 0, 7, 0, -1, -1},
1039 {-1, 6, -1, 7, 7, -1, 6, -1},
1040 { 4, 1, 6, 6, 6, 4, 1, -1},
1041 {-1, 5, -1, 7, 7, -1, 5, -1},
1042 {-1, -1, -1, -1, -1, -1, -1, -1},
1043 {-1, -1, -1, -1, -1, -1, -1, -1},
1044 {-1, -1, -1, -1, -1, -1, -1, -1}},
1045 {{-1, -1, -1, 5, 6, -1, -1, -1},
1046 {-1, -1, 3, 3, 3, -1, -1, -1},
1047 {-1, -1, 7, 5, 3, 7, -1, -1},
1048 {-1, 3, -1, 6, -1, 3, -1, -1},
1049 { 2, -1, -1, 3, 7, -1, -1, 1},
1050 { 2, 2, -1, 3, -1, 1, 1, -1},
1051 {-1, 0, 2, 5, 6, 1, 0, -1},
1052 {-1, -1, -1, 3, -1, -1, -1, -1},
1053 {-1, -1, -1, 3, 7, -1, -1, -1},
1054 {-1, -1, -1, -1, -1, -1, -1, -1}},
1055 {{-1, 6, -1, -1, -1, -1, 2, -1},
1056 {-1, 2, 6, 0, 6, 0, -1, -1},
1057 {-1, 0, -1, -1, -1, -1, -1, -1},
1058 { 6, -1, -1, -1, -1, -1, -1, -1},
1059 {-1, 3, 3, 2, 0, 6, 0, 0},
1060 {-1, 6, -1, -1, -1, -1, 0, -1},
1061 {-1, -1, -1, 6, 0, 2, 6, -1},
1062 {-1, 2, 0, -1, -1, -1, -1, -1},
1063 {-1, -1, -1, -1, -1, -1, -1, -1},
1064 {-1, -1, -1, -1, -1, -1, -1, -1}},
1065 {{ 0, 7, -1, -1, -1, -1, -1, -1},
1066 { 1, 5, -1, -1, -1, -1, -1, -1},
1067 { 7, 2, 5, -1, -1, -1, -1, -1},
1068 { 6, 3, 4, -1, -1, -1, -1, -1},
1069 { 5, 5, 4, 4, -1, -1, -1, -1},
1070 { 3, 3, 5, 3, -1, -1, -1, -1},
1071 { 1, 2, 2, 5, 3, -1, -1, -1},
1072 { 1, 0, 0, 7, 6, -1, -1, -1},
1073 { 3, 3, 5, 5, 7, 6, -1, -1},
1074 {-1, -1, -1, -1, -1, -1, -1, -1}},
1075 {{-1, -1, 2, 6, 6, 2, -1, -1},
1076 {-1, 2, 1, 1, 0, 2, -1, -1},
1077 {-1, 2, 3, 2, 2, 0, 2, -1},
1078 { 2, 3, 2, 5, 2, 7, 2, -1},
1079 { 2, 4, 2, 5, 2, 7, 2, 0},
1080 { 2, 4, 2, 6, 6, 2, 0, -1},
1081 {-1, 2, 5, 2, 2, 2, 7, 2},
1082 {-1, 2, 5, 6, 6, 7, 2, -1},
1083 {-1, -1, 2, 2, 2, 2, 2, -1},
1084 {-1, -1, -1, -1, -1, -1, -1, -1}},
1085 {{-1, -1, 0, -1, -1, 0, -1, -1},
1086 { 1, 0, 0, 1, 0, 0, 1, -1},
1087 { 1, 7, 7, 5, 5, 7, 7, 1},
1088 { 3, 2, -1, 2, -1, 2, 3, -1},
1089 { 3, 7, -1, 6, 6, -1, 7, 3},
1090 { 7, -1, -1, 6, -1, -1, 7, -1},
1091 { 4, 4, 5, -1, -1, 5, 4, 4},
1092 {-1, -1, -1, -1, -1, -1, -1, -1},
1093 {-1, -1, -1, -1, -1, -1, -1, -1},
1094 {-1, -1, -1, -1, -1, -1, -1, -1}},
1095 {{-1, 6, 3, -1, -1, 3, 6, -1},
1096 { 6, -1, 2, -1, 2, -1, 6, -1},
1097 { 2, -1, 0, 1, 1, 0, -1, 2},
1098 { 5, 0, -1, 7, -1, 0, 5, -1},
1099 {-1, 5, -1, 6, 6, -1, 5, -1},
1100 { 7, 1, 4, -1, 4, 1, 7, -1},
1101 { 7, -1, 4, -1, -1, 4, -1, 7},
1102 { 2, 0, -1, -1, -1, 0, 2, -1},
1103 {-1, 2, -1, -1, -1, -1, 2, -1},
1104 {-1, -1, -1, -1, -1, -1, -1, -1}},
1105 {{ 6, 1, -1, -1, -1, -1, 4, 0},
1106 { 2, 7, 5, 5, 5, 7, 3, -1},
1107 { 6, 1, -1, -1, -1, -1, 4, 0},
1108 { 2, 5, 7, 7, 7, 5, 3, -1},
1109 { 6, 1, -1, -1, -1, -1, 4, 0},
1110 { 2, 0, 6, 6, 6, 0, 3, -1},
1111 { 6, 1, -1, -1, -1, -1, 4, 0},
1112 {-1, -1, -1, -1, -1, -1, -1, -1},
1113 {-1, -1, -1, -1, -1, -1, -1, -1},
1114 {-1, -1, -1, -1, -1, -1, -1, -1}},
1115 {{ 5, -1, -1, 1, 1, -1, -1, 5},
1116 { 5, -1, 4, -1, 4, -1, 5, -1},
1117 {-1, 2, 4, -1, -1, 4, 2, -1},
1118 { 7, 2, -1, -1, -1, 2, 7, -1},
1119 { 0, -1, 0, 4, 4, 0, -1, 0},
1120 { 7, 2, -1, -1, -1, 2, 7, -1},
1121 {-1, 2, 3, -1, -1, 3, 2, -1},
1122 { 5, -1, 3, -1, 3, -1, 5, -1},
1123 { 5, -1, -1, 6, 6, -1, -1, 5},
1124 {-1, -1, -1, -1, -1, -1, -1, -1}},
1125 {{ 2, 2, -1, -1, -1, -1, 5, 5},
1126 { 5, -1, -1, -1, -1, -1, 2, -1},
1127 { 5, -1, -1, -1, -1, -1, -1, 2},
1128 { 1, -1, 1, 5, 1, -1, 3, -1},
1129 { 5, 2, 5, 3, 1, 2, 5, 2},
1130 { 2, 0, 5, -1, 2, 0, 5, -1},
1131 {-1, 3, 7, -1, -1, 3, 7, -1},
1132 {-1, -1, 2, 0, 5, -1, -1, -1},
1133 {-1, -1, -1, -1, -1, -1, -1, -1},
1134 {-1, -1, -1, -1, -1, -1, -1, -1}},
1135 {{ 0, 6, 5, 2, 3, 4, 1, 7},
1136 {-1, -1, -1, -1, 1, -1, -1, -1},
1137 {-1, -1, -1, 1, 1, -1, -1, -1},
1138 {-1, -1, 1, -1, -1, -1, -1, -1},
1139 { 7, 1, 4, 3, 2, 5, 6, 0},
1140 {-1, -1, -1, -1, 1, -1, -1, -1},
1141 {-1, -1, -1, 1, 1, -1, -1, -1},
1142 {-1, -1, 1, -1, -1, -1, -1, -1},
1143 { 0, 6, 5, 2, 3, 4, 1, 7},
1144 {-1, -1, -1, -1, -1, -1, -1, -1}},
1145 {{-1, -1, 1, -1, -1, 1, -1, -1},
1146 {-1, 2, 4, -1, 2, 4, -1, -1},
1147 {-1, 2, 3, 6, 5, 3, 2, -1},
1148 {-1, 6, 5, -1, 6, 5, -1, -1},
1149 {-1, -1, -1, 7, 7, -1, -1, -1},
1150 {-1, -1, -1, 7, -1, -1, -1, -1},
1151 { 1, -1, -1, 7, 7, -1, -1, 3},
1152 { 2, -1, -1, 7, -1, -1, 2, -1},
1153 {-1, 3, 4, 5, 6, 4, 1, -1},
1154 {-1, -1, -1, -1, -1, -1, -1, -1}},
1155 {{ 1, -1, -1, 2, 2, -1, -1, 2},
1156 { 1, 3, 7, 3, 7, 4, 2, -1},
1157 {-1, 1, 6, -1, -1, 6, 2, -1},
1158 { 6, -1, 7, 3, 7, -1, 6, -1},
1159 {-1, 4, 2, -1, -1, 1, 3, -1},
1160 {-1, -1, 2, 6, 1, -1, -1, -1},
1161 {-1, 4, 3, 3, 4, 4, 3, -1},
1162 {-1, -1, -1, -1, -1, -1, -1, -1},
1163 {-1, -1, -1, -1, -1, -1, -1, -1},
1164 {-1, -1, -1, -1, -1, -1, -1, -1}},
1165 {{-1, -1, -1, 5, 6, -1, -1, -1},
1166 {-1, -1, -1, 3, -1, -1, -1, -1},
1167 {-1, -1, -1, 1, 2, -1, -1, -1},
1168 {-1, -1, -1, 4, -1, -1, -1, -1},
1169 {-1, -1, -1, 5, 7, -1, -1, -1},
1170 {-1, -1, -1, 2, -1, -1, -1, -1},
1171 { 6, 5, 4, 3, 2, 1, 7, 5},
1172 {-1, -1, -1, -1, -1, -1, -1, -1},
1173 {-1, -1, -1, -1, -1, -1, -1, -1},
1174 {-1, -1, -1, -1, -1, -1, -1, -1}},
1175 {{-1, 0, -1, 1, -1, 2, -1, -1},
1176 {-1, 4, -1, 5, -1, 6, -1, -1},
1177 {-1, 7, -1, 0, -1, 2, -1, -1},
1178 {-1, 6, -1, 3, -1, 6, -1, -1},
1179 {-1, 1, -1, 1, -1, 2, -1, -1},
1180 {-1, 3, -1, 5, -1, 0, -1, -1},
1181 {-1, 2, -1, 4, -1, 6, -1, -1},
1182 {-1, 3, -1, 6, -1, 7, -1, -1},
1183 {-1, -1, -1, -1, -1, -1, -1, -1},
1184 {-1, -1, -1, -1, -1, -1, -1, -1}},
1185 {{ 1, 1, 2, 2, 3, 3, 4, 4},
1186 { 5, 5, 6, 7, 6, 5, 5, -1},
1187 { 6, 4, 3, 3, 2, 2, 1, 6},
1188 { 4, 6, 5, 7, 6, 3, 1, -1},
1189 {-1, -1, -1, -1, -1, -1, -1, -1},
1190 {-1, -1, -1, -1, -1, -1, -1, -1},
1191 {-1, -1, -1, -1, -1, -1, -1, -1},
1192 {-1, -1, -1, -1, -1, -1, -1, -1},
1193 {-1, -1, -1, -1, -1, -1, -1, -1},
1194 {-1, -1, -1, -1, -1, -1, -1, -1}},
1195 {{ 7, 4, -1, 1, 2, -1, 4, 7},
1196 { 5, 5, -1, 2, -1, 4, 4, -1},
1197 {-1, 5, -1, 7, 7, -1, 4, -1},
1198 { 1, 0, 6, 7, 6, 0, 2, -1},
1199 {-1, 2, -1, 5, 3, -1, 1, -1},
1200 { 1, 1, -1, -1, -1, 2, 2, -1},
1201 { 6, 1, 4, -1, -1, 4, 2, 6},
1202 { 5, 3, -1, -1, -1, 3, 5, -1},
1203 {-1, -1, -1, -1, -1, -1, -1, -1},
1204 {-1, -1, -1, -1, -1, -1, -1, -1}},
1205 {{ 1, 5, 1, 0, 0, 1, 5, 1},
1206 { 1, 2, 5, -1, 5, 2, 1, -1},
1207 { 3, 6, 1, 2, 2, 1, 6, 3},
1208 { 4, 3, 4, -1, 4, 3, 4, -1},
1209 { 3, 4, 6, 5, 5, 6, 4, 3},
1210 { 0, 2, 3, -1, 3, 2, 0, -1},
1211 { 2, 3, 1, 5, 5, 1, 3, 2},
1212 {-1, -1, -1, -1, -1, -1, -1, -1},
1213 {-1, -1, -1, -1, -1, -1, -1, -1},
1214 {-1, -1, -1, -1, -1, -1, -1, -1}},
1215 {{ 3, 0, 2, 7, 5, 7, 6, 5},
1216 { 6, -1, 1, -1, 2, -1, 1, -1},
1217 {-1, 6, 4, 0, 3, 4, 5, -1},
1218 {-1, 5, -1, 1, -1, 4, -1, -1},
1219 {-1, 7, 3, 5, 6, 5, 3, -1},
1220 { 1, -1, 2, -1, 4, -1, 2, -1},
1221 { 6, 4, 4, 6, 6, 5, 5, 1},
1222 {-1, -1, -1, -1, -1, -1, -1, -1},
1223 {-1, -1, -1, -1, -1, -1, -1, -1},
1224 {-1, -1, -1, -1, -1, -1, -1, -1}}
1227 /* the tile struct
1228 * type is the bubble number 0-7
1229 * fallx is the x axis movement for the falling bubble
1230 * fallvel is the initial upward velocity for the falling bubble
1231 * ingroup denotes a bubble that is part of a group to be removed
1232 * anchored denotes a bubble that is anchored to the ceiling
1234 struct tile {
1235 int type;
1236 int fallx;
1237 int fallvel;
1238 bool ingroup;
1239 bool anchored;
1240 bool delete;
1243 /* the game context struct
1244 * score is the current score
1245 * level is the current level
1246 * angle is the current cannon direction
1247 * shots is the number of shots fired since last compression
1248 * compress is the height of the compressor
1249 * onboardcnt is the number of unique bubbles on the playing board
1250 * onboard is the unique bubbles on the playing board
1251 * nextinq is the pointer to the next bubble in the firing queue
1252 * queue is the circular buffer of bubbles to be fired
1253 * elapsedlvl is level elapsed time in 1/100s of seconds
1254 * elapsedshot is the shot elapsed time in 1/100s of seconds
1255 * startedshot is when the current shot began
1256 * playboard is the game playing board
1258 struct game_context {
1259 unsigned int score;
1260 unsigned int level;
1261 int angle;
1262 int shots;
1263 int compress;
1264 int onboardcnt;
1265 int onboard[NUM_BUBBLES];
1266 int nextinq;
1267 int queue[NUM_QUEUE];
1268 long elapsedlvl;
1269 long elapsedshot;
1270 long startedshot;
1271 struct tile playboard[BB_HEIGHT][BB_WIDTH];
1274 struct highscore highscores[NUM_SCORES];
1276 /* used to denote available resume info */
1277 static bool resume = false;
1278 static bool resume_file = false;
1279 static unsigned int highlevel = 0; /* the highest level beaten */
1280 static unsigned int last_highlevel = 0;
1282 static void bubbles_init(struct game_context* bb);
1283 static bool bubbles_nextlevel(struct game_context* bb);
1284 static void bubbles_getonboard(struct game_context* bb);
1285 static void bubbles_drawboard(struct game_context* bb);
1286 static int bubbles_fire(struct game_context* bb);
1287 static bool bubbles_collision(struct game_context* bb, int y, int x,
1288 int nearrow, int nearcol);
1289 static bool bubbles_ingroup(struct game_context* bb, int row, int col);
1290 static int bubbles_searchgroup(struct game_context* bb, int row, int col);
1291 static int bubbles_remove(struct game_context* bb);
1292 static void bubbles_anchored(struct game_context* bb, int row, int col);
1293 static int bubbles_fall(struct game_context* bb);
1294 static int bubbles_checklevel(struct game_context* bb);
1295 static void bubbles_recordscore(struct game_context* bb);
1296 static bool bubbles_loadgame(struct game_context* bb);
1297 static void bubbles_savegame(struct game_context* bb);
1298 static inline void bubbles_setcolors(void);
1299 static void bubbles_callback(void* param);
1300 static int bubbles_handlebuttons(struct game_context* bb, bool animblock,
1301 int timeout);
1302 static int bubbles(struct game_context* bb);
1304 /*****************************************************************************
1305 * bubbles_init() initializes bubbles data structures.
1306 ******************************************************************************/
1307 static void bubbles_init(struct game_context* bb) {
1308 bubbles_setcolors();
1309 /* seed the rand generator */
1310 rb->srand(*rb->current_tick);
1312 /* check for resumed game */
1313 if (resume)
1315 resume = false;
1316 return;
1319 bb->score = 0;
1320 bubbles_nextlevel(bb);
1323 /*****************************************************************************
1324 * bubbles_nextlevel() sets up the game for the next level, returns false if
1325 * there are no more levels.
1326 ******************************************************************************/
1327 static bool bubbles_nextlevel(struct game_context* bb) {
1328 int i, j, pos;
1330 bb->level++;
1332 /* check if there are no more levels */
1333 if(bb->level > NUM_LEVELS) return false;
1335 /* save highest level */
1336 if (bb->level-1 > highlevel)
1337 highlevel = bb->level-1;
1339 /* set up the play board */
1340 rb->memset(bb->playboard, 0, sizeof(bb->playboard));
1341 for(i=0; i<BB_LEVEL_HEIGHT; i++) {
1342 for(j=0; j<BB_WIDTH; j++) {
1343 pos = (int)level[bb->level-1][i][j];
1344 if(pos >=0 && pos < NUM_BUBBLES) {
1345 bb->playboard[i][j].type = pos;
1346 } else {
1347 bb->playboard[i][j].type = -1;
1351 for(i=BB_LEVEL_HEIGHT; i<BB_HEIGHT; i++) {
1352 for(j=0; j<BB_WIDTH; j++) {
1353 bb->playboard[i][j].type = -1;
1357 /* fill first bubbles in shot queue */
1358 bubbles_getonboard(bb);
1359 for(i=0; i<NUM_QUEUE; i++) {
1360 bb->queue[i] = bb->onboard[rb->rand()%bb->onboardcnt];
1363 bb->angle = 0;
1364 bb->shots = 0;
1365 bb->compress = 0;
1366 bb->nextinq = 0;
1367 bb->elapsedlvl = 0;
1368 bb->elapsedshot = 0;
1370 return true;
1373 /*****************************************************************************
1374 * bubbles_getonboard() determines which bubble types are on the play board.
1375 ******************************************************************************/
1376 static void bubbles_getonboard(struct game_context* bb) {
1377 int i, j, k;
1378 bool found;
1380 bb->onboardcnt = 0;
1381 rb->memset(bb->onboard, -1, sizeof(bb->onboard));
1383 for(i=0; i<BB_HEIGHT; i++) {
1384 for(j=0; j<BB_WIDTH; j++) {
1385 if(bb->playboard[i][j].type >= 0) {
1386 found = false;
1388 for(k=0; k<bb->onboardcnt; k++) {
1389 if(bb->playboard[i][j].type == bb->onboard[k]) {
1390 found = true;
1391 break;
1395 if(!found) {
1396 bb->onboard[bb->onboardcnt] = bb->playboard[i][j].type;
1397 bb->onboardcnt++;
1400 if(bb->onboardcnt == NUM_BUBBLES) return;
1406 /*****************************************************************************
1407 * bubbles_drawboard() draws the game board to the buffer but does not update
1408 * the lcd.
1409 ******************************************************************************/
1410 static void bubbles_drawboard(struct game_context* bb) {
1411 int i, j;
1412 int w1, w2, h;
1413 int colmax, indent;
1414 int tipx, tipy;
1415 bool evenline = false;
1416 char *level = "Level";
1417 char *score = "Score";
1418 char *next = "Next";
1419 char *hurry = "HURRY!";
1420 char str[11];
1422 /* clear screen */
1423 rb->lcd_clear_display();
1424 int font = rb->screens[SCREEN_MAIN]->getfont();
1425 h = rb->font_get(font)->height + 1;
1426 /* draw background */
1427 #ifdef HAVE_LCD_COLOR
1428 rb->lcd_bitmap(bubbles_background, 0, 0, LCD_WIDTH, LCD_HEIGHT);
1429 #endif
1431 /* display play board */
1432 for(i=0; i<BB_HEIGHT; i++) {
1433 colmax = BB_WIDTH;
1434 if(evenline) {
1435 colmax--;
1436 indent = ROW_INDENT;
1437 } else {
1438 indent = 0;
1440 evenline = !evenline;
1442 for(j=0; j<colmax; j++) {
1443 if(bb->playboard[i][j].type >= 0 && !bb->playboard[i][j].delete) {
1444 rb->lcd_bitmap_part(bubbles_emblem,
1445 0, EMBLEM_HEIGHT*bb->playboard[i][j].type,
1446 STRIDE( SCREEN_MAIN,
1447 BMPWIDTH_bubbles_emblem, BMPHEIGHT_bubbles_emblem),
1448 XOFS+indent+BUBBLE_WIDTH*j+(BUBBLE_WIDTH-EMBLEM_WIDTH)/2,
1449 YOFS+ROW_HEIGHT*i+(BUBBLE_HEIGHT-EMBLEM_HEIGHT)/2+bb->compress*ROW_HEIGHT,
1450 EMBLEM_WIDTH, EMBLEM_HEIGHT);
1451 rb->lcd_set_drawmode(DRMODE_FG);
1452 rb->lcd_mono_bitmap((const unsigned char *)bubbles_bubble,
1453 XOFS+indent+BUBBLE_WIDTH*j,
1454 YOFS+ROW_HEIGHT*i+bb->compress*ROW_HEIGHT,
1455 BUBBLE_WIDTH, BUBBLE_HEIGHT);
1456 rb->lcd_set_drawmode(DRMODE_SOLID);
1461 /* display bubble to be shot */
1462 rb->lcd_bitmap_part(bubbles_emblem,
1463 0, EMBLEM_HEIGHT*bb->queue[bb->nextinq],
1464 STRIDE( SCREEN_MAIN,
1465 BMPWIDTH_bubbles_emblem, BMPHEIGHT_bubbles_emblem),
1466 SHOTX+(BUBBLE_WIDTH-EMBLEM_WIDTH)/2,
1467 SHOTY+(BUBBLE_HEIGHT-EMBLEM_HEIGHT)/2,
1468 EMBLEM_WIDTH, EMBLEM_HEIGHT);
1469 rb->lcd_set_drawmode(DRMODE_FG);
1470 rb->lcd_mono_bitmap((const unsigned char *)bubbles_bubble,
1471 SHOTX, SHOTY,
1472 BUBBLE_WIDTH, BUBBLE_HEIGHT);
1473 rb->lcd_set_drawmode(DRMODE_SOLID);
1475 /* display next bubble to be shot */
1476 #ifndef NEXT_BB_X
1477 rb->lcd_bitmap_part(bubbles_emblem,
1478 0, EMBLEM_HEIGHT*bb->queue[(bb->nextinq+1)%NUM_QUEUE],
1479 STRIDE( SCREEN_MAIN,
1480 BMPWIDTH_bubbles_emblem, BMPHEIGHT_bubbles_emblem),
1481 XOFS/2-BUBBLE_WIDTH/2+(BUBBLE_WIDTH-EMBLEM_WIDTH)/2,
1482 SHOTY+(BUBBLE_HEIGHT-EMBLEM_HEIGHT)/2,
1483 EMBLEM_WIDTH, EMBLEM_HEIGHT);
1484 rb->lcd_set_drawmode(DRMODE_FG);
1485 rb->lcd_mono_bitmap((const unsigned char *)bubbles_bubble,
1486 XOFS/2-BUBBLE_WIDTH/2, SHOTY,
1487 BUBBLE_WIDTH, BUBBLE_HEIGHT);
1488 rb->lcd_set_drawmode(DRMODE_SOLID);
1489 #else
1490 rb->lcd_bitmap_part(bubbles_emblem,
1491 0, EMBLEM_HEIGHT*bb->queue[(bb->nextinq+1)%NUM_QUEUE],
1492 STRIDE( SCREEN_MAIN,
1493 BMPWIDTH_bubbles_emblem, BMPHEIGHT_bubbles_emblem),
1494 NEXT_BB_X + NEXT_BB_WIDTH/2-BUBBLE_WIDTH/2+(BUBBLE_WIDTH-EMBLEM_WIDTH)/2,
1495 NEXT_BB_Y + (BUBBLE_HEIGHT-EMBLEM_HEIGHT)/2 + h,
1496 EMBLEM_WIDTH, EMBLEM_HEIGHT);
1497 rb->lcd_set_drawmode(DRMODE_FG);
1498 rb->lcd_mono_bitmap((const unsigned char *)bubbles_bubble,
1499 NEXT_BB_X + NEXT_BB_WIDTH/2-BUBBLE_WIDTH/2, NEXT_BB_Y + h,
1500 BUBBLE_WIDTH, BUBBLE_HEIGHT);
1501 rb->lcd_set_drawmode(DRMODE_SOLID);
1502 #endif
1504 /* draw bounding lines */
1505 #ifndef HAVE_LCD_COLOR
1506 rb->lcd_vline(XOFS-1, 0, LCD_HEIGHT);
1507 rb->lcd_vline(XOFS+BUBBLE_WIDTH*BB_WIDTH, 0, LCD_HEIGHT);
1508 #endif
1509 rb->lcd_hline(XOFS, XOFS+BUBBLE_WIDTH*BB_WIDTH-1, YOFS+bb->compress*ROW_HEIGHT-1);
1510 rb->lcd_hline(XOFS, XOFS+BUBBLE_WIDTH*BB_WIDTH-1,
1511 YOFS+ROW_HEIGHT*(BB_HEIGHT-2)+BUBBLE_HEIGHT);
1513 /* draw arrow */
1514 tipx = SHOTX+BUBBLE_WIDTH/2+(((fp14_sin(bb->angle)>>4)*BUBBLE_WIDTH*3/2)>>10);
1515 tipy = SHOTY+BUBBLE_HEIGHT/2-(((fp14_cos(bb->angle)>>4)*BUBBLE_HEIGHT*3/2)>>10);
1517 rb->lcd_drawline(SHOTX+BUBBLE_WIDTH/2+(((fp14_sin(bb->angle)>>4)*BUBBLE_WIDTH/2)>>10),
1518 SHOTY+BUBBLE_HEIGHT/2-(((fp14_cos(bb->angle)>>4)*BUBBLE_HEIGHT/2)>>10),
1519 tipx, tipy);
1520 xlcd_filltriangle(tipx, tipy,
1521 tipx+(((fp14_sin(bb->angle-135)>>4)*BUBBLE_WIDTH/3)>>10),
1522 tipy-(((fp14_cos(bb->angle-135)>>4)*BUBBLE_HEIGHT/3)>>10),
1523 tipx+(((fp14_sin(bb->angle+135)>>4)*BUBBLE_WIDTH/3)>>10),
1524 tipy-(((fp14_cos(bb->angle+135)>>4)*BUBBLE_HEIGHT/3)>>10));
1526 /* draw text */
1527 rb->snprintf(str, 4, "%d", bb->level);
1528 rb->lcd_getstringsize(level, &w1, NULL);
1529 rb->lcd_getstringsize(str, &w2, NULL);
1530 #ifndef LEVEL_TXT_X
1531 rb->lcd_putsxy(XOFS/2-w1/2, 2, level);
1532 rb->lcd_putsxy(XOFS/2-w2/2, 2+h, str);
1533 #else
1534 rb->lcd_putsxy(LEVEL_TXT_X+(LEVEL_TXT_WIDTH/2-w1/2), LEVEL_TXT_Y, level);
1535 rb->lcd_putsxy(LEVEL_TXT_X+(LEVEL_TXT_WIDTH/2-w2/2), LEVEL_TXT_Y+h, str);
1536 #endif
1538 rb->snprintf(str, 10, "%d", bb->score);
1539 rb->lcd_getstringsize(score, &w1,NULL);
1540 rb->lcd_getstringsize(str, &w2, NULL);
1541 #ifndef SCORE_TXT_X
1542 rb->lcd_putsxy(XOFS/2-w1/2, 29, score);
1543 rb->lcd_putsxy(XOFS/2-w2/2, 29+h, str);
1544 #else
1545 rb->lcd_putsxy(SCORE_TXT_X+(SCORE_TXT_WIDTH/2-w1/2), SCORE_TXT_Y, score);
1546 rb->lcd_putsxy(SCORE_TXT_X+(SCORE_TXT_WIDTH/2-w2/2), SCORE_TXT_Y+h, str);
1547 #endif
1549 rb->lcd_getstringsize(next, &w1, NULL);
1550 #ifndef NEXT_BB_X
1551 rb->lcd_putsxy(XOFS/2-w1/2, SHOTY-h, next);
1552 #else
1553 rb->lcd_putsxy(NEXT_BB_X+(NEXT_BB_WIDTH/2-w1/2), NEXT_BB_Y, next);
1554 #endif
1557 if(bb->elapsedshot >= (MAX_SHOTTIME*7)/10) {
1558 rb->lcd_getstringsize(hurry, &w1, &h);
1559 rb->lcd_putsxy(LCD_WIDTH/2-w1/2, LCD_HEIGHT/2-h/2, hurry);
1563 /*****************************************************************************
1564 * bubbles_fire() fires the current bubble, reloads the cannon, attaches
1565 * bubble to playboard, removes appropriate bubbles, and advances the
1566 * the compressor.
1567 ******************************************************************************/
1568 static int bubbles_fire(struct game_context* bb) {
1569 int bubblecur;
1570 long shotxinc, shotyinc;
1571 long shotxofs, shotyofs;
1572 int shotxdirec = 1;
1573 long tempxofs, tempyofs;
1574 int nearrow, nearcol;
1575 int lastrow = BB_HEIGHT-1;
1576 int lastcol = (BB_WIDTH-1)/2;
1577 int buttonres;
1578 long lasttick, currenttick;
1580 /* get current bubble */
1581 bubblecur = bb->queue[bb->nextinq];
1582 shotxinc = ((fp14_sin(bb->angle)>>4)*BUBBLE_WIDTH)/3;
1583 shotyinc = ((-1*(fp14_cos(bb->angle)>>4))*BUBBLE_HEIGHT)/3;
1584 shotxofs = shotyofs = 0;
1586 /* advance the queue */
1587 bb->queue[bb->nextinq] = bb->onboard[rb->rand()%bb->onboardcnt];
1588 bb->nextinq = (bb->nextinq+1)%NUM_QUEUE;
1589 bubbles_drawboard(bb);
1590 rb->lcd_update_rect(0, 0, XOFS, LCD_HEIGHT);
1592 /* move the bubble across the play board */
1593 lasttick = *rb->current_tick;
1595 while(true) {
1596 /* move the bubble one step */
1597 shotyofs += shotyinc;
1598 shotxofs += shotxinc*shotxdirec;
1600 /* check for bounce off sides */
1601 if(SHOTX+(shotxofs>>10) < XOFS) {
1602 shotxofs += 2*((XOFS<<10)-(((SHOTX)<<10)+shotxofs));
1603 shotxdirec *= -1;
1604 } else if(SHOTX+(shotxofs>>10) > XOFS+(BB_WIDTH-1)*BUBBLE_WIDTH) {
1605 shotxofs -= 2*((((SHOTX)<<10)+shotxofs)-
1606 ((XOFS<<10)+(((BB_WIDTH-1)*BUBBLE_WIDTH)<<10)));
1607 shotxdirec *= -1;
1610 tempxofs = shotxofs>>10;
1611 tempyofs = shotyofs>>10;
1613 /* display shot */
1614 bubbles_drawboard(bb);
1615 rb->lcd_bitmap_part(bubbles_emblem, 0, EMBLEM_HEIGHT*bubblecur,
1616 STRIDE( SCREEN_MAIN,
1617 BMPWIDTH_bubbles_emblem,
1618 BMPHEIGHT_bubbles_emblem),
1619 SHOTX+tempxofs+(BUBBLE_WIDTH-EMBLEM_WIDTH)/2,
1620 SHOTY+tempyofs+(BUBBLE_HEIGHT-EMBLEM_HEIGHT)/2,
1621 EMBLEM_WIDTH, EMBLEM_HEIGHT);
1622 rb->lcd_set_drawmode(DRMODE_FG);
1623 rb->lcd_mono_bitmap((const unsigned char *)bubbles_bubble,
1624 SHOTX+tempxofs, SHOTY+tempyofs,
1625 BUBBLE_WIDTH, BUBBLE_HEIGHT);
1626 rb->lcd_set_drawmode(DRMODE_SOLID);
1627 rb->lcd_update_rect(XOFS, 0, BB_WIDTH*BUBBLE_WIDTH, LCD_HEIGHT);
1629 /* find nearest position */
1630 nearrow = ((SHOTY+tempyofs)-
1631 (YOFS+bb->compress*ROW_HEIGHT)+
1632 (ROW_HEIGHT/2))/ROW_HEIGHT;
1633 if(nearrow >= BB_HEIGHT) nearrow = BB_HEIGHT-1;
1635 if(nearrow%2) { /* odd row */
1636 nearcol = ((SHOTX+tempxofs)-
1637 (XOFS+ROW_INDENT)+
1638 (BUBBLE_WIDTH/2))/BUBBLE_WIDTH;
1639 if(nearcol >= BB_WIDTH-1) nearcol = BB_WIDTH-2;
1640 } else { /* even row */
1641 nearcol = ((SHOTX+tempxofs)-XOFS+(BUBBLE_WIDTH/2))/BUBBLE_WIDTH;
1642 if(nearcol >= BB_WIDTH) nearcol = BB_WIDTH-1;
1644 if(nearcol < 0) nearcol = 0;
1646 /* if nearest position is occupied attach to last position */
1647 if(bb->playboard[nearrow][nearcol].type >= 0) {
1648 bb->playboard[lastrow][lastcol].type = bubblecur;
1649 break;
1652 /* save last position */
1653 lastrow = nearrow;
1654 lastcol = nearcol;
1656 /* if collision with neighbor then attach shot */
1657 if(bubbles_collision(bb, YOFS+SHOTY+tempyofs, SHOTX+tempxofs,
1658 nearrow, nearcol)) {
1659 bb->playboard[nearrow][nearcol].type = bubblecur;
1660 break;
1663 /* if at top then attach shot to the ceiling */
1664 if(nearrow == 0 && SHOTY+tempyofs <= YOFS+bb->compress*ROW_HEIGHT) {
1665 bb->playboard[nearrow][nearcol].type = bubblecur;
1666 break;
1669 /* handle button events */
1670 buttonres = bubbles_handlebuttons(bb, true, 0);
1671 if(buttonres != BB_NONE) return buttonres;
1673 /* framerate limiting */
1674 currenttick = *rb->current_tick;
1675 if(currenttick-lasttick < HZ/MAX_FPS) {
1676 rb->sleep((HZ/MAX_FPS)-(currenttick-lasttick));
1677 } else {
1678 rb->yield();
1680 lasttick = currenttick;
1683 bubbles_drawboard(bb);
1684 rb->lcd_update();
1686 /* clear appropriate bubbles from playing board */
1687 if(bubbles_ingroup(bb, lastrow, lastcol)) {
1688 buttonres = bubbles_remove(bb);
1689 if(buttonres != BB_NONE) return buttonres;
1692 /* update shots and compress amount */
1693 bb->shots++;
1694 if(bb->shots >= NUM_COMPRESS) {
1695 bb->shots = 0;
1696 bb->compress++;
1699 return BB_NONE;
1702 /*****************************************************************************
1703 * bubbles_collision() determines if a fired bubble has collided with another
1704 * bubble.
1705 ******************************************************************************/
1706 static bool bubbles_collision(struct game_context* bb, int y, int x,
1707 int nearrow, int nearcol) {
1708 int nx, ny;
1709 int adj = nearrow%2;
1711 /* check neighbors */
1712 if(nearcol-1 >= 0) {
1713 if(bb->playboard[nearrow][nearcol-1].type >= 0) {
1714 nx = XOFS+(nearrow%2 ? ROW_INDENT : 0)+BUBBLE_WIDTH*(nearcol-1);
1715 ny = YOFS+ROW_HEIGHT*nearrow+bb->compress*ROW_HEIGHT;
1716 if((x-nx)*(x-nx)+(y-ny)*(y-ny) < MIN_DISTANCE) return true;
1720 if(nearcol-1+adj >= 0) {
1721 if(nearrow-1 >= 0) {
1722 if(bb->playboard[nearrow-1][nearcol-1+adj].type >= 0) {
1723 nx = XOFS+((nearrow-1)%2 ? ROW_INDENT : 0)+
1724 BUBBLE_WIDTH*(nearcol-1+adj);
1725 ny = YOFS+ROW_HEIGHT*(nearrow-1)+bb->compress*ROW_HEIGHT;
1726 if((x-nx)*(x-nx)+(y-ny)*(y-ny) < MIN_DISTANCE) return true;
1730 if(nearrow+1 < BB_HEIGHT) {
1731 if(bb->playboard[nearrow+1][nearcol-1+adj].type >= 0) {
1732 nx = XOFS+((nearrow+1)%2 ? ROW_INDENT : 0)+
1733 BUBBLE_WIDTH*(nearcol-1+adj);
1734 ny = YOFS+ROW_HEIGHT*(nearrow+1)+bb->compress*ROW_HEIGHT;
1735 if((x-nx)*(x-nx)+(y-ny)*(y-ny) < MIN_DISTANCE) return true;
1740 if(nearcol+adj >= 0) {
1741 if(nearrow-1 >= 0) {
1742 if(bb->playboard[nearrow-1][nearcol+adj].type >= 0) {
1743 nx = XOFS+((nearrow-1)%2 ? ROW_INDENT : 0)+
1744 BUBBLE_WIDTH*(nearcol+adj);
1745 ny = YOFS+ROW_HEIGHT*(nearrow-1)+bb->compress*ROW_HEIGHT;
1746 if((x-nx)*(x-nx)+(y-ny)*(y-ny) < MIN_DISTANCE) return true;
1750 if(nearrow+1 < BB_HEIGHT) {
1751 if(bb->playboard[nearrow+1][nearcol+adj].type >= 0) {
1752 nx = XOFS+((nearrow+1)%2 ? ROW_INDENT : 0)+
1753 BUBBLE_WIDTH*(nearcol+adj);
1754 ny = YOFS+ROW_HEIGHT*(nearrow+1)+bb->compress*ROW_HEIGHT;
1755 if((x-nx)*(x-nx)+(y-ny)*(y-ny) < MIN_DISTANCE) return true;
1760 if(nearcol+1 < BB_WIDTH-adj) {
1761 if(bb->playboard[nearrow][nearcol+1].type >= 0) {
1762 nx = XOFS+(nearrow%2 ? ROW_INDENT : 0)+BUBBLE_WIDTH*(nearcol+1);
1763 ny = YOFS+ROW_HEIGHT*nearrow+bb->compress*ROW_HEIGHT;
1764 if((x-nx)*(x-nx)+(y-ny)*(y-ny) < MIN_DISTANCE) return true;
1768 return false;
1771 /*****************************************************************************
1772 * bubbles_ingroup() marks all bubbles that form the current group.
1773 ******************************************************************************/
1774 static bool bubbles_ingroup(struct game_context* bb, int row, int col) {
1775 int i, j;
1776 int count;
1778 count = bubbles_searchgroup(bb, row, col);
1780 /* unmark group if too small */
1781 if(count < 3) {
1782 for(i=0; i<BB_HEIGHT; i++) {
1783 for(j=0; j<BB_WIDTH; j++) {
1784 bb->playboard[i][j].ingroup = false;
1788 return false;
1791 return true;
1794 /*****************************************************************************
1795 * bubbles_searchgroup() return the size of the group of bubbles of the same
1796 * type that the current bubble belongs to.
1797 ******************************************************************************/
1798 static int bubbles_searchgroup(struct game_context* bb, int row, int col) {
1799 int i, adj;
1800 int myrow, mycol, mytype;
1801 int count = 0;
1803 struct coord {
1804 int row;
1805 int col;
1806 } search[(2*BB_WIDTH-1)*(BB_HEIGHT/2)];
1808 /* search initial bubble */
1809 bb->playboard[row][col].ingroup = true;
1810 search[count].row = row;
1811 search[count].col = col;
1812 count++;
1814 /* breadth-first search neighbors */
1815 for(i=0; i<count; i++) {
1816 myrow = search[i].row;
1817 mycol = search[i].col;
1818 mytype = bb->playboard[myrow][mycol].type;
1819 adj = myrow%2;
1821 if(mycol-1 >= 0) {
1822 if(bb->playboard[myrow][mycol-1].type == mytype &&
1823 !bb->playboard[myrow][mycol-1].ingroup) {
1824 bb->playboard[myrow][mycol-1].ingroup = true;
1825 search[count].row = myrow;
1826 search[count].col = mycol-1;
1827 count++;
1831 if(mycol-1+adj >= 0) {
1832 if(myrow-1 >= 0) {
1833 if(bb->playboard[myrow-1][mycol-1+adj].type == mytype &&
1834 !bb->playboard[myrow-1][mycol-1+adj].ingroup) {
1835 bb->playboard[myrow-1][mycol-1+adj].ingroup = true;
1836 search[count].row = myrow-1;
1837 search[count].col = mycol-1+adj;
1838 count++;
1842 if(myrow+1 < BB_HEIGHT) {
1843 if(bb->playboard[myrow+1][mycol-1+adj].type == mytype &&
1844 !bb->playboard[myrow+1][mycol-1+adj].ingroup) {
1845 bb->playboard[myrow+1][mycol-1+adj].ingroup = true;
1846 search[count].row = myrow+1;
1847 search[count].col = mycol-1+adj;
1848 count++;
1853 if(mycol+adj >= 0) {
1854 if(myrow-1 >= 0) {
1855 if(bb->playboard[myrow-1][mycol+adj].type == mytype &&
1856 !bb->playboard[myrow-1][mycol+adj].ingroup) {
1857 bb->playboard[myrow-1][mycol+adj].ingroup = true;
1858 search[count].row = myrow-1;
1859 search[count].col = mycol+adj;
1860 count++;
1864 if(myrow+1 < BB_HEIGHT) {
1865 if(bb->playboard[myrow+1][mycol+adj].type == mytype &&
1866 !bb->playboard[myrow+1][mycol+adj].ingroup) {
1867 bb->playboard[myrow+1][mycol+adj].ingroup = true;
1868 search[count].row = myrow+1;
1869 search[count].col = mycol+adj;
1870 count++;
1875 if(mycol+1 < BB_WIDTH-adj) {
1876 if(bb->playboard[myrow][mycol+1].type == mytype &&
1877 !bb->playboard[myrow][mycol+1].ingroup) {
1878 bb->playboard[myrow][mycol+1].ingroup = true;
1879 search[count].row = myrow;
1880 search[count].col = mycol+1;
1881 count++;
1886 return count;
1889 /*****************************************************************************
1890 * bubbles_remove() removes all bubbles in the current group and all
1891 * unanchored bubbles from the play board.
1892 ******************************************************************************/
1893 static int bubbles_remove(struct game_context* bb) {
1894 int i, j;
1895 int buttonres;
1897 /* determine all anchored bubbles */
1898 for(j=0; j<BB_WIDTH; j++) {
1899 if(bb->playboard[0][j].type >= 0 && !bb->playboard[0][j].ingroup) {
1900 bubbles_anchored(bb, 0, j);
1904 /* mark bubbles to be deleted */
1905 for(i=0; i<BB_HEIGHT; i++) {
1906 for(j=0; j<BB_WIDTH; j++) {
1907 if(bb->playboard[i][j].type >= 0 &&
1908 (!bb->playboard[i][j].anchored || bb->playboard[i][j].ingroup)) {
1909 bb->playboard[i][j].delete = true;
1914 /* animate falling bubbles */
1915 buttonres = bubbles_fall(bb);
1916 if(buttonres != BB_NONE) return buttonres;
1918 /* remove bubbles */
1919 for(i=0; i<BB_HEIGHT; i++) {
1920 for(j=0; j<BB_WIDTH; j++) {
1921 if(bb->playboard[i][j].delete) {
1922 bb->playboard[i][j].ingroup = false;
1923 bb->playboard[i][j].type = -1;
1924 bb->playboard[i][j].delete = false;
1925 } else {
1926 bb->playboard[i][j].anchored = false;
1931 bubbles_getonboard(bb);
1933 return BB_NONE;
1936 /*****************************************************************************
1937 * bubbles_anchored() marks all bubbles that are anchored in some way to the
1938 * current bubble.
1939 ******************************************************************************/
1940 static void bubbles_anchored(struct game_context* bb, int row, int col) {
1941 int i, adj;
1942 int myrow, mycol, mytype;
1943 int count = 0;
1945 struct coord {
1946 int row;
1947 int col;
1948 } search[(2*BB_WIDTH-1)*(BB_HEIGHT/2)];
1950 /* search initial bubble */
1951 bb->playboard[row][col].anchored = true;
1952 search[count].row = row;
1953 search[count].col = col;
1954 count++;
1956 /* breadth-first search neighbors */
1957 for(i=0; i<count; i++) {
1958 myrow = search[i].row;
1959 mycol = search[i].col;
1960 mytype = bb->playboard[myrow][mycol].type;
1961 adj = myrow%2;
1963 if(mycol-1 >= 0) {
1964 if(bb->playboard[myrow][mycol-1].type >= 0 &&
1965 !bb->playboard[myrow][mycol-1].ingroup &&
1966 !bb->playboard[myrow][mycol-1].anchored) {
1967 bb->playboard[myrow][mycol-1].anchored = true;
1968 search[count].row = myrow;
1969 search[count].col = mycol-1;
1970 count++;
1974 if(mycol-1+adj >= 0) {
1975 if(myrow-1 >= 0) {
1976 if(bb->playboard[myrow-1][mycol-1+adj].type >= 0 &&
1977 !bb->playboard[myrow-1][mycol-1+adj].ingroup &&
1978 !bb->playboard[myrow-1][mycol-1+adj].anchored) {
1979 bb->playboard[myrow-1][mycol-1+adj].anchored = true;
1980 search[count].row = myrow-1;
1981 search[count].col = mycol-1+adj;
1982 count++;
1986 if(myrow+1 < BB_HEIGHT) {
1987 if(bb->playboard[myrow+1][mycol-1+adj].type >= 0 &&
1988 !bb->playboard[myrow+1][mycol-1+adj].ingroup &&
1989 !bb->playboard[myrow+1][mycol-1+adj].anchored) {
1990 bb->playboard[myrow+1][mycol-1+adj].anchored = true;
1991 search[count].row = myrow+1;
1992 search[count].col = mycol-1+adj;
1993 count++;
1998 if(mycol+adj >= 0) {
1999 if(myrow-1 >= 0) {
2000 if(bb->playboard[myrow-1][mycol+adj].type >= 0 &&
2001 !bb->playboard[myrow-1][mycol+adj].ingroup &&
2002 !bb->playboard[myrow-1][mycol+adj].anchored) {
2003 bb->playboard[myrow-1][mycol+adj].anchored = true;
2004 search[count].row = myrow-1;
2005 search[count].col = mycol+adj;
2006 count++;
2010 if(myrow+1 < BB_HEIGHT) {
2011 if(bb->playboard[myrow+1][mycol+adj].type >= 0 &&
2012 !bb->playboard[myrow+1][mycol+adj].ingroup &&
2013 !bb->playboard[myrow+1][mycol+adj].anchored) {
2014 bb->playboard[myrow+1][mycol+adj].anchored = true;
2015 search[count].row = myrow+1;
2016 search[count].col = mycol+adj;
2017 count++;
2022 if(mycol+1 < BB_WIDTH-adj) {
2023 if(bb->playboard[myrow][mycol+1].type >= 0 &&
2024 !bb->playboard[myrow][mycol+1].ingroup &&
2025 !bb->playboard[myrow][mycol+1].anchored) {
2026 bb->playboard[myrow][mycol+1].anchored = true;
2027 search[count].row = myrow;
2028 search[count].col = mycol+1;
2029 count++;
2035 /*****************************************************************************
2036 * bubbles_fall() makes removed bubbles fall from the screen.
2037 ******************************************************************************/
2038 static int bubbles_fall(struct game_context* bb) {
2039 int i, j;
2040 int count;
2041 int indent;
2042 int xofs, yofs;
2043 int buttonres;
2044 bool onscreen;
2045 long lasttick, currenttick;
2047 /* give all falling bubbles an x axis movement */
2048 for(i=0; i<BB_HEIGHT; i++) {
2049 for(j=0; j<BB_WIDTH; j++) {
2050 if(bb->playboard[i][j].delete) {
2051 bb->playboard[i][j].fallx = rb->rand()%25 - 12;
2052 bb->playboard[i][j].fallvel = rb->rand()%5 + 6;
2057 /* draw bubbles falling off the screen
2058 * follows y=x^2-8x scaled to bubble size
2060 lasttick = *rb->current_tick;
2062 for(count=1; ;count++) {
2063 onscreen = false;
2064 bubbles_drawboard(bb);
2066 for(i=0; i<BB_HEIGHT; i++) {
2067 for(j=0; j<BB_WIDTH; j++) {
2068 if(bb->playboard[i][j].delete) {
2069 indent = (i%2 ? ROW_INDENT : 0);
2070 xofs = ((bb->playboard[i][j].fallx*count)*BUBBLE_WIDTH)/48;
2071 yofs = ((count*count - bb->playboard[i][j].fallvel*count)*
2072 BUBBLE_HEIGHT)/20;
2074 /* draw bubble if it is still on the screen */
2075 if(YOFS+ROW_HEIGHT*i+bb->compress*ROW_HEIGHT+yofs
2076 <= LCD_HEIGHT) {
2077 onscreen = true;
2079 rb->lcd_bitmap_part(bubbles_emblem, 0,
2080 EMBLEM_HEIGHT*bb->playboard[i][j].type,
2081 STRIDE( SCREEN_MAIN,
2082 BMPWIDTH_bubbles_emblem,
2083 BMPHEIGHT_bubbles_emblem),
2084 XOFS+indent+BUBBLE_WIDTH*j+
2085 (BUBBLE_WIDTH-EMBLEM_WIDTH)/2+xofs,
2086 YOFS+ROW_HEIGHT*i+(BUBBLE_HEIGHT-EMBLEM_HEIGHT)/2+
2087 bb->compress*ROW_HEIGHT+yofs,
2088 EMBLEM_WIDTH, EMBLEM_HEIGHT);
2089 rb->lcd_set_drawmode(DRMODE_FG);
2090 rb->lcd_mono_bitmap(
2091 (const unsigned char *)bubbles_bubble,
2092 XOFS+indent+BUBBLE_WIDTH*j+xofs,
2093 YOFS+ROW_HEIGHT*i+bb->compress*ROW_HEIGHT+yofs,
2094 BUBBLE_WIDTH, BUBBLE_HEIGHT);
2095 rb->lcd_set_drawmode(DRMODE_SOLID);
2101 rb->lcd_update();
2103 /* break out if all bubbles are off the screen */
2104 if(!onscreen) break;
2106 /* handle button events */
2107 buttonres = bubbles_handlebuttons(bb, true, 0);
2108 if(buttonres != BB_NONE) return buttonres;
2110 /* framerate limiting */
2111 currenttick = *rb->current_tick;
2112 if(currenttick-lasttick < HZ/MAX_FPS) {
2113 rb->sleep((HZ/MAX_FPS)-(currenttick-lasttick));
2114 } else {
2115 rb->yield();
2117 lasttick = currenttick;
2120 return BB_NONE;
2123 /*****************************************************************************
2124 * bubbles_checklevel() checks the state of the playboard for a win or loss.
2125 ******************************************************************************/
2126 static int bubbles_checklevel(struct game_context* bb) {
2127 int i, j;
2128 int points;
2129 char str[13];
2131 bubbles_drawboard(bb);
2132 rb->lcd_update();
2134 /* check for bubbles below cut off point */
2135 for(i=0; i<=bb->compress; i++) {
2136 for(j=0; j<BB_WIDTH; j++) {
2137 if(bb->playboard[BB_HEIGHT-1-i][j].type >= 0) return BB_LOSE;
2141 /* check for bubbles above cut off point */
2142 for(i=0; i<BB_HEIGHT-1-bb->compress; i++) {
2143 for(j=0; j<BB_WIDTH; j++) {
2144 if(bb->playboard[i][j].type >= 0) return BB_NONE;
2148 /* level complete, record score */
2149 points = 100 - bb->elapsedlvl/100;
2150 if(points > 0) {
2151 bb->score += points;
2152 } else {
2153 points = 0;
2156 rb->snprintf(str, 12, "%d points", points);
2157 rb->splash(HZ, str);
2159 /* advance to the next level */
2160 if(!bubbles_nextlevel(bb)) {
2161 return BB_WIN;
2164 bubbles_drawboard(bb);
2165 rb->lcd_update();
2166 rb->snprintf(str, 12, "Level %d", bb->level);
2167 rb->splash(HZ, str);
2168 bubbles_drawboard(bb);
2169 rb->lcd_update();
2171 return BB_NONE;
2174 /*****************************************************************************
2175 * bubbles_recordscore() inserts a high score into the high scores list and
2176 * returns the high score position.
2177 ******************************************************************************/
2178 static void bubbles_recordscore(struct game_context* bb) {
2180 int position;
2182 position = highscore_update(bb->score, bb->level-1, "",
2183 highscores, NUM_SCORES);
2184 if (position==0)
2185 rb->splash(HZ*2, "New High Score");
2186 if (position != -1)
2187 highscore_show(position, highscores, NUM_SCORES, true);
2190 /*****************************************************************************
2191 * bubbles_loaddata() loads highest level beaten.
2192 ******************************************************************************/
2193 static void bubbles_loaddata(void) {
2194 int fd;
2196 last_highlevel = highlevel = 0;
2197 /* open data file */
2198 fd = rb->open(DATA_FILE, O_RDONLY);
2199 if (fd < 0) return;
2201 /* read in saved game */
2202 if (rb->read(fd, &highlevel, sizeof(highlevel)) < (long)sizeof(highlevel))
2204 highlevel = 0;
2206 if (highlevel >= NUM_LEVELS)
2207 highlevel = NUM_LEVELS-1;
2208 last_highlevel = highlevel;
2210 rb->close(fd);
2213 /*****************************************************************************
2214 * bubbles_savedata() saves the current game state.
2215 ******************************************************************************/
2216 static void bubbles_savedata(void) {
2217 int fd;
2219 if (last_highlevel >= highlevel) /* no need to save */
2220 return;
2222 fd = rb->open(DATA_FILE, O_WRONLY|O_CREAT);
2223 if (fd < 0) return;
2225 rb->write(fd, &highlevel, sizeof(highlevel));
2227 rb->close(fd);
2230 /*****************************************************************************
2231 * bubbles_loadgame() loads the saved game and returns load success.
2232 ******************************************************************************/
2233 static bool bubbles_loadgame(struct game_context* bb) {
2234 int fd;
2236 bool ret = true;
2237 /* open game file */
2238 fd = rb->open(SAVE_FILE, O_RDONLY);
2239 if(fd < 0) return false;
2241 /* read in saved game */
2242 if(rb->read(fd, bb, sizeof(struct game_context))
2243 < (long)sizeof(struct game_context))
2245 ret = false;
2248 rb->close(fd);
2250 return ret;
2253 /*****************************************************************************
2254 * bubbles_savegame() saves the current game state.
2255 ******************************************************************************/
2256 static void bubbles_savegame(struct game_context* bb) {
2257 int fd;
2259 if (!resume) /* nothing to save */
2260 return;
2261 /* write out the game state to the save file */
2262 fd = rb->open(SAVE_FILE, O_WRONLY|O_CREAT);
2263 if (fd < 0)
2265 rb->splash(HZ/2, "Failed to save game");
2266 return;
2268 if (rb->write(fd, bb, sizeof(struct game_context)) <= 0)
2270 rb->splash(HZ/2, "Failed to save game");
2273 rb->close(fd);
2276 /*****************************************************************************
2277 * bubbles_setcolors() set the foreground and background colors.
2278 ******************************************************************************/
2279 static inline void bubbles_setcolors(void) {
2280 #ifdef HAVE_LCD_COLOR
2281 rb->lcd_set_background(LCD_RGBPACK(181,181,222));
2282 rb->lcd_set_foreground(LCD_BLACK);
2283 #endif
2286 /*****************************************************************************
2287 * bubbles_callback() is the default event handler callback which is called
2288 * on usb connect and shutdown.
2289 ******************************************************************************/
2290 static void bubbles_callback(void* param) {
2291 (void) param;
2292 highscore_save(SCORE_FILE, highscores, NUM_SCORES);
2295 /*****************************************************************************
2296 * bubbles_handlebuttons() handles button events during a game.
2297 ******************************************************************************/
2298 static int bubbles_handlebuttons(struct game_context* bb, bool animblock,
2299 int timeout) {
2300 int button;
2301 int buttonres;
2302 long start;
2303 const struct button_mapping *plugin_contexts[]
2304 #if (CONFIG_KEYPAD != SANSA_E200_PAD) && \
2305 (CONFIG_KEYPAD != SANSA_FUZE_PAD)
2306 = {generic_left_right_fire,generic_actions};
2307 #else
2308 = {generic_directions,generic_actions};
2309 #endif
2311 if (timeout < 0)
2312 timeout = 0;
2313 button = pluginlib_getaction(timeout,plugin_contexts,2);
2314 #if defined(HAS_BUTTON_HOLD) && !defined(HAVE_REMOTE_LCD_AS_MAIN)
2315 /* FIXME: Should probably check remote hold here */
2316 if (rb->button_hold())
2317 button = BUBBLES_START;
2318 #endif
2320 switch(button){
2321 case BUBBLES_LEFT_REP:
2322 if(bb->angle > MIN_ANGLE) bb->angle -= ANGLE_STEP_REP;
2323 case BUBBLES_LEFT: /* change angle to the left */
2324 if(bb->angle > MIN_ANGLE) bb->angle -= ANGLE_STEP;
2325 break;
2327 case BUBBLES_RIGHT_REP:
2328 if(bb->angle < MAX_ANGLE) bb->angle += ANGLE_STEP_REP;
2329 case BUBBLES_RIGHT: /* change angle to the right */
2330 if(bb->angle < MAX_ANGLE) bb->angle += ANGLE_STEP;
2331 break;
2333 case BUBBLES_SELECT: /* fire the shot */
2334 if(!animblock) {
2335 bb->elapsedlvl += bb->elapsedshot;
2336 bb->elapsedshot = 0;
2337 buttonres = bubbles_fire(bb);
2338 if(buttonres != BB_NONE) return buttonres;
2339 buttonres = bubbles_checklevel(bb);
2340 if(buttonres != BB_NONE) return buttonres;
2341 bb->startedshot = *rb->current_tick;
2343 break;
2345 case BUBBLES_START: /* pause the game */
2346 start = *rb->current_tick;
2347 rb->splash(0, "Paused");
2348 while(pluginlib_getaction(TIMEOUT_BLOCK,plugin_contexts,2)
2349 != (BUBBLES_START));
2350 bb->startedshot += *rb->current_tick-start;
2351 bubbles_drawboard(bb);
2352 rb->lcd_update();
2353 break;
2355 case BUBBLES_RESUME: /* save and end the game */
2356 case BUBBLES_QUIT: /* end the game */
2357 if(!animblock) {
2358 resume = true;
2359 return BB_END;
2361 break;
2363 case ACTION_UNKNOWN:
2364 case ACTION_NONE: /* no button pressed */
2365 break;
2367 default:
2368 if(rb->default_event_handler_ex(button, bubbles_callback,
2369 (void*) bb) == SYS_USB_CONNECTED)
2370 return BB_USB;
2371 break;
2374 return BB_NONE;
2377 /*****************************************************************************
2378 * bubbles_menu() is the initial menu at the start of the game.
2379 ******************************************************************************/
2380 static int bubbles_menu(struct game_context* bb) {
2381 static unsigned int startlevel = 0;
2382 int selected = resume?0:1;
2383 bool startgame = false;
2385 MENUITEM_STRINGLIST(menu,"Bubbles Menu",NULL,
2386 "Resume Game", "Start New Game",
2387 "Level", "High Scores", "Playback Control",
2388 "Quit without Saving", "Quit");
2390 while(!startgame){
2391 switch (rb->do_menu(&menu, &selected, NULL, false))
2393 case 0: /* resume game */
2394 if (!resume)
2395 rb->splash(HZ/2, "Nothing to resume");
2396 else
2397 startgame = true;
2398 if(resume_file)
2399 rb->remove(SAVE_FILE);
2400 resume_file = false;
2401 break;
2402 case 1: /* new game */
2403 bb->level = startlevel;
2404 startgame = true;
2405 resume = false;
2406 resume_file = false;
2407 break;
2408 case 2: /* choose level */
2409 startlevel++;
2410 rb->set_int("Choose start level", "", UNIT_INT, &startlevel,
2411 NULL, 1, 1, highlevel+1, NULL);
2412 startlevel--;
2413 break;
2414 case 3: /* High scores */
2415 highscore_show(NUM_SCORES, highscores, NUM_SCORES, true);
2416 break;
2417 case 4: /* Playback Control */
2418 playback_control(NULL);
2419 break;
2420 case 5: /* quit but don't save */
2421 return BB_QUIT_WITHOUT_SAVING;
2422 case 6: /* save and quit */
2423 return BB_QUIT;
2424 case MENU_ATTACHED_USB:
2425 bubbles_callback(bb);
2426 return BB_USB;
2429 return 0;
2432 /*****************************************************************************
2433 * bubbles() is the main game subroutine, it returns the final game status.
2434 ******************************************************************************/
2435 static int bubbles(struct game_context* bb) {
2436 int buttonres;
2437 long timeout;
2439 /********************
2440 * menu *
2441 ********************/
2442 buttonres = bubbles_menu(bb);
2443 if(buttonres != 0)
2444 return buttonres;
2446 /********************
2447 * init *
2448 ********************/
2449 bubbles_init(bb);
2450 bubbles_drawboard(bb);
2451 rb->lcd_update();
2453 /**********************
2454 * play *
2455 **********************/
2456 bb->startedshot = *rb->current_tick;
2458 while(true) {
2459 /* refresh the board */
2460 bubbles_drawboard(bb);
2461 rb->lcd_update();
2463 /* manange idle framerate */
2464 bb->elapsedshot = *rb->current_tick-bb->startedshot;
2466 if(MAX_SHOTTIME-bb->elapsedshot < HZ/2) {
2467 timeout = MAX_SHOTTIME-bb->elapsedshot;
2468 } else {
2469 timeout = HZ/2;
2472 /* handle button events */
2473 buttonres = bubbles_handlebuttons(bb, false, timeout);
2474 if(buttonres != BB_NONE) return buttonres;
2476 /* handle timing */
2477 bb->elapsedshot = *rb->current_tick-bb->startedshot;
2479 if(bb->elapsedshot > MAX_SHOTTIME) {
2480 bb->elapsedlvl += bb->elapsedshot;
2481 bb->elapsedshot = 0;
2482 buttonres = bubbles_fire(bb);
2483 if(buttonres != BB_NONE) return buttonres;
2484 buttonres = bubbles_checklevel(bb);
2485 if(buttonres != BB_NONE) return buttonres;
2486 bb->startedshot = *rb->current_tick;
2491 /*****************************************************************************
2492 * plugin entry point.
2493 ******************************************************************************/
2494 enum plugin_status plugin_start(const void* parameter) {
2495 static struct game_context bb;
2496 bool exit = false;
2497 enum plugin_status ret = PLUGIN_OK;
2499 (void)parameter;
2501 /* load files */
2502 resume = bubbles_loadgame(&bb);
2503 resume_file = resume;
2504 bubbles_loaddata();
2505 highscore_load(SCORE_FILE, highscores, NUM_SCORES);
2506 rb->lcd_clear_display();
2508 /* start app */
2509 #if LCD_DEPTH > 1
2510 rb->lcd_set_backdrop(NULL);
2511 #endif
2512 rb->lcd_setfont(FONT_SYSFIXED);
2514 while(!exit) {
2515 switch(bubbles(&bb)){
2516 case BB_WIN:
2517 rb->splash(HZ*2, "You Win!");
2518 /* record high level */
2519 highlevel = NUM_LEVELS-1;
2520 /* record high score */
2521 bubbles_recordscore(&bb);
2522 break;
2524 case BB_LOSE:
2525 resume = false;
2526 rb->splash(HZ*2, "Game Over");
2527 /* record high score */
2528 bubbles_recordscore(&bb);
2529 /* fall through to BB_END */
2531 case BB_END:
2532 break;
2534 case BB_USB:
2535 ret = PLUGIN_USB_CONNECTED;
2536 exit = true;
2537 break;
2539 case BB_QUIT:
2540 #define SAVE_MESSAGE "Saving Game and Scores..."
2541 /* the first splash is to make sure it's read, but don't make it
2542 * too long to not delay the saving further */
2543 rb->splash(HZ/5, SAVE_MESSAGE);
2544 rb->splash(0, SAVE_MESSAGE);
2545 bubbles_savegame(&bb);
2546 bubbles_savedata();
2547 highscore_save(SCORE_FILE, highscores, NUM_SCORES);
2548 /* fall through */
2550 case BB_QUIT_WITHOUT_SAVING:
2551 exit = true;
2552 break;
2554 default:
2555 break;
2559 rb->lcd_setfont(FONT_UI);
2560 return ret;
2563 #endif