Reverting parts of r19760 that was mistakenly committed.
[kugel-rb.git] / apps / plugins / bubbles.c
blob0894c75d4a65049604531cb1109c8b73a09051dc
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"
32 PLUGIN_HEADER
34 /* files */
35 #define SCORE_FILE PLUGIN_GAMES_DIR "/bubbles.score"
36 #define SAVE_FILE PLUGIN_GAMES_DIR "/bubbles.save"
38 /* final game return status */
39 #define BB_NONE 5
40 #define BB_WIN 4
41 #define BB_END 3
42 #define BB_USB 2
43 #define BB_QUIT 1
44 #define BB_LOSE 0
46 /* play board dimension */
47 #define BB_HEIGHT 12
48 #define BB_WIDTH 8
49 #define BB_LEVEL_HEIGHT 10
51 /* various amounts */
52 #define NUM_SCORES 10
53 #define NUM_LEVELS 100
54 #define NUM_QUEUE 2
55 #define NUM_BUBBLES 8
56 #define MIN_ANGLE -76
57 #define MAX_ANGLE 76
58 #define NUM_COMPRESS 9
59 #define MAX_SHOTTIME 1000
61 /* keyboard layouts */
62 /* FIXME: shouldn't the below be #ifdef HAVE_SCROLLWHEEL rather? */
64 #if (CONFIG_KEYPAD != SANSA_E200_PAD) && \
65 (CONFIG_KEYPAD != SANSA_FUZE_PAD)
66 /* sansas use the wheel instead of left/right if available */
67 #define BUBBLES_LEFT PLA_LEFT
68 #define BUBBLES_LEFT_REP PLA_LEFT_REPEAT
69 #define BUBBLES_RIGHT PLA_RIGHT
70 #define BUBBLES_RIGHT_REP PLA_RIGHT_REPEAT
71 #define ANGLE_STEP 4
72 #define ANGLE_STEP_REP 4
73 #else
74 #define BUBBLES_LEFT PLA_UP
75 #define BUBBLES_LEFT_REP PLA_UP_REPEAT
76 #define BUBBLES_RIGHT PLA_DOWN
77 #define BUBBLES_RIGHT_REP PLA_DOWN_REPEAT
78 #define ANGLE_STEP 2
79 #define ANGLE_STEP_REP 4
80 #endif
82 #define BUBBLES_QUIT PLA_QUIT
83 #define BUBBLES_START PLA_START
84 #define BUBBLES_SELECT PLA_FIRE
85 #define BUBBLES_RESUME PLA_MENU
87 #if CONFIG_KEYPAD != ONDIO_PAD
89 #define BUBBLES_LVLINC PLA_UP
90 #define BUBBLES_LVLINC_REP PLA_UP_REPEAT
91 #define BUBBLES_LVLDEC PLA_DOWN
92 #define BUBBLES_LVLDEC_REP PLA_DOWN_REPEAT
94 #else /* ondio keys */
96 #define BUBBLES_LVLINC PLA_RIGHT
97 #define BUBBLES_LVLINC_REP PLA_RIGHT_REPEAT
98 #define BUBBLES_LVLDEC PLA_LEFT
99 #define BUBBLES_LVLDEC_REP PLA_LEFT_REPEAT
101 #endif
103 /* external bitmaps */
104 #ifdef HAVE_LCD_COLOR
105 #include "pluginbitmaps/bubbles_background.h"
106 #endif
107 #include "pluginbitmaps/bubbles_bubble.h"
108 #include "pluginbitmaps/bubbles_emblem.h"
110 #define BUBBLE_WIDTH BMPWIDTH_bubbles_bubble
111 #define BUBBLE_HEIGHT BMPHEIGHT_bubbles_bubble
112 #define EMBLEM_WIDTH BMPWIDTH_bubbles_emblem
113 #define EMBLEM_HEIGHT (BMPHEIGHT_bubbles_emblem/8)
115 /* bubbles will consume height of ROW_HEIGHT*(BB_HEIGHT-1)+BUBBLE_HEIGHT*3/2 */
116 /* 22x22 bubbles (iPod Video) */
117 #if (LCD_HEIGHT == 240) && (LCD_WIDTH == 320)
118 #define XOFS 72
119 #define ROW_HEIGHT 18
120 #define ROW_INDENT 11
121 #define MAX_FPS 40
123 /* 22x22 bubbles (Gigabeat) */
124 #elif (LCD_HEIGHT == 320) && (LCD_WIDTH == 240)
125 #define XOFS 64
126 #define ROW_HEIGHT 18
127 #define ROW_INDENT 11
128 #define MAX_FPS 30
130 /* 16x16 bubbles (H300, iPod Color) */
131 #elif (LCD_HEIGHT == 176) && (LCD_WIDTH == 220)
132 #define XOFS 46
133 #define ROW_HEIGHT 14
134 #define ROW_INDENT 8
135 #define MAX_FPS 30
137 /* 16x16 bubbles (Sansa E200) */
138 #elif (LCD_HEIGHT == 220) && (LCD_WIDTH == 176)
139 #define XOFS 48
140 #define ROW_HEIGHT 14
141 #define ROW_INDENT 8
142 #define MAX_FPS 30
144 /* 12x12 bubbles (iPod Nano) */
145 #elif (LCD_HEIGHT == 132) && (LCD_WIDTH == 176)
146 #define XOFS 40
147 #define ROW_HEIGHT 10
148 #define ROW_INDENT 6
149 #define MAX_FPS 40
151 /* 12x12 bubbles (H100, H10, iAudio X5, iPod 3G, iPod 4G grayscale) */
152 #elif (LCD_HEIGHT == 128) && ((LCD_WIDTH == 160) || (LCD_WIDTH == 128))
153 #define XOFS 33
154 #define ROW_HEIGHT 10
155 #define ROW_INDENT 6
156 #define MAX_FPS 30
158 /* 10x10 bubbles (iPod Mini) */
159 #elif (LCD_HEIGHT == 110) && (LCD_WIDTH == 138)
160 #define XOFS 33
161 #define ROW_HEIGHT 8
162 #define ROW_INDENT 5
163 #define MAX_FPS 30
165 /* 9x9 bubbles (iAudio M3) */
166 #elif (LCD_HEIGHT == 96) && (LCD_WIDTH == 128)
167 #define XOFS 45
168 #define ROW_HEIGHT 7
169 #define ROW_INDENT 4
170 #define MAX_FPS 30
172 /* 8x8 bubbles (Sansa C200) */
173 #elif ((LCD_HEIGHT == 80) && (LCD_WIDTH == 132))
174 #define XOFS 45
175 #define ROW_HEIGHT 6
176 #define ROW_INDENT 4
177 #define MAX_FPS 30
179 /* 7x7 bubbles (Sansa Clip/m200) */
180 #elif (LCD_HEIGHT == 64 && LCD_WIDTH == 128)
181 #define XOFS 33
182 #define ROW_HEIGHT 5
183 #define ROW_INDENT 4
184 #define MAX_FPS 30
186 /* 8x7 bubbles (Archos recorder, Ondio) */
187 #elif (LCD_HEIGHT == 64) && (LCD_WIDTH == 112)
188 #define XOFS 33
189 #define ROW_HEIGHT 5
190 #define ROW_INDENT 4
191 #define MAX_FPS 20
193 #else
194 #error BUBBLES: Unsupported LCD type
195 #endif
197 #define TEXT_LINES (LCD_HEIGHT/8)
199 /* shot position */
200 #define SHOTX XOFS+ROW_INDENT+BUBBLE_WIDTH*3
201 #define SHOTY ROW_HEIGHT*(BB_HEIGHT-1)+BUBBLE_HEIGHT/2
203 /* collision distance squared */
204 #define MIN_DISTANCE ((BUBBLE_WIDTH*8)/10)*((BUBBLE_HEIGHT*8)/10)
206 /* global rockbox api */
207 static const struct plugin_api* rb;
209 /* levels */
210 char level[NUM_LEVELS][BB_LEVEL_HEIGHT][BB_WIDTH] = {
211 {{ 6, 6, 4, 4, 2, 2, 3, 3},
212 { 6, 6, 4, 4, 2, 2, 3, -1},
213 { 2, 2, 3, 3, 6, 6, 4, 4},
214 { 2, 3, 3, 6, 6, 4, 4, -1},
215 {-1, -1, -1, -1, -1, -1, -1, -1},
216 {-1, -1, -1, -1, -1, -1, -1, -1},
217 {-1, -1, -1, -1, -1, -1, -1, -1},
218 {-1, -1, -1, -1, -1, -1, -1, -1},
219 {-1, -1, -1, -1, -1, -1, -1, -1},
220 {-1, -1, -1, -1, -1, -1, -1, -1}},
221 {{-1, 7, 7, 7, 7, 7, 7, -1},
222 {-1, 1, 1, 1, 1, 1, -1, -1},
223 {-1, -1, 2, 2, 2, 2, -1, -1},
224 {-1, -1, -1, 2, -1, -1, -1, -1},
225 {-1, -1, -1, 2, 2, -1, -1, -1},
226 {-1, -1, -1, 5, -1, -1, -1, -1},
227 {-1, -1, -1, 5, 5, -1, -1, -1},
228 {-1, -1, -1, -1, -1, -1, -1, -1},
229 {-1, -1, -1, -1, -1, -1, -1, -1},
230 {-1, -1, -1, -1, -1, -1, -1, -1}},
231 {{-1, -1, 7, -1, -1, 7, -1, -1},
232 {-1, -1, 7, 1, 7, -1, -1, -1},
233 {-1, -1, -1, 1, 2, -1, -1, -1},
234 {-1, -1, 1, 2, 1, -1, -1, -1},
235 {-1, -1, -1, 2, 5, -1, -1, -1},
236 {-1, -1, 3, 5, 3, -1, -1, -1},
237 {-1, -1, -1, 5, 3, -1, -1, -1},
238 {-1, -1, -1, 3, -1, -1, -1, -1},
239 {-1, -1, -1, -1, -1, -1, -1, -1},
240 {-1, -1, -1, -1, -1, -1, -1, -1}},
241 {{-1, -1, -1, 0, 0, -1, -1, -1},
242 {-1, -1, 5, 0, 1, -1, -1, -1},
243 {-1, -1, 3, 5, 1, 6, -1, -1},
244 {-1, 4, 3, -1, 6, 7, -1, -1},
245 {-1, 7, 4, -1, -1, 7, 4, -1},
246 { 6, 7, -1, -1, -1, 4, 3, -1},
247 { 1, 6, -1, -1, -1, -1, 3, 5},
248 { 1, -1, -1, -1, -1, -1, 5, -1},
249 {-1, -1, -1, -1, -1, -1, -1, -1},
250 {-1, -1, -1, -1, -1, -1, -1, -1}},
251 {{-1, -1, 0, 0, 0, 0, -1, -1},
252 {-1, 0, 1, 1, 1, 0, -1, -1},
253 {-1, 0, 1, 0, 0, 1, 0, -1},
254 {-1, 0, 1, 1, 1, 0, -1, -1},
255 {-1, -1, 0, 0, 0, 0, -1, -1},
256 {-1, -1, 7, -1, 7, -1, -1, -1},
257 {-1, -1, 7, 7, 7, 7, -1, -1},
258 {-1, -1, -1, -1, -1, -1, -1, -1},
259 {-1, -1, -1, -1, -1, -1, -1, -1},
260 {-1, -1, -1, -1, -1, -1, -1, -1}},
261 {{-1, 4, 4, 4, 6, 6, 6, -1},
262 { 4, -1, -1, -1, -1, -1, 6, -1},
263 {-1, 4, -1, -1, -1, -1, 6, -1},
264 { 4, 2, 3, 1, 2, 3, 6, -1},
265 {-1, 3, 1, 2, 3, 1, 2, -1},
266 {-1, -1, -1, -1, -1, -1, -1, -1},
267 {-1, -1, -1, -1, -1, -1, -1, -1},
268 {-1, -1, -1, -1, -1, -1, -1, -1},
269 {-1, -1, -1, -1, -1, -1, -1, -1},
270 {-1, -1, -1, -1, -1, -1, -1, -1}},
271 {{-1, 4, 4, 4, 6, 6, 6, -1},
272 { 4, -1, -1, -1, -1, -1, 6, -1},
273 {-1, 4, -1, -1, -1, -1, 6, -1},
274 { 4, 2, 3, 1, 2, 3, 6, -1},
275 {-1, 3, 1, 2, 3, 1, 2, -1},
276 {-1, 2, 3, 1, 2, 3, -1, -1},
277 {-1, -1, -1, -1, -1, -1, -1, -1},
278 {-1, -1, -1, -1, -1, -1, -1, -1},
279 {-1, -1, -1, -1, -1, -1, -1, -1},
280 {-1, -1, -1, -1, -1, -1, -1, -1}},
281 {{-1, 0, 0, -1, -1, 2, 2, -1},
282 {-1, 5, -1, -1, -1, 3, -1, -1},
283 {-1, 0, -1, -1, -1, 6, -1, -1},
284 {-1, 3, -1, -1, -1, 0, -1, -1},
285 {-1, 4, -1, -1, -1, 5, -1, -1},
286 {-1, 2, -1, -1, -1, 3, -1, -1},
287 {-1, 2, -1, -1, -1, 1, -1, -1},
288 {-1, 3, -1, -1, -1, 4, -1, -1},
289 {-1, -1, -1, -1, -1, -1, -1, -1},
290 {-1, -1, -1, -1, -1, -1, -1, -1}},
291 {{ 3, -1, -1, -1, -1, -1, -1, 3},
292 { 6, 3, 2, 4, 6, 3, 2, -1},
293 { 4, -1, -1, -1, -1, -1, -1, 4},
294 { 2, 4, 6, 3, 2, 4, 6, -1},
295 {-1, -1, -1, 6, -1, -1, -1, -1},
296 {-1, -1, -1, 3, -1, -1, -1, -1},
297 {-1, -1, -1, -1, -1, -1, -1, -1},
298 {-1, -1, -1, -1, -1, -1, -1, -1},
299 {-1, -1, -1, -1, -1, -1, -1, -1},
300 {-1, -1, -1, -1, -1, -1, -1, -1}},
301 {{-1, 2, -1, 1, -1, 1, -1, 2},
302 { 1, 2, -1, 2, 1, -1, 1, -1},
303 { 1, -1, 1, -1, 2, -1, 2, -1},
304 { 2, 1, -1, 1, 2, -1, 2, -1},
305 {-1, 2, -1, 2, -1, 2, -1, 2},
306 { 1, 2, -1, 2, 1, -1, 1, -1},
307 { 1, -1, 1, -1, 2, -1, 1, -1},
308 { 2, 2, -1, 1, 1, -1, 2, -1},
309 {-1, 2, -1, 1, -1, 1, -1, 1},
310 {-1, -1, -1, -1, -1, -1, -1, -1}},
311 {{-1, 7, 7, -1, -1, 5, 5, -1},
312 { 1, -1, -1, -1, -1, -1, 4, -1},
313 { 2, 1, -1, -1, -1, -1, 4, 3},
314 { 2, -1, -1, -1, -1, -1, 3, -1},
315 { 1, 2, -1, -1, -1, -1, 3, 4},
316 { 1, -1, -1, -1, -1, -1, 4, -1},
317 { 7, 1, -1, -1, -1, -1, 4, 5},
318 { 7, 7, -1, -1, -1, 5, 5, -1},
319 {-1, -1, -1, -1, -1, -1, -1, -1},
320 {-1, -1, -1, -1, -1, -1, -1, -1}},
321 {{ 7, 7, -1, -1, -1, -1, 5, 5},
322 { 1, 5, -1, -1, -1, 7, 4, -1},
323 { 2, 1, -1, -1, -1, -1, 4, 3},
324 { 2, -1, -1, -1, -1, -1, 3, -1},
325 { 1, 5, -1, -1, -1, -1, 7, 4},
326 { 1, -1, -1, -1, -1, -1, 4, -1},
327 { 7, 1, -1, -1, -1, -1, 4, 5},
328 { 7, 5, -1, -1, -1, 7, 5, -1},
329 {-1, -1, -1, -1, -1, -1, -1, -1},
330 {-1, -1, -1, -1, -1, -1, -1, -1}},
331 {{-1, -1, -1, 0, 0, -1, -1, -1},
332 {-1, -1, 5, 0, 1, -1, -1, -1},
333 {-1, -1, 3, 5, 1, 6, -1, -1},
334 {-1, 4, 3, 2, 6, 2, -1, -1},
335 {-1, 7, 4, 7, 2, 2, 4, -1},
336 { 6, 7, 7, 3, 3, 4, 3, -1},
337 { 1, 6, 1, 1, 1, 3, 3, 5},
338 { 1, 1, -1, -1, -1, -1, 5, -1},
339 {-1, -1, -1, -1, -1, -1, -1, -1},
340 {-1, -1, -1, -1, -1, -1, -1, -1}},
341 {{-1, -1, 0, -1, -1, 0, -1, -1},
342 {-1, 3, 3, -1, 3, 3, -1, -1},
343 {-1, 0, 2, 0, 0, 2, 0, -1},
344 {-1, 3, 3, -1, 3, 3, -1, -1},
345 {-1, -1, 0, -1, -1, 0, -1, -1},
346 {-1, -1, -1, -1, -1, -1, -1, -1},
347 {-1, -1, -1, -1, -1, -1, -1, -1},
348 {-1, -1, -1, -1, -1, -1, -1, -1},
349 {-1, -1, -1, -1, -1, -1, -1, -1},
350 {-1, -1, -1, -1, -1, -1, -1, -1}},
351 {{-1, -1, -1, 1, 1, -1, -1, -1},
352 {-1, -1, 2, 2, 2, -1, -1, -1},
353 {-1, -1, 3, 3, 3, 3, -1, -1},
354 {-1, 4, 4, 4, 4, 4, -1, -1},
355 {-1, 5, 5, 5, 5, 5, 5, -1},
356 {-1, -1, -1, 6, -1, -1, -1, -1},
357 {-1, -1, -1, 7, 7, -1, -1, -1},
358 {-1, -1, -1, 0, -1, -1, -1, -1},
359 {-1, -1, -1, -1, -1, -1, -1, -1},
360 {-1, -1, -1, -1, -1, -1, -1, -1}},
361 {{-1, -1, -1, 2, 5, -1, -1, -1},
362 {-1, 4, 3, -1, -1, -1, -1, -1},
363 { 6, 7, -1, 5, 2, -1, -1, -1},
364 {-1, -1, -1, -1, 3, 4, -1, -1},
365 {-1, -1, -1, 2, 5, -1, 7, 6},
366 {-1, 4, 3, -1, -1, -1, -1, -1},
367 { 6, 7, -1, 5, 2, -1, -1, -1},
368 {-1, -1, -1, -1, 3, 4, -1, -1},
369 {-1, -1, -1, -1, -1, -1, 7, 6},
370 {-1, -1, -1, -1, -1, -1, -1, -1}},
371 {{-1, -1, -1, 5, 5, -1, -1, -1},
372 {-1, -1, -1, 3, -1, -1, -1, -1},
373 {-1, -1, -1, 1, -1, -1, -1, -1},
374 {-1, -1, -1, 7, -1, -1, -1, -1},
375 {-1, -1, -1, 2, -1, -1, -1, -1},
376 {-1, -1, -1, 4, -1, -1, -1, -1},
377 {-1, -1, -1, 5, -1, -1, -1, -1},
378 {-1, -1, -1, 3, -1, -1, -1, -1},
379 {-1, -1, -1, -1, -1, -1, -1, -1},
380 {-1, -1, -1, -1, -1, -1, -1, -1}},
381 {{-1, -1, -1, 0, 1, -1, -1, -1},
382 {-1, -1, 0, 2, 7, 7, -1, -1},
383 {-1, -1, -1, 0, 1, 7, -1, -1},
384 {-1, 0, 0, 0, 0, -1, -1, -1},
385 {-1, 0, 0, 0, 1, 1, -1, -1},
386 { 0, 0, 0, 1, 1, 1, -1, -1},
387 {-1, 0, 0, 1, 1, 1, -1, -1},
388 {-1, 0, 0, 0, 7, 7, -1, -1},
389 {-1, -1, 7, 7, -1, -1, -1, -1},
390 {-1, -1, -1, -1, -1, -1, -1, -1}},
391 {{-1, 1, -1, -1, -1, -1, -1, -1},
392 { 1, -1, -1, -1, -1, -1, -1, -1},
393 {-1, 2, 3, 4, 7, 6, 5, -1},
394 {-1, -1, -1, -1, -1, -1, 1, -1},
395 {-1, -1, -1, -1, -1, -1, 1, -1},
396 {-1, 2, 3, 4, 7, 6, -1, -1},
397 {-1, 1, -1, -1, -1, -1, -1, -1},
398 { 1, -1, -1, -1, -1, -1, -1, -1},
399 {-1, 2, 3, 4, 7, 6, 5, -1},
400 {-1, -1, -1, -1, -1, -1, -1, -1}},
401 {{-1, 6, -1, -1, -1, -1, -1, -1},
402 { 5, -1, -1, -1, -1, -1, -1, -1},
403 { 2, 3, 4, 7, 6, 5, 2, 3},
404 {-1, -1, -1, -1, -1, -1, 4, -1},
405 {-1, -1, -1, -1, -1, -1, 7, -1},
406 {-1, 4, 3, 2, 5, 6, -1, -1},
407 {-1, 7, -1, -1, -1, -1, -1, -1},
408 { 6, -1, -1, -1, -1, -1, -1, -1},
409 { 5, 2, 3, 4, 7, 6, 5, -1},
410 {-1, -1, -1, -1, -1, -1, -1, -1}},
411 {{ 3, 2, 1, 0, 0, 1, 2, 3},
412 { 3, 2, 1, 0, 1, 2, 3, -1},
413 { 4, 3, 2, 1, 1, 2, 3, 4},
414 { 4, 3, 2, 1, 2, 3, 4, -1},
415 { 5, 4, 3, 2, 2, 3, 4, 5},
416 { 5, 4, 3, 2, 3, 4, 5, -1},
417 { 6, 5, 4, 3, 3, 4, 5, 6},
418 { 6, 5, 4, 3, 4, 5, 6, -1},
419 { 7, 6, 5, 4, 4, 5, 6, 7},
420 {-1, -1, -1, -1, -1, -1, -1, -1}},
421 {{-1, -1, -1, 5, 5, -1, -1, -1},
422 {-1, -1, -1, 3, -1, -1, -1, -1},
423 {-1, -1, -1, 2, 4, -1, -1, -1},
424 {-1, -1, -1, 6, -1, -1, -1, -1},
425 {-1, -1, -1, 2, 4, -1, -1, -1},
426 {-1, 2, -1, 5, -1, 4, -1, -1},
427 { 1, 0, 1, 0, 1, 0, 1, 0},
428 { 3, -1, 3, -1, 2, -1, 6, -1},
429 {-1, -1, -1, -1, -1, -1, -1, -1},
430 {-1, -1, -1, -1, -1, -1, -1, -1}},
431 {{-1, -1, -1, -1, 1, -1, -1, -1},
432 { 7, 4, 3, 5, -1, -1, -1, -1},
433 { 6, -1, -1, 1, -1, -1, -1, -1},
434 {-1, -1, -1, 5, 3, 4, 7, -1},
435 { 6, -1, -1, -1, 1, -1, -1, 6},
436 { 7, 4, 3, 5, -1, -1, -1, -1},
437 {-1, -1, -1, 1, -1, -1, -1, 6},
438 {-1, -1, -1, 5, 3, 4, 7, -1},
439 {-1, -1, -1, -1, -1, -1, -1, -1},
440 {-1, -1, -1, -1, -1, -1, -1, -1}},
441 {{-1, -1, -1, -1, 7, 3, 6, -1},
442 {-1, -1, 3, 7, 3, 6, 3, -1},
443 {-1, -1, 5, 7, 3, 6, 3, -1},
444 {-1, 6, 7, 3, 6, 7, -1, -1},
445 {-1, 7, 7, 3, 6, 1, -1, -1},
446 { 3, 7, 3, 6, 3, -1, -1, -1},
447 { 5, 6, 2, 7, 1, -1, -1, -1},
448 {-1, -1, -1, -1, -1, -1, -1, -1},
449 {-1, -1, -1, -1, -1, -1, -1, -1},
450 {-1, -1, -1, -1, -1, -1, -1, -1}},
451 {{ 5, -1, -1, -1, -1, -1, -1, 5},
452 { 5, -1, 6, 6, 6, -1, 5, -1},
453 {-1, 5, 4, -1, -1, 4, 5, -1},
454 {-1, 3, -1, -1, -1, 3, -1, -1},
455 {-1, 6, 0, -1, -1, 0, 6, -1},
456 {-1, 3, -1, -1, -1, 3, -1, -1},
457 {-1, -1, 4, -1, -1, 4, -1, -1},
458 {-1, -1, 6, 6, 6, -1, -1, -1},
459 {-1, -1, -1, -1, -1, -1, -1, -1},
460 {-1, -1, -1, -1, -1, -1, -1, -1}},
461 {{-1, 7, 0, -1, -1, 0, 7, -1},
462 { 7, -1, 0, -1, 0, -1, 7, -1},
463 { 7, 1, -1, 0, 0, -1, 1, 7},
464 { 7, 1, 2, 0, 2, 1, 7, -1},
465 { 7, 6, 3, 2, 2, 3, 6, 7},
466 { 7, -1, 3, 2, 3, -1, 7, -1},
467 {-1, 7, 7, 3, 3, 7, 7, -1},
468 {-1, -1, -1, 3, -1, -1, -1, -1},
469 {-1, -1, -1, -1, -1, -1, -1, -1},
470 {-1, -1, -1, -1, -1, -1, -1, -1}},
471 {{-1, 3, -1, 1, -1, 7, -1, 6},
472 { 5, -1, 7, -1, 7, -1, 6, -1},
473 { 6, -1, 0, -1, 5, -1, 3, -1},
474 {-1, 2, -1, 1, -1, 5, -1, -1},
475 {-1, 4, -1, 3, -1, 4, -1, -1},
476 { 2, -1, 3, -1, 2, -1, -1, -1},
477 {-1, -1, 4, -1, 6, -1, -1, -1},
478 {-1, -1, -1, 5, -1, -1, -1, -1},
479 {-1, -1, -1, -1, -1, -1, -1, -1},
480 {-1, -1, -1, -1, -1, -1, -1, -1}},
481 {{-1, -1, -1, -1, 1, -1, -1, -1},
482 {-1, -1, -1, -1, 3, -1, -1, -1},
483 { 6, 1, 3, 1, 2, 1, 4, 1},
484 {-1, -1, -1, -1, 6, -1, -1, -1},
485 {-1, -1, -1, 4, 1, -1, -1, -1},
486 {-1, -1, 1, -1, 3, -1, -1, -1},
487 {-1, -1, -1, 2, 1, -1, -1, -1},
488 {-1, -1, -1, -1, 4, -1, -1, -1},
489 {-1, -1, -1, 6, 1, -1, -1, -1},
490 {-1, -1, -1, 6, -1, -1, -1, -1}},
491 {{-1, -1, -1, 5, 4, -1, -1, -1},
492 {-1, -1, 4, 1, 0, -1, -1, -1},
493 {-1, -1, -1, 2, 3, -1, -1, -1},
494 {-1, 1, 4, -1, 2, 2, -1, -1},
495 {-1, 3, 1, 2, 5, 1, 4, -1},
496 {-1, 4, 2, -1, 0, 4, -1, -1},
497 {-1, -1, -1, -1, -1, -1, -1, -1},
498 {-1, -1, -1, -1, -1, -1, -1, -1},
499 {-1, -1, -1, -1, -1, -1, -1, -1},
500 {-1, -1, -1, -1, -1, -1, -1, -1}},
501 {{-1, -1, -1, -1, 1, -1, -1, -1},
502 {-1, -1, -1, 1, -1, -1, -1, -1},
503 {-1, 2, -1, -1, 1, -1, 5, -1},
504 { 5, -1, -1, 1, -1, -1, 0, -1},
505 {-1, 6, -1, -1, 1, -1, 4, -1},
506 {-1, 0, -1, 1, -1, 5, -1, -1},
507 {-1, -1, 5, 5, 0, 1, -1, -1},
508 {-1, -1, -1, -1, -1, -1, -1, -1},
509 {-1, -1, -1, -1, -1, -1, -1, -1},
510 {-1, -1, -1, -1, -1, -1, -1, -1}},
511 {{-1, -1, -1, 6, 3, -1, -1, -1},
512 {-1, -1, 3, 2, 6, -1, -1, -1},
513 {-1, -1, 2, 6, 3, 2, -1, -1},
514 {-1, 6, 3, 2, 6, 3, -1, -1},
515 {-1, 3, 2, 6, 3, 2, 6, -1},
516 { 2, 6, 3, 2, 6, 3, 2, -1},
517 { 6, 3, 2, 6, 3, 2, 6, 3},
518 {-1, -1, -1, -1, -1, -1, -1, -1},
519 {-1, -1, -1, -1, -1, -1, -1, -1},
520 {-1, -1, -1, -1, -1, -1, -1, -1}},
521 {{ 6, 6, 6, 6, 6, 6, 6, 6},
522 { 4, -1, -1, -1, -1, -1, -1, -1},
523 {-1, 3, 2, 5, 7, 6, 4, 3},
524 {-1, 5, -1, -1, -1, -1, -1, -1},
525 {-1, -1, 7, 6, 4, 3, 2, 5},
526 {-1, -1, 4, -1, -1, -1, -1, -1},
527 {-1, -1, -1, 3, 2, 5, 7, 6},
528 {-1, -1, -1, -1, -1, -1, -1, -1},
529 {-1, -1, -1, -1, -1, -1, -1, -1},
530 {-1, -1, -1, -1, -1, -1, -1, -1}},
531 {{ 1, -1, 7, -1, -1, 6, -1, 2},
532 { 6, -1, 1, -1, 6, 1, 3, -1},
533 {-1, 4, -1, 7, 2, -1, 7, -1},
534 { 2, 7, -1, -1, -1, 4, -1, -1},
535 { 6, -1, 3, 5, 0, 2, -1, 7},
536 { 1, -1, -1, -1, -1, -1, 1, -1},
537 {-1, 1, 4, 5, 7, 5, 1, -1},
538 {-1, -1, -1, -1, -1, -1, -1, -1},
539 {-1, -1, -1, -1, -1, -1, -1, -1},
540 {-1, -1, -1, -1, -1, -1, -1, -1}},
541 {{ 6, 6, 6, -1, -1, 6, 6, 6},
542 {-1, -1, 6, -1, 6, -1, -1, -1},
543 {-1, -1, 2, 3, 3, 2, -1, -1},
544 {-1, 3, -1, 5, -1, 3, -1, -1},
545 {-1, -1, 5, 3, 3, 5, -1, -1},
546 {-1, -1, 6, 1, 6, -1, -1, -1},
547 {-1, 4, 2, -1, -1, 2, 4, -1},
548 {-1, -1, -1, -1, -1, -1, -1, -1},
549 {-1, -1, -1, -1, -1, -1, -1, -1},
550 {-1, -1, -1, -1, -1, -1, -1, -1}},
551 {{-1, -1, -1, 5, 5, -1, -1, -1},
552 {-1, -1, 5, -1, -1, -1, -1, -1},
553 {-1, 3, 4, 6, 6, -1, -1, 5},
554 { 3, 3, 4, 6, 5, -1, 5, -1},
555 { 3, 2, 3, 6, 6, 5, 5, -1},
556 { 3, 3, 4, 6, 5, -1, 5, -1},
557 {-1, 3, 4, 6, 6, -1, -1, 5},
558 {-1, -1, 5, -1, -1, -1, -1, -1},
559 {-1, -1, -1, 5, 5, -1, -1, -1},
560 {-1, -1, -1, -1, -1, -1, -1, -1}},
561 {{ 1, -1, -1, -1, -1, -1, -1, 1},
562 { 1, -1, 2, 2, 2, -1, 1, -1},
563 {-1, 1, 2, 3, 3, 2, 1, -1},
564 { 6, 2, 3, -1, 3, 2, 6, -1},
565 { 6, 2, 3, -1, -1, 3, 2, 6},
566 { 6, 2, 3, -1, 3, 2, 6, -1},
567 { 3, 3, 3, 7, 7, 3, 3, 3},
568 { 0, 5, 0, 2, 0, 5, 0, -1},
569 {-1, -1, -1, -1, -1, -1, -1, -1},
570 {-1, -1, -1, -1, -1, -1, -1, -1}},
571 {{-1, -1, 7, 7, 7, -1, -1, -1},
572 {-1, 7, 2, 2, 7, -1, -1, -1},
573 {-1, 7, 5, 5, 5, 7, -1, -1},
574 { 7, 7, 7, 7, 7, 7, -1, -1},
575 {-1, -1, 6, -1, 6, -1, -1, -1},
576 {-1, 6, -1, -1, 6, -1, -1, -1},
577 {-1, 6, 4, 4, -1, 6, 4, 4},
578 {-1, -1, -1, -1, -1, -1, -1, -1},
579 {-1, -1, -1, -1, -1, -1, -1, -1},
580 {-1, -1, -1, -1, -1, -1, -1, -1}},
581 {{-1, 3, 3, -1, 3, 3, 3, -1},
582 { 3, 7, 5, 4, 6, 5, 3, -1},
583 { 1, 3, 3, 3, -1, 3, 3, 1},
584 { 2, 1, 2, 1, 2, 1, 2, -1},
585 { 1, 3, 3, -1, 3, 3, 3, 1},
586 { 3, 5, 6, 4, 5, 7, 3, -1},
587 { 2, 3, 3, 3, -1, 3, 3, 2},
588 { 1, 1, 2, 2, 2, 1, 1, -1},
589 {-1, -1, -1, -1, -1, -1, -1, -1},
590 {-1, -1, -1, -1, -1, -1, -1, -1}},
591 {{-1, 6, 5, -1, -1, -1, -1, -1},
592 { 3, 1, 3, -1, -1, -1, -1, -1},
593 {-1, 5, 6, -1, -1, -1, -1, -1},
594 {-1, -1, 5, 3, -1, -1, -1, -1},
595 {-1, -1, 6, 1, 6, -1, -1, -1},
596 {-1, -1, 3, 5, -1, -1, -1, -1},
597 {-1, -1, -1, -1, 3, 6, -1, -1},
598 {-1, -1, -1, 5, 6, 5, -1, -1},
599 {-1, -1, -1, -1, 6, 3, -1, -1},
600 {-1, -1, -1, -1, -1, -1, -1, -1}},
601 {{ 6, 3, 7, 4, 5, 1, 6, 3},
602 { 5, 1, 6, 3, 7, 4, 5, -1},
603 { 6, 3, 7, 4, 5, 1, 6, 3},
604 {-1, -1, -1, -1, -1, -1, -1, -1},
605 {-1, -1, -1, -1, -1, -1, -1, -1},
606 {-1, -1, -1, -1, -1, -1, -1, -1},
607 {-1, -1, -1, -1, -1, -1, -1, -1},
608 {-1, -1, -1, -1, -1, -1, -1, -1},
609 {-1, -1, -1, -1, -1, -1, -1, -1},
610 {-1, -1, -1, -1, -1, -1, -1, -1}},
611 {{-1, -1, -1, -1, -1, -1, 4, 4},
612 {-1, -1, 7, 7, 7, 4, 4, -1},
613 {-1, -1, -1, -1, -1, -1, 4, 4},
614 {-1, 1, -1, -1, -1, 7, -1, -1},
615 {-1, 1, 1, -1, -1, 7, -1, -1},
616 { 3, 3, 3, -1, 7, -1, -1, -1},
617 { 3, -1, 2, 3, 3, 3, -1, 3},
618 {-1, 2, -1, 3, -1, 3, 3, -1},
619 {-1, 2, -1, -1, -1, -1, -1, -1},
620 {-1, -1, -1, -1, -1, -1, -1, -1}},
621 {{-1, -1, 4, -1, -1, -1, -1, -1},
622 {-1, 7, 4, -1, -1, -1, -1, -1},
623 {-1, -1, 7, 4, -1, -1, -1, -1},
624 {-1, 4, 7, 4, -1, -1, -1, -1},
625 { 1, 1, 1, 1, 1, 1, 1, -1},
626 { 1, 2, 1, 2, 1, 1, -1, -1},
627 { 2, 2, 2, 2, 2, 2, 2, 2},
628 {-1, -1, -1, -1, -1, -1, -1, -1},
629 {-1, -1, -1, -1, -1, -1, -1, -1},
630 {-1, -1, -1, -1, -1, -1, -1, -1}},
631 {{ 0, -1, -1, -1, -1, -1, -1, 6},
632 { 6, 1, 4, 3, 7, 5, 0, -1},
633 { 0, -1, -1, -1, -1, -1, -1, 6},
634 { 6, 1, 4, 3, 7, 5, 0, -1},
635 { 0, -1, -1, -1, -1, -1, -1, 6},
636 { 6, 1, 4, 3, 7, 5, 0, -1},
637 {-1, -1, -1, -1, -1, -1, -1, -1},
638 {-1, -1, -1, -1, -1, -1, -1, -1},
639 {-1, -1, -1, -1, -1, -1, -1, -1},
640 {-1, -1, -1, -1, -1, -1, -1, -1}},
641 {{ 3, 3, 4, 6, 6, 4, 3, 3},
642 { 0, 3, 4, 6, 4, 3, 1, -1},
643 { 5, 1, 3, 4, 4, 3, 0, 1},
644 { 0, 1, 3, 4, 3, 1, 0, -1},
645 { 2, 1, 6, 3, 3, 0, 0, 1},
646 { 0, 3, 4, 3, 6, 1, 5, -1},
647 { 6, 1, 2, 6, 4, 0, 0, 2},
648 {-1, -1, -1, -1, -1, -1, -1, -1},
649 {-1, -1, -1, -1, -1, -1, -1, -1},
650 {-1, -1, -1, -1, -1, -1, -1, -1}},
651 {{ 6, 6, -1, -1, -1, -1, 4, 4},
652 { 4, 0, -1, -1, -1, 3, 6, -1},
653 { 0, 6, -1, -1, -1, -1, 4, 2},
654 { 7, -1, -1, -1, -1, -1, 7, -1},
655 { 4, 4, -1, -1, -1, -1, 5, 6},
656 { 6, 4, 7, 7, 5, 6, 4, -1},
657 {-1, 7, 6, 4, 6, 4, 7, -1},
658 {-1, 0, -1, 7, -1, 7, -1, -1},
659 {-1, -1, -1, -1, -1, -1, -1, -1},
660 {-1, -1, -1, -1, -1, -1, -1, -1}},
661 {{-1, 5, -1, -1, -1, -1, 4, -1},
662 {-1, 5, -1, -1, -1, 4, -1, -1},
663 {-1, -1, 5, 6, 6, 4, -1, -1},
664 {-1, -1, 2, -1, 2, -1, -1, -1},
665 { 0, 0, 6, -1, -1, 6, 1, 1},
666 {-1, -1, 2, -1, 2, -1, -1, -1},
667 {-1, -1, 7, 6, 6, 3, -1, -1},
668 {-1, 7, -1, -1, -1, 3, -1, -1},
669 {-1, 7, -1, -1, -1, -1, 3, -1},
670 {-1, -1, -1, -1, -1, -1, -1, -1}},
671 {{-1, 6, -1, -1, -1, -1, 2, -1},
672 { 1, 7, 1, 1, 1, 3, 1, -1},
673 {-1, -1, 4, 1, 1, 4, -1, -1},
674 {-1, 1, 3, 1, 7, 1, -1, -1},
675 {-1, -1, -1, 2, 6, -1, -1, -1},
676 {-1, -1, 1, 5, 1, -1, -1, -1},
677 {-1, -1, -1, -1, -1, -1, -1, -1},
678 {-1, -1, -1, -1, -1, -1, -1, -1},
679 {-1, -1, -1, -1, -1, -1, -1, -1},
680 {-1, -1, -1, -1, -1, -1, -1, -1}},
681 {{ 7, 7, 7, 7, 7, 7, 7, 7},
682 { 7, -1, -1, -1, -1, -1, 7, -1},
683 { 7, -1, -1, 2, 0, 5, 2, 2},
684 { 7, -1, -1, -1, 0, 3, 6, -1},
685 { 7, -1, -1, -1, -1, -1, 4, 0},
686 { 5, 5, -1, -1, -1, -1, -1, -1},
687 { 4, 3, 6, 2, -1, -1, -1, -1},
688 { 0, 2, 0, 4, -1, -1, -1, -1},
689 {-1, -1, -1, -1, -1, -1, -1, -1},
690 {-1, -1, -1, -1, -1, -1, -1, -1}},
691 {{-1, -1, 1, -1, -1, 1, -1, -1},
692 {-1, 4, -1, -1, 5, -1, -1, -1},
693 {-1, 7, -1, -1, 1, 1, 1, -1},
694 { 6, -1, -1, -1, -1, 7, -1, -1},
695 { 1, 1, 1, 1, -1, 4, -1, -1},
696 {-1, -1, 5, -1, -1, -1, -1, -1},
697 {-1, -1, 0, -1, -1, -1, -1, -1},
698 {-1, 3, -1, -1, -1, -1, -1, -1},
699 {-1, 1, -1, -1, -1, -1, -1, -1},
700 {-1, -1, -1, -1, -1, -1, -1, -1}},
701 {{-1, 7, 7, -1, -1, 7, 7, -1},
702 { 6, -1, 4, -1, 4, -1, 6, -1},
703 { 5, -1, -1, 3, 3, -1, -1, 5},
704 { 6, -1, -1, -1, -1, -1, 6, -1},
705 {-1, 7, -1, -1, -1, -1, 7, -1},
706 {-1, 4, -1, -1, -1, 4, -1, -1},
707 {-1, -1, 3, -1, -1, 3, -1, -1},
708 {-1, -1, 2, -1, 2, -1, -1, -1},
709 {-1, -1, -1, 5, 5, -1, -1, -1},
710 {-1, -1, -1, -1, -1, -1, -1, -1}},
711 {{-1, 0, 0, -1, -1, 0, 0, -1},
712 { 7, 4, 6, 6, 6, 4, 3, -1},
713 { 5, 6, 6, 6, 2, 6, 6, 3},
714 { 7, 4, 6, 6, 6, 4, 3, -1},
715 {-1, 0, 0, -1, -1, 0, 0, -1},
716 {-1, -1, -1, -1, -1, -1, -1, -1},
717 {-1, -1, -1, -1, -1, -1, -1, -1},
718 {-1, -1, -1, -1, -1, -1, -1, -1},
719 {-1, -1, -1, -1, -1, -1, -1, -1},
720 {-1, -1, -1, -1, -1, -1, -1, -1}},
721 {{-1, -1, -1, -1, -1, 7, 7, 7},
722 {-1, -1, -1, -1, 2, 7, 7, -1},
723 {-1, 0, 7, 7, 7, -1, 7, 7},
724 { 6, 7, 7, 7, -1, -1, -1, -1},
725 { 6, -1, -1, -1, 7, 7, 7, 7},
726 { 6, -1, -1, -1, -1, -1, -1, -1},
727 { 4, 2, 2, 2, 4, -1, 3, -1},
728 { 4, 4, 4, 4, 3, 3, 3, -1},
729 {-1, -1, -1, -1, -1, -1, -1, -1},
730 {-1, -1, -1, -1, -1, -1, -1, -1}},
731 {{ 4, -1, -1, 7, -1, 6, -1, 7},
732 { 7, 6, 7, -1, -1, 7, 4, -1},
733 {-1, -1, 7, -1, -1, 7, -1, -1},
734 {-1, 0, 0, 0, 0, 0, 3, -1},
735 {-1, -1, 0, 2, 2, 0, 6, 4},
736 {-1, -1, 0, 0, 0, 1, 3, -1},
737 {-1, -1, -1, 0, 0, -1, 3, 4},
738 {-1, -1, -1, 6, -1, 5, 6, -1},
739 {-1, -1, -1, -1, -1, -1, 1, 0},
740 {-1, -1, -1, -1, -1, -1, -1, -1}},
741 {{-1, 5, -1, -1, -1, -1, 5, -1},
742 { 0, -1, -1, 0, -1, -1, 0, -1},
743 { 0, 0, 0, 2, 2, 0, 0, 0},
744 { 0, -1, -1, 0, -1, -1, 0, -1},
745 {-1, 7, -1, 3, -1, -1, 7, -1},
746 {-1, -1, 3, 6, -1, -1, -1, -1},
747 {-1, -1, -1, 6, -1, -1, -1, -1},
748 {-1, 3, 6, -1, -1, -1, -1, -1},
749 {-1, 3, -1, -1, -1, -1, -1, -1},
750 {-1, -1, -1, -1, -1, -1, -1, -1}},
751 {{-1, -1, -1, 6, 5, -1, -1, -1},
752 {-1, -1, 2, 6, 3, -1, -1, -1},
753 {-1, -1, 5, 4, 7, 1, -1, -1},
754 {-1, 6, 2, 2, 3, 4, -1, -1},
755 {-1, -1, 3, 7, 3, 6, -1, -1},
756 {-1, -1, 1, 3, 2, -1, -1, -1},
757 {-1, -1, -1, 4, 5, -1, -1, -1},
758 {-1, -1, -1, 4, -1, -1, -1, -1},
759 {-1, -1, -1, -1, -1, -1, -1, -1},
760 {-1, -1, -1, -1, -1, -1, -1, -1}},
761 {{ 7, 7, -1, 2, 2, -1, 6, 6},
762 { 6, -1, -1, 6, -1, -1, 3, -1},
763 { 2, -1, -1, 1, -1, -1, 2, -1},
764 { 5, -1, -1, 3, -1, -1, 2, -1},
765 { 1, -1, -1, 2, -1, -1, 1, -1},
766 { 5, -1, -1, 2, -1, -1, 2, -1},
767 { 6, -1, -1, 1, -1, -1, 7, -1},
768 { 5, -1, -1, 5, -1, -1, 4, -1},
769 {-1, -1, -1, -1, -1, -1, -1, -1},
770 {-1, -1, -1, -1, -1, -1, -1, -1}},
771 {{-1, -1, -1, 6, 6, -1, -1, -1},
772 {-1, 0, 4, 4, 4, 0, -1, -1},
773 {-1, -1, -1, 6, 6, -1, -1, -1},
774 {-1, -1, 2, 7, 2, -1, -1, -1},
775 {-1, -1, -1, 6, 6, -1, -1, -1},
776 {-1, 0, 5, 5, 5, 0, -1, -1},
777 {-1, -1, -1, 3, 3, -1, -1, -1},
778 {-1, -1, -1, -1, -1, -1, -1, -1},
779 {-1, -1, -1, -1, -1, -1, -1, -1},
780 {-1, -1, -1, -1, -1, -1, -1, -1}},
781 {{-1, -1, 4, 1, 3, -1, -1, -1},
782 {-1, 1, -1, -1, 1, -1, -1, -1},
783 {-1, -1, 4, 1, 3, 4, 1, -1},
784 {-1, 1, 3, 4, -1, -1, 4, -1},
785 {-1, 3, -1, -1, 3, 4, 1, -1},
786 {-1, 1, 3, 4, 1, 3, -1, -1},
787 {-1, -1, 4, 1, -1, -1, -1, -1},
788 {-1, -1, -1, -1, -1, -1, -1, -1},
789 {-1, -1, -1, -1, -1, -1, -1, -1},
790 {-1, -1, -1, -1, -1, -1, -1, -1}},
791 {{-1, 6, 4, -1, 3, 2, 5, -1},
792 { 0, -1, -1, -1, -1, -1, 1, -1},
793 {-1, 2, 3, 5, -1, 4, 6, -1},
794 { 0, -1, -1, -1, -1, -1, 1, -1},
795 {-1, 4, 6, -1, 2, 5, 3, -1},
796 { 0, -1, -1, -1, -1, -1, 1, -1},
797 {-1, 5, 2, 3, -1, 4, 6, -1},
798 {-1, -1, -1, -1, -1, -1, -1, -1},
799 {-1, -1, -1, -1, -1, -1, -1, -1},
800 {-1, -1, -1, -1, -1, -1, -1, -1}},
801 {{-1, -1, -1, 6, 6, -1, -1, -1},
802 {-1, -1, 7, 6, 4, -1, -1, -1},
803 {-1, 2, 1, 7, 4, 1, 3, -1},
804 { 2, 1, 1, 1, 1, 1, 3, -1},
805 {-1, 2, 2, 2, 3, 3, 3, -1},
806 {-1, -1, -1, 5, -1, -1, -1, -1},
807 {-1, -1, -1, 2, 3, -1, -1, -1},
808 {-1, -1, -1, 5, -1, -1, -1, -1},
809 {-1, -1, 2, 2, 3, 3, -1, -1},
810 {-1, -1, -1, -1, -1, -1, -1, -1}},
811 {{ 4, -1, 5, -1, -1, 3, -1, 6},
812 { 2, -1, 3, -1, 2, -1, 4, -1},
813 { 4, -1, -1, 1, 0, -1, -1, 6},
814 { 6, -1, 2, 3, 5, -1, 4, -1},
815 { 4, -1, -1, 0, 1, -1, -1, 6},
816 { 2, -1, 5, -1, 3, -1, 4, -1},
817 { 4, -1, 3, -1, -1, 2, -1, 6},
818 { 6, -1, -1, -1, -1, -1, 4, -1},
819 {-1, -1, -1, -1, -1, -1, -1, -1},
820 {-1, -1, -1, -1, -1, -1, -1, -1}},
821 {{ 2, 6, 0, 5, 5, 1, 3, 4},
822 { 1, -1, -1, 2, -1, -1, 0, -1},
823 { 4, -1, -1, 3, 6, -1, -1, 2},
824 {-1, -1, -1, 0, -1, -1, -1, -1},
825 {-1, -1, -1, 1, 4, -1, -1, -1},
826 {-1, -1, -1, 2, -1, -1, -1, -1},
827 {-1, -1, -1, 6, 3, -1, -1, -1},
828 {-1, -1, -1, 5, -1, -1, -1, -1},
829 {-1, -1, -1, 4, 1, -1, -1, -1},
830 {-1, -1, -1, -1, -1, -1, -1, -1}},
831 {{-1, -1, -1, -1, 5, 1, 1, 3},
832 { 0, 5, 1, 0, 5, 3, 3, -1},
833 { 5, 1, 0, 5, 1, 0, 5, 1},
834 { 0, 5, 1, 0, 5, 1, 6, -1},
835 {-1, -1, -1, -1, 1, 6, 5, 1},
836 {-1, -1, -1, -1, 5, 1, 6, -1},
837 {-1, -1, -1, -1, 1, 0, 5, 1},
838 {-1, -1, -1, -1, 5, 1, 0, -1},
839 {-1, -1, -1, -1, -1, -1, -1, -1},
840 {-1, -1, -1, -1, -1, -1, -1, -1}},
841 {{-1, 0, 7, 3, -1, -1, 2, 2},
842 {-1, 0, 7, 3, -1, -1, 2, -1},
843 {-1, 0, 7, 3, -1, -1, 2, 2},
844 {-1, 0, 7, 3, -1, 3, 1, -1},
845 {-1, 0, 7, 3, -1, 6, 4, 5},
846 {-1, 0, 7, 3, -1, 7, 0, -1},
847 {-1, 0, 7, 3, -1, 2, 3, 4},
848 {-1, 0, 7, 3, -1, 5, 6, -1},
849 {-1, -1, -1, -1, -1, 7, 0, 1},
850 {-1, -1, -1, -1, -1, -1, -1, -1}},
851 {{-1, -1, -1, 7, 7, 7, 7, -1},
852 { 3, 4, 5, -1, -1, -1, 7, -1},
853 { 2, -1, -1, -1, -1, -1, -1, 3},
854 { 7, -1, -1, -1, -1, -1, 4, -1},
855 { 7, -1, -1, -1, 3, 4, 5, 6},
856 { 7, -1, -1, 2, 0, 1, 2, -1},
857 { 6, -1, -1, -1, 3, 4, 5, 6},
858 { 0, 1, -1, -1, -1, -1, -1, -1},
859 { 2, 3, 4, -1, -1, -1, -1, -1},
860 { 5, 6, 0, -1, -1, -1, -1, -1}},
861 {{-1, 7, -1, -1, -1, -1, 2, -1},
862 { 1, 1, -1, -1, -1, 3, 3, -1},
863 {-1, 2, -1, -1, -1, -1, 4, -1},
864 { 3, 3, -1, -1, -1, 5, 5, -1},
865 {-1, 4, -1, -1, -1, -1, 6, -1},
866 { 5, 5, -1, -1, -1, 1, 1, -1},
867 {-1, 6, -1, -1, -1, -1, 7, -1},
868 {-1, -1, -1, -1, -1, -1, -1, -1},
869 {-1, -1, -1, -1, -1, -1, -1, -1},
870 {-1, -1, -1, -1, -1, -1, -1, -1}},
871 {{-1, 4, -1, -1, -1, -1, 4, -1},
872 { 2, -1, -1, 1, -1, -1, 2, -1},
873 { 5, -1, -1, 0, 0, -1, -1, 5},
874 { 5, -1, -1, 1, -1, -1, 6, -1},
875 {-1, 4, 2, 7, 7, 5, 4, -1},
876 {-1, -1, -1, 6, -1, -1, -1, -1},
877 {-1, -1, -1, 3, 3, -1, -1, -1},
878 {-1, -1, -1, 7, -1, -1, -1, -1},
879 {-1, -1, -1, -1, -1, -1, -1, -1},
880 {-1, -1, -1, -1, -1, -1, -1, -1}},
881 {{-1, 1, -1, -1, 2, 3, 4, -1},
882 { 2, -1, -1, 3, 0, 4, -1, -1},
883 { 4, -1, -1, 2, 3, 1, -1, -1},
884 { 3, -1, 4, 3, 0, -1, -1, -1},
885 { 4, -1, -1, 2, 5, 1, -1, -1},
886 { 3, -1, 4, 5, 0, 4, -1, -1},
887 {-1, -1, -1, -1, -1, -1, -1, -1},
888 {-1, -1, -1, -1, -1, -1, -1, -1},
889 {-1, -1, -1, -1, -1, -1, -1, -1},
890 {-1, -1, -1, -1, -1, -1, -1, -1}},
891 {{ 2, -1, -1, 1, 1, -1, -1, 2},
892 { 2, -1, 3, 3, 3, -1, 2, -1},
893 {-1, 2, -1, 4, 4, -1, 2, -1},
894 {-1, 7, 7, 0, 7, 7, -1, -1},
895 {-1, -1, -1, 4, 4, -1, -1, -1},
896 {-1, -1, 5, 7, 5, -1, -1, -1},
897 { 6, 3, 2, 6, 4, 2, 3, 6},
898 { 5, -1, -1, -1, -1, -1, 1, -1},
899 {-1, -1, -1, -1, -1, -1, -1, -1},
900 {-1, -1, -1, -1, -1, -1, -1, -1}},
901 {{ 4, 2, 3, 5, 7, 1, 3, 6},
902 { 1, -1, -1, 1, -1, -1, 1, -1},
903 { 3, 0, 1, 3, 2, 4, 3, 5},
904 { 4, -1, -1, 4, -1, -1, 4, -1},
905 {-1, 5, -1, -1, 5, -1, -1, 5},
906 { 0, 3, 2, 0, 4, 5, 0, -1},
907 {-1, 6, -1, -1, 6, -1, -1, 6},
908 { 7, -1, -1, 7, -1, -1, 7, -1},
909 {-1, -1, -1, -1, -1, -1, -1, -1},
910 {-1, -1, -1, -1, -1, -1, -1, -1}},
911 {{-1, 5, 4, -1, 1, 1, -1, -1},
912 { 5, -1, 4, 1, -1, 1, -1, -1},
913 { 0, -1, -1, -1, -1, -1, 0, -1},
914 { 0, 6, 4, -1, -1, 4, 2, -1},
915 {-1, 4, 3, 5, 2, 6, 3, 6},
916 {-1, 2, 6, -1, -1, 5, 4, -1},
917 {-1, -1, -1, -1, -1, -1, -1, -1},
918 {-1, -1, -1, -1, -1, -1, -1, -1},
919 {-1, -1, -1, -1, -1, -1, -1, -1},
920 {-1, -1, -1, -1, -1, -1, -1, -1}},
921 {{-1, -1, -1, 6, 6, -1, -1, -1},
922 {-1, -1, 5, 5, 4, -1, -1, -1},
923 {-1, -1, 1, 6, 6, 4, -1, -1},
924 {-1, 1, 7, 2, 5, 3, -1, -1},
925 {-1, 2, 7, 2, 1, 5, 3, -1},
926 { 2, 1, 3, 1, 4, 2, 7, -1},
927 {-1, 3, 1, 3, 4, 2, 7, -1},
928 {-1, 3, 5, 5, 6, 6, -1, -1},
929 {-1, -1, -1, -1, -1, -1, -1, -1},
930 {-1, -1, -1, -1, -1, -1, -1, -1}},
931 {{-1, -1, 7, 3, -1, -1, -1, -1},
932 {-1, 1, 7, 6, -1, -1, -1, -1},
933 {-1, 3, 7, 5, 1, 5, -1, -1},
934 { 7, 7, 0, 2, 4, 0, 4, -1},
935 { 7, 1, 4, 6, 5, 6, 5, 7},
936 { 1, 7, 7, 1, 7, 7, 1, -1},
937 {-1, -1, -1, -1, -1, -1, -1, -1},
938 {-1, -1, -1, -1, -1, -1, -1, -1},
939 {-1, -1, -1, -1, -1, -1, -1, -1},
940 {-1, -1, -1, -1, -1, -1, -1, -1}},
941 {{-1, -1, 1, -1, -1, 1, -1, -1},
942 {-1, 5, 6, 1, 5, 6, -1, -1},
943 {-1, 1, 1, 2, 2, 1, 1, -1},
944 { 4, 7, 1, 0, 1, 7, 4, -1},
945 {-1, 3, 7, 5, 7, 5, 3, -1},
946 {-1, 1, 1, 1, 1, 1, -1, -1},
947 {-1, -1, -1, -1, -1, -1, -1, -1},
948 {-1, -1, -1, -1, -1, -1, -1, -1},
949 {-1, -1, -1, -1, -1, -1, -1, -1},
950 {-1, -1, -1, -1, -1, -1, -1, -1}},
951 {{ 4, -1, -1, -1, 5, -1, -1, 4},
952 { 6, 6, 7, 6, -1, 4, 5, -1},
953 { 4, 2, 7, 5, 2, 2, 6, 4},
954 {-1, -1, 4, 1, -1, 5, 2, -1},
955 {-1, 5, 2, 7, 7, -1, 7, 4},
956 { 4, 6, 5, 4, -1, 4, 2, -1},
957 {-1, -1, -1, 4, -1, 4, 1, -1},
958 { 0, 0, 0, 5, -1, -1, -1, -1},
959 {-1, -1, -1, -1, 0, 0, 0, 0},
960 {-1, -1, -1, -1, -1, -1, -1, -1}},
961 {{ 1, -1, -1, -1, 0, 0, -1, -1},
962 { 2, -1, -1, 0, 1, 0, -1, -1},
963 { 3, -1, -1, 0, 2, 2, 0, -1},
964 { 4, -1, 0, 1, 1, 1, 0, -1},
965 { 5, -1, -1, 0, 4, 4, 0, -1},
966 { 6, -1, -1, 4, 4, 4, -1, -1},
967 { 7, -1, -1, -1, 4, 4, -1, -1},
968 {-1, -1, -1, 0, 1, 0, -1, -1},
969 {-1, -1, -1, 0, 1, 1, 0, -1},
970 {-1, -1, -1, -1, -1, -1, -1, -1}},
971 {{-1, -1, 3, -1, -1, 1, 7, -1},
972 {-1, 7, 4, -1, -1, 4, 3, -1},
973 { 1, -1, -1, 0, 2, 0, -1, -1},
974 { 5, 4, -1, 3, -1, -1, -1, -1},
975 { 4, -1, 3, 6, 1, 1, 6, -1},
976 {-1, 1, -1, -1, 4, -1, 1, -1},
977 {-1, 7, 5, -1, -1, -1, 3, -1},
978 {-1, -1, 3, -1, -1, -1, -1, -1},
979 {-1, -1, -1, -1, -1, -1, -1, -1},
980 {-1, -1, -1, -1, -1, -1, -1, -1}},
981 {{ 1, -1, -1, -1, 1, -1, -1, -1},
982 { 2, -1, -1, -1, 2, -1, -1, -1},
983 {-1, 3, -1, -1, 3, 3, -1, -1},
984 {-1, 4, -1, 4, -1, 4, -1, -1},
985 {-1, 5, -1, -1, 5, 5, -1, -1},
986 { 6, -1, -1, 7, 1, 7, -1, -1},
987 { 7, -1, -1, -1, 6, 6, -1, -1},
988 {-1, -1, -1, -1, -1, -1, -1, -1},
989 {-1, -1, -1, -1, -1, -1, -1, -1},
990 {-1, -1, -1, -1, -1, -1, -1, -1}},
991 {{ 2, -1, -1, 6, -1, 2, 5, 1},
992 { 5, -1, 4, -1, 4, -1, 4, -1},
993 { 6, -1, -1, 3, -1, -1, -1, 3},
994 { 4, 2, 0, -1, -1, -1, 5, -1},
995 {-1, -1, -1, 6, -1, 3, 6, -1},
996 {-1, -1, 5, -1, 5, -1, -1, -1},
997 {-1, -1, -1, 3, -1, 4, 2, 5},
998 {-1, -1, -1, -1, -1, -1, -1, -1},
999 {-1, -1, -1, -1, -1, -1, -1, -1},
1000 {-1, -1, -1, -1, -1, -1, -1, -1}},
1001 {{ 6, -1, -1, -1, 4, -1, -1, 3},
1002 { 0, 3, -1, -1, 6, -1, 0, -1},
1003 {-1, -1, 7, -1, 1, -1, 3, -1},
1004 { 7, -1, 4, 7, -1, 2, -1, -1},
1005 { 5, 2, 3, 2, 1, 6, -1, 3},
1006 {-1, -1, 0, 4, 3, 5, 4, -1},
1007 {-1, 7, 6, -1, -1, 0, -1, -1},
1008 { 4, 3, -1, -1, -1, 4, 2, -1},
1009 { 0, -1, -1, -1, -1, -1, 6, -1},
1010 {-1, -1, -1, -1, -1, -1, -1, -1}},
1011 {{ 6, 1, 2, 5, 1, 6, 3, 0},
1012 {-1, -1, -1, -1, -1, -1, 4, -1},
1013 { 0, 5, 2, 7, 1, 6, 2, -1},
1014 { 3, -1, -1, -1, -1, -1, -1, -1},
1015 { 6, 7, 6, 4, 0, 5, 2, 6},
1016 {-1, -1, -1, -1, -1, -1, 1, -1},
1017 { 6, 1, 4, 0, 6, 2, 3, -1},
1018 { 0, -1, -1, -1, -1, -1, -1, -1},
1019 {-1, 0, 4, 5, 3, 7, 6, 0},
1020 {-1, -1, -1, -1, -1, -1, -1, -1}},
1021 {{-1, -1, -1, 0, 1, -1, -1, -1},
1022 {-1, -1, 0, 7, 0, -1, -1, -1},
1023 {-1, -1, 1, 2, 2, 0, -1, -1},
1024 {-1, 0, 7, 0, 7, 0, -1, -1},
1025 {-1, 6, -1, 7, 7, -1, 6, -1},
1026 { 4, 1, 6, 6, 6, 4, 1, -1},
1027 {-1, 5, -1, 7, 7, -1, 5, -1},
1028 {-1, -1, -1, -1, -1, -1, -1, -1},
1029 {-1, -1, -1, -1, -1, -1, -1, -1},
1030 {-1, -1, -1, -1, -1, -1, -1, -1}},
1031 {{-1, -1, -1, 5, 6, -1, -1, -1},
1032 {-1, -1, 3, 3, 3, -1, -1, -1},
1033 {-1, -1, 7, 5, 3, 7, -1, -1},
1034 {-1, 3, -1, 6, -1, 3, -1, -1},
1035 { 2, -1, -1, 3, 7, -1, -1, 1},
1036 { 2, 2, -1, 3, -1, 1, 1, -1},
1037 {-1, 0, 2, 5, 6, 1, 0, -1},
1038 {-1, -1, -1, 3, -1, -1, -1, -1},
1039 {-1, -1, -1, 3, 7, -1, -1, -1},
1040 {-1, -1, -1, -1, -1, -1, -1, -1}},
1041 {{-1, 6, -1, -1, -1, -1, 2, -1},
1042 {-1, 2, 6, 0, 6, 0, -1, -1},
1043 {-1, 0, -1, -1, -1, -1, -1, -1},
1044 { 6, -1, -1, -1, -1, -1, -1, -1},
1045 {-1, 3, 3, 2, 0, 6, 0, 0},
1046 {-1, 6, -1, -1, -1, -1, 0, -1},
1047 {-1, -1, -1, 6, 0, 2, 6, -1},
1048 {-1, 2, 0, -1, -1, -1, -1, -1},
1049 {-1, -1, -1, -1, -1, -1, -1, -1},
1050 {-1, -1, -1, -1, -1, -1, -1, -1}},
1051 {{ 0, 7, -1, -1, -1, -1, -1, -1},
1052 { 1, 5, -1, -1, -1, -1, -1, -1},
1053 { 7, 2, 5, -1, -1, -1, -1, -1},
1054 { 6, 3, 4, -1, -1, -1, -1, -1},
1055 { 5, 5, 4, 4, -1, -1, -1, -1},
1056 { 3, 3, 5, 3, -1, -1, -1, -1},
1057 { 1, 2, 2, 5, 3, -1, -1, -1},
1058 { 1, 0, 0, 7, 6, -1, -1, -1},
1059 { 3, 3, 5, 5, 7, 6, -1, -1},
1060 {-1, -1, -1, -1, -1, -1, -1, -1}},
1061 {{-1, -1, 2, 6, 6, 2, -1, -1},
1062 {-1, 2, 1, 1, 0, 2, -1, -1},
1063 {-1, 2, 3, 2, 2, 0, 2, -1},
1064 { 2, 3, 2, 5, 2, 7, 2, -1},
1065 { 2, 4, 2, 5, 2, 7, 2, 0},
1066 { 2, 4, 2, 6, 6, 2, 0, -1},
1067 {-1, 2, 5, 2, 2, 2, 7, 2},
1068 {-1, 2, 5, 6, 6, 7, 2, -1},
1069 {-1, -1, 2, 2, 2, 2, 2, -1},
1070 {-1, -1, -1, -1, -1, -1, -1, -1}},
1071 {{-1, -1, 0, -1, -1, 0, -1, -1},
1072 { 1, 0, 0, 1, 0, 0, 1, -1},
1073 { 1, 7, 7, 5, 5, 7, 7, 1},
1074 { 3, 2, -1, 2, -1, 2, 3, -1},
1075 { 3, 7, -1, 6, 6, -1, 7, 3},
1076 { 7, -1, -1, 6, -1, -1, 7, -1},
1077 { 4, 4, 5, -1, -1, 5, 4, 4},
1078 {-1, -1, -1, -1, -1, -1, -1, -1},
1079 {-1, -1, -1, -1, -1, -1, -1, -1},
1080 {-1, -1, -1, -1, -1, -1, -1, -1}},
1081 {{-1, 6, 3, -1, -1, 3, 6, -1},
1082 { 6, -1, 2, -1, 2, -1, 6, -1},
1083 { 2, -1, 0, 1, 1, 0, -1, 2},
1084 { 5, 0, -1, 7, -1, 0, 5, -1},
1085 {-1, 5, -1, 6, 6, -1, 5, -1},
1086 { 7, 1, 4, -1, 4, 1, 7, -1},
1087 { 7, -1, 4, -1, -1, 4, -1, 7},
1088 { 2, 0, -1, -1, -1, 0, 2, -1},
1089 {-1, 2, -1, -1, -1, -1, 2, -1},
1090 {-1, -1, -1, -1, -1, -1, -1, -1}},
1091 {{ 6, 1, -1, -1, -1, -1, 4, 0},
1092 { 2, 7, 5, 5, 5, 7, 3, -1},
1093 { 6, 1, -1, -1, -1, -1, 4, 0},
1094 { 2, 5, 7, 7, 7, 5, 3, -1},
1095 { 6, 1, -1, -1, -1, -1, 4, 0},
1096 { 2, 0, 6, 6, 6, 0, 3, -1},
1097 { 6, 1, -1, -1, -1, -1, 4, 0},
1098 {-1, -1, -1, -1, -1, -1, -1, -1},
1099 {-1, -1, -1, -1, -1, -1, -1, -1},
1100 {-1, -1, -1, -1, -1, -1, -1, -1}},
1101 {{ 5, -1, -1, 1, 1, -1, -1, 5},
1102 { 5, -1, 4, -1, 4, -1, 5, -1},
1103 {-1, 2, 4, -1, -1, 4, 2, -1},
1104 { 7, 2, -1, -1, -1, 2, 7, -1},
1105 { 0, -1, 0, 4, 4, 0, -1, 0},
1106 { 7, 2, -1, -1, -1, 2, 7, -1},
1107 {-1, 2, 3, -1, -1, 3, 2, -1},
1108 { 5, -1, 3, -1, 3, -1, 5, -1},
1109 { 5, -1, -1, 6, 6, -1, -1, 5},
1110 {-1, -1, -1, -1, -1, -1, -1, -1}},
1111 {{ 2, 2, -1, -1, -1, -1, 5, 5},
1112 { 5, -1, -1, -1, -1, -1, 2, -1},
1113 { 5, -1, -1, -1, -1, -1, -1, 2},
1114 { 1, -1, 1, 5, 1, -1, 3, -1},
1115 { 5, 2, 5, 3, 1, 2, 5, 2},
1116 { 2, 0, 5, -1, 2, 0, 5, -1},
1117 {-1, 3, 7, -1, -1, 3, 7, -1},
1118 {-1, -1, 2, 0, 5, -1, -1, -1},
1119 {-1, -1, -1, -1, -1, -1, -1, -1},
1120 {-1, -1, -1, -1, -1, -1, -1, -1}},
1121 {{ 0, 6, 5, 2, 3, 4, 1, 7},
1122 {-1, -1, -1, -1, 1, -1, -1, -1},
1123 {-1, -1, -1, 1, 1, -1, -1, -1},
1124 {-1, -1, 1, -1, -1, -1, -1, -1},
1125 { 7, 1, 4, 3, 2, 5, 6, 0},
1126 {-1, -1, -1, -1, 1, -1, -1, -1},
1127 {-1, -1, -1, 1, 1, -1, -1, -1},
1128 {-1, -1, 1, -1, -1, -1, -1, -1},
1129 { 0, 6, 5, 2, 3, 4, 1, 7},
1130 {-1, -1, -1, -1, -1, -1, -1, -1}},
1131 {{-1, -1, 1, -1, -1, 1, -1, -1},
1132 {-1, 2, 4, -1, 2, 4, -1, -1},
1133 {-1, 2, 3, 6, 5, 3, 2, -1},
1134 {-1, 6, 5, -1, 6, 5, -1, -1},
1135 {-1, -1, -1, 7, 7, -1, -1, -1},
1136 {-1, -1, -1, 7, -1, -1, -1, -1},
1137 { 1, -1, -1, 7, 7, -1, -1, 3},
1138 { 2, -1, -1, 7, -1, -1, 2, -1},
1139 {-1, 3, 4, 5, 6, 4, 1, -1},
1140 {-1, -1, -1, -1, -1, -1, -1, -1}},
1141 {{ 1, -1, -1, 2, 2, -1, -1, 2},
1142 { 1, 3, 7, 3, 7, 4, 2, -1},
1143 {-1, 1, 6, -1, -1, 6, 2, -1},
1144 { 6, -1, 7, 3, 7, -1, 6, -1},
1145 {-1, 4, 2, -1, -1, 1, 3, -1},
1146 {-1, -1, 2, 6, 1, -1, -1, -1},
1147 {-1, 4, 3, 3, 4, 4, 3, -1},
1148 {-1, -1, -1, -1, -1, -1, -1, -1},
1149 {-1, -1, -1, -1, -1, -1, -1, -1},
1150 {-1, -1, -1, -1, -1, -1, -1, -1}},
1151 {{-1, -1, -1, 5, 6, -1, -1, -1},
1152 {-1, -1, -1, 3, -1, -1, -1, -1},
1153 {-1, -1, -1, 1, 2, -1, -1, -1},
1154 {-1, -1, -1, 4, -1, -1, -1, -1},
1155 {-1, -1, -1, 5, 7, -1, -1, -1},
1156 {-1, -1, -1, 2, -1, -1, -1, -1},
1157 { 6, 5, 4, 3, 2, 1, 7, 5},
1158 {-1, -1, -1, -1, -1, -1, -1, -1},
1159 {-1, -1, -1, -1, -1, -1, -1, -1},
1160 {-1, -1, -1, -1, -1, -1, -1, -1}},
1161 {{-1, 0, -1, 1, -1, 2, -1, -1},
1162 {-1, 4, -1, 5, -1, 6, -1, -1},
1163 {-1, 7, -1, 0, -1, 2, -1, -1},
1164 {-1, 6, -1, 3, -1, 6, -1, -1},
1165 {-1, 1, -1, 1, -1, 2, -1, -1},
1166 {-1, 3, -1, 5, -1, 0, -1, -1},
1167 {-1, 2, -1, 4, -1, 6, -1, -1},
1168 {-1, 3, -1, 6, -1, 7, -1, -1},
1169 {-1, -1, -1, -1, -1, -1, -1, -1},
1170 {-1, -1, -1, -1, -1, -1, -1, -1}},
1171 {{ 1, 1, 2, 2, 3, 3, 4, 4},
1172 { 5, 5, 6, 7, 6, 5, 5, -1},
1173 { 6, 4, 3, 3, 2, 2, 1, 6},
1174 { 4, 6, 5, 7, 6, 3, 1, -1},
1175 {-1, -1, -1, -1, -1, -1, -1, -1},
1176 {-1, -1, -1, -1, -1, -1, -1, -1},
1177 {-1, -1, -1, -1, -1, -1, -1, -1},
1178 {-1, -1, -1, -1, -1, -1, -1, -1},
1179 {-1, -1, -1, -1, -1, -1, -1, -1},
1180 {-1, -1, -1, -1, -1, -1, -1, -1}},
1181 {{ 7, 4, -1, 1, 2, -1, 4, 7},
1182 { 5, 5, -1, 2, -1, 4, 4, -1},
1183 {-1, 5, -1, 7, 7, -1, 4, -1},
1184 { 1, 0, 6, 7, 6, 0, 2, -1},
1185 {-1, 2, -1, 5, 3, -1, 1, -1},
1186 { 1, 1, -1, -1, -1, 2, 2, -1},
1187 { 6, 1, 4, -1, -1, 4, 2, 6},
1188 { 5, 3, -1, -1, -1, 3, 5, -1},
1189 {-1, -1, -1, -1, -1, -1, -1, -1},
1190 {-1, -1, -1, -1, -1, -1, -1, -1}},
1191 {{ 1, 5, 1, 0, 0, 1, 5, 1},
1192 { 1, 2, 5, -1, 5, 2, 1, -1},
1193 { 3, 6, 1, 2, 2, 1, 6, 3},
1194 { 4, 3, 4, -1, 4, 3, 4, -1},
1195 { 3, 4, 6, 5, 5, 6, 4, 3},
1196 { 0, 2, 3, -1, 3, 2, 0, -1},
1197 { 2, 3, 1, 5, 5, 1, 3, 2},
1198 {-1, -1, -1, -1, -1, -1, -1, -1},
1199 {-1, -1, -1, -1, -1, -1, -1, -1},
1200 {-1, -1, -1, -1, -1, -1, -1, -1}},
1201 {{ 3, 0, 2, 7, 5, 7, 6, 5},
1202 { 6, -1, 1, -1, 2, -1, 1, -1},
1203 {-1, 6, 4, 0, 3, 4, 5, -1},
1204 {-1, 5, -1, 1, -1, 4, -1, -1},
1205 {-1, 7, 3, 5, 6, 5, 3, -1},
1206 { 1, -1, 2, -1, 4, -1, 2, -1},
1207 { 6, 4, 4, 6, 6, 5, 5, 1},
1208 {-1, -1, -1, -1, -1, -1, -1, -1},
1209 {-1, -1, -1, -1, -1, -1, -1, -1},
1210 {-1, -1, -1, -1, -1, -1, -1, -1}}
1213 /* the tile struct
1214 * type is the bubble number 0-7
1215 * fallx is the x axis movement for the falling bubble
1216 * fallvel is the initial upward velocity for the falling bubble
1217 * ingroup denotes a bubble that is part of a group to be removed
1218 * anchored denotes a bubble that is anchored to the ceiling
1220 struct tile {
1221 int type;
1222 int fallx;
1223 int fallvel;
1224 bool ingroup;
1225 bool anchored;
1226 bool delete;
1229 /* the highscore struct
1230 * level is the highscore level
1231 * score is the highscore score
1233 struct highscore {
1234 unsigned int level;
1235 unsigned int score;
1238 /* the game context struct
1239 * score is the current score
1240 * level is the current level
1241 * highlevel is the highest level beaten
1242 * highscores is the list of high scores
1243 * angle is the current cannon direction
1244 * shots is the number of shots fired since last compression
1245 * compress is the height of the compressor
1246 * onboardcnt is the number of unique bubbles on the playing board
1247 * onboard is the unique bubbles on the playing board
1248 * nextinq is the pointer to the next bubble in the firing queue
1249 * queue is the circular buffer of bubbles to be fired
1250 * elapsedlvl is level elapsed time in 1/100s of seconds
1251 * elapsedshot is the shot elapsed time in 1/100s of seconds
1252 * startedshot is when the current shot began
1253 * resume denotes whether to resume the currently loaded game
1254 * dirty denotes whether the high scores are out of sync with the saved file
1255 * playboard is the game playing board
1257 struct game_context {
1258 unsigned int score;
1259 unsigned int level;
1260 unsigned int highlevel;
1261 struct highscore highscores[NUM_SCORES];
1262 int angle;
1263 int shots;
1264 int compress;
1265 int onboardcnt;
1266 int onboard[NUM_BUBBLES];
1267 int nextinq;
1268 int queue[NUM_QUEUE];
1269 long elapsedlvl;
1270 long elapsedshot;
1271 long startedshot;
1272 bool resume;
1273 bool dirty;
1274 struct tile playboard[BB_HEIGHT][BB_WIDTH];
1277 static void bubbles_init(struct game_context* bb);
1278 static bool bubbles_nextlevel(struct game_context* bb);
1279 static void bubbles_getonboard(struct game_context* bb);
1280 static void bubbles_drawboard(struct game_context* bb);
1281 static int bubbles_fire(struct game_context* bb);
1282 static bool bubbles_collision(struct game_context* bb, int y, int x,
1283 int nearrow, int nearcol);
1284 static bool bubbles_ingroup(struct game_context* bb, int row, int col);
1285 static int bubbles_searchgroup(struct game_context* bb, int row, int col);
1286 static int bubbles_remove(struct game_context* bb);
1287 static void bubbles_anchored(struct game_context* bb, int row, int col);
1288 static int bubbles_fall(struct game_context* bb);
1289 static int bubbles_checklevel(struct game_context* bb);
1290 static int bubbles_recordscore(struct game_context* bb);
1291 static void bubbles_savescores(struct game_context* bb);
1292 static bool bubbles_loadgame(struct game_context* bb);
1293 static void bubbles_savegame(struct game_context* bb);
1294 static void bubbles_setcolors(void);
1295 static void bubbles_callback(void* param);
1296 static int bubbles_handlebuttons(struct game_context* bb, bool animblock,
1297 int timeout);
1298 static int bubbles(struct game_context* bb);
1300 /*****************************************************************************
1301 * bubbles_init() initializes bubbles data structures.
1302 ******************************************************************************/
1303 static void bubbles_init(struct game_context* bb) {
1304 /* seed the rand generator */
1305 rb->srand(*rb->current_tick);
1307 /* check for resumed game */
1308 if(bb->resume) {
1309 bb->resume = false;
1310 return;
1313 bb->score = 0;
1314 bubbles_nextlevel(bb);
1317 /*****************************************************************************
1318 * bubbles_nextlevel() sets up the game for the next level, returns false if
1319 * there are no more levels.
1320 ******************************************************************************/
1321 static bool bubbles_nextlevel(struct game_context* bb) {
1322 int i, j, pos;
1324 bb->level++;
1326 /* check if there are no more levels */
1327 if(bb->level > NUM_LEVELS) return false;
1329 /* set up the play board */
1330 rb->memset(bb->playboard, 0, sizeof(bb->playboard));
1331 for(i=0; i<BB_LEVEL_HEIGHT; i++) {
1332 for(j=0; j<BB_WIDTH; j++) {
1333 pos = (int)level[bb->level-1][i][j];
1334 if(pos >=0 && pos < NUM_BUBBLES) {
1335 bb->playboard[i][j].type = pos;
1336 } else {
1337 bb->playboard[i][j].type = -1;
1341 for(i=BB_LEVEL_HEIGHT; i<BB_HEIGHT; i++) {
1342 for(j=0; j<BB_WIDTH; j++) {
1343 bb->playboard[i][j].type = -1;
1347 /* fill first bubbles in shot queue */
1348 bubbles_getonboard(bb);
1349 for(i=0; i<NUM_QUEUE; i++) {
1350 bb->queue[i] = bb->onboard[rb->rand()%bb->onboardcnt];
1353 bb->angle = 0;
1354 bb->shots = 0;
1355 bb->compress = 0;
1356 bb->nextinq = 0;
1357 bb->elapsedlvl = 0;
1358 bb->elapsedshot = 0;
1360 return true;
1363 /*****************************************************************************
1364 * bubbles_getonboard() determines which bubble types are on the play board.
1365 ******************************************************************************/
1366 static void bubbles_getonboard(struct game_context* bb) {
1367 int i, j, k;
1368 bool found;
1370 bb->onboardcnt = 0;
1371 rb->memset(bb->onboard, -1, sizeof(bb->onboard));
1373 for(i=0; i<BB_HEIGHT; i++) {
1374 for(j=0; j<BB_WIDTH; j++) {
1375 if(bb->playboard[i][j].type >= 0) {
1376 found = false;
1378 for(k=0; k<bb->onboardcnt; k++) {
1379 if(bb->playboard[i][j].type == bb->onboard[k]) {
1380 found = true;
1381 break;
1385 if(!found) {
1386 bb->onboard[bb->onboardcnt] = bb->playboard[i][j].type;
1387 bb->onboardcnt++;
1390 if(bb->onboardcnt == NUM_BUBBLES) return;
1396 /*****************************************************************************
1397 * bubbles_drawboard() draws the game board to the buffer but does not update
1398 * the lcd.
1399 ******************************************************************************/
1400 static void bubbles_drawboard(struct game_context* bb) {
1401 int i, j;
1402 int w, h;
1403 int colmax, indent;
1404 int tipx, tipy;
1405 bool evenline = false;
1406 char *level = "Level";
1407 char *score = "Score";
1408 char *next = "Next";
1409 char *hurry = "HURRY!";
1410 char str[11];
1412 /* clear screen */
1413 rb->lcd_clear_display();
1415 /* draw background */
1416 #ifdef HAVE_LCD_COLOR
1417 rb->lcd_bitmap(bubbles_background, 0, 0, LCD_WIDTH, LCD_HEIGHT);
1418 #endif
1420 /* display play board */
1421 for(i=0; i<BB_HEIGHT; i++) {
1422 colmax = BB_WIDTH;
1423 if(evenline) {
1424 colmax--;
1425 indent = ROW_INDENT;
1426 } else {
1427 indent = 0;
1429 evenline = !evenline;
1431 for(j=0; j<colmax; j++) {
1432 if(bb->playboard[i][j].type >= 0 && !bb->playboard[i][j].delete) {
1433 rb->lcd_bitmap_part(bubbles_emblem,
1434 0, EMBLEM_HEIGHT*bb->playboard[i][j].type, EMBLEM_WIDTH,
1435 XOFS+indent+BUBBLE_WIDTH*j+(BUBBLE_WIDTH-EMBLEM_WIDTH)/2,
1436 ROW_HEIGHT*i+(BUBBLE_HEIGHT-EMBLEM_HEIGHT)/2+bb->compress*ROW_HEIGHT,
1437 EMBLEM_WIDTH, EMBLEM_HEIGHT);
1438 rb->lcd_set_drawmode(DRMODE_FG);
1439 rb->lcd_mono_bitmap((const unsigned char *)bubbles_bubble,
1440 XOFS+indent+BUBBLE_WIDTH*j,
1441 ROW_HEIGHT*i+bb->compress*ROW_HEIGHT,
1442 BUBBLE_WIDTH, BUBBLE_HEIGHT);
1443 rb->lcd_set_drawmode(DRMODE_SOLID);
1448 /* display bubble to be shot */
1449 rb->lcd_bitmap_part(bubbles_emblem,
1450 0, EMBLEM_HEIGHT*bb->queue[bb->nextinq], EMBLEM_WIDTH,
1451 SHOTX+(BUBBLE_WIDTH-EMBLEM_WIDTH)/2,
1452 SHOTY+(BUBBLE_HEIGHT-EMBLEM_HEIGHT)/2,
1453 EMBLEM_WIDTH, EMBLEM_HEIGHT);
1454 rb->lcd_set_drawmode(DRMODE_FG);
1455 rb->lcd_mono_bitmap((const unsigned char *)bubbles_bubble,
1456 SHOTX, SHOTY,
1457 BUBBLE_WIDTH, BUBBLE_HEIGHT);
1458 rb->lcd_set_drawmode(DRMODE_SOLID);
1460 /* display next bubble to be shot */
1461 rb->lcd_bitmap_part(bubbles_emblem,
1462 0, EMBLEM_HEIGHT*bb->queue[(bb->nextinq+1)%NUM_QUEUE], EMBLEM_WIDTH,
1463 XOFS/2-BUBBLE_WIDTH/2+(BUBBLE_WIDTH-EMBLEM_WIDTH)/2,
1464 SHOTY+(BUBBLE_HEIGHT-EMBLEM_HEIGHT)/2,
1465 EMBLEM_WIDTH, EMBLEM_HEIGHT);
1466 rb->lcd_set_drawmode(DRMODE_FG);
1467 rb->lcd_mono_bitmap((const unsigned char *)bubbles_bubble,
1468 XOFS/2-BUBBLE_WIDTH/2, SHOTY,
1469 BUBBLE_WIDTH, BUBBLE_HEIGHT);
1470 rb->lcd_set_drawmode(DRMODE_SOLID);
1472 /* draw bounding lines */
1473 #ifndef HAVE_LCD_COLOR
1474 rb->lcd_vline(XOFS-1, 0, LCD_HEIGHT);
1475 rb->lcd_vline(XOFS+BUBBLE_WIDTH*BB_WIDTH, 0, LCD_HEIGHT);
1476 #endif
1477 rb->lcd_hline(XOFS, XOFS+BUBBLE_WIDTH*BB_WIDTH-1, bb->compress*ROW_HEIGHT-1);
1478 rb->lcd_hline(XOFS, XOFS+BUBBLE_WIDTH*BB_WIDTH-1,
1479 ROW_HEIGHT*(BB_HEIGHT-2)+BUBBLE_HEIGHT);
1481 /* draw arrow */
1482 tipx = SHOTX+BUBBLE_WIDTH/2+(((sin_int(bb->angle)>>4)*BUBBLE_WIDTH*3/2)>>10);
1483 tipy = SHOTY+BUBBLE_HEIGHT/2-(((cos_int(bb->angle)>>4)*BUBBLE_HEIGHT*3/2)>>10);
1485 rb->lcd_drawline(SHOTX+BUBBLE_WIDTH/2+(((sin_int(bb->angle)>>4)*BUBBLE_WIDTH/2)>>10),
1486 SHOTY+BUBBLE_HEIGHT/2-(((cos_int(bb->angle)>>4)*BUBBLE_HEIGHT/2)>>10),
1487 tipx, tipy);
1488 xlcd_filltriangle(tipx, tipy,
1489 tipx+(((sin_int(bb->angle-135)>>4)*BUBBLE_WIDTH/3)>>10),
1490 tipy-(((cos_int(bb->angle-135)>>4)*BUBBLE_HEIGHT/3)>>10),
1491 tipx+(((sin_int(bb->angle+135)>>4)*BUBBLE_WIDTH/3)>>10),
1492 tipy-(((cos_int(bb->angle+135)>>4)*BUBBLE_HEIGHT/3)>>10));
1494 /* draw text */
1495 rb->lcd_getstringsize(level, &w, &h);
1496 rb->lcd_putsxy(XOFS/2-w/2, 2, level);
1498 rb->snprintf(str, 4, "%d", bb->level);
1499 rb->lcd_getstringsize(str, &w, &h);
1500 rb->lcd_putsxy(XOFS/2-w/2, 11, str);
1502 rb->lcd_getstringsize(score, &w, &h);
1503 rb->lcd_putsxy(XOFS/2-w/2, 29, score);
1505 rb->snprintf(str, 10, "%d", bb->score);
1506 rb->lcd_getstringsize(str, &w, &h);
1507 rb->lcd_putsxy(XOFS/2-w/2, 38, str);
1509 rb->lcd_getstringsize(next, &w, &h);
1510 rb->lcd_putsxy(XOFS/2-w/2, SHOTY-9, next);
1512 if(bb->elapsedshot >= (MAX_SHOTTIME*7)/10) {
1513 rb->lcd_getstringsize(hurry, &w, &h);
1514 rb->lcd_putsxy(LCD_WIDTH/2-w/2, LCD_HEIGHT/2-h/2, hurry);
1518 /*****************************************************************************
1519 * bubbles_fire() fires the current bubble, reloads the cannon, attaches
1520 * bubble to playboard, removes appropriate bubbles, and advances the
1521 * the compressor.
1522 ******************************************************************************/
1523 static int bubbles_fire(struct game_context* bb) {
1524 int bubblecur;
1525 long shotxinc, shotyinc;
1526 long shotxofs, shotyofs;
1527 int shotxdirec = 1;
1528 long tempxofs, tempyofs;
1529 int nearrow, nearcol;
1530 int lastrow = BB_HEIGHT-1;
1531 int lastcol = (BB_WIDTH-1)/2;
1532 int buttonres;
1533 long lasttick, currenttick;
1535 /* get current bubble */
1536 bubblecur = bb->queue[bb->nextinq];
1537 shotxinc = ((sin_int(bb->angle)>>4)*BUBBLE_WIDTH)/3;
1538 shotyinc = ((-1*(cos_int(bb->angle)>>4))*BUBBLE_HEIGHT)/3;
1539 shotxofs = shotyofs = 0;
1541 /* advance the queue */
1542 bb->queue[bb->nextinq] = bb->onboard[rb->rand()%bb->onboardcnt];
1543 bb->nextinq = (bb->nextinq+1)%NUM_QUEUE;
1544 bubbles_drawboard(bb);
1545 rb->lcd_update_rect(0, 0, XOFS, LCD_HEIGHT);
1547 /* move the bubble across the play board */
1548 lasttick = *rb->current_tick;
1550 while(true) {
1551 /* move the bubble one step */
1552 shotyofs += shotyinc;
1553 shotxofs += shotxinc*shotxdirec;
1555 /* check for bounce off sides */
1556 if(SHOTX+(shotxofs>>10) < XOFS) {
1557 shotxofs += 2*((XOFS<<10)-(((SHOTX)<<10)+shotxofs));
1558 shotxdirec *= -1;
1559 } else if(SHOTX+(shotxofs>>10) > XOFS+(BB_WIDTH-1)*BUBBLE_WIDTH) {
1560 shotxofs -= 2*((((SHOTX)<<10)+shotxofs)-
1561 ((XOFS<<10)+(((BB_WIDTH-1)*BUBBLE_WIDTH)<<10)));
1562 shotxdirec *= -1;
1565 tempxofs = shotxofs>>10;
1566 tempyofs = shotyofs>>10;
1568 /* display shot */
1569 bubbles_drawboard(bb);
1570 rb->lcd_bitmap_part(bubbles_emblem, 0, EMBLEM_HEIGHT*bubblecur, EMBLEM_WIDTH,
1571 SHOTX+tempxofs+(BUBBLE_WIDTH-EMBLEM_WIDTH)/2,
1572 SHOTY+tempyofs+(BUBBLE_HEIGHT-EMBLEM_HEIGHT)/2,
1573 EMBLEM_WIDTH, EMBLEM_HEIGHT);
1574 rb->lcd_set_drawmode(DRMODE_FG);
1575 rb->lcd_mono_bitmap((const unsigned char *)bubbles_bubble,
1576 SHOTX+tempxofs, SHOTY+tempyofs,
1577 BUBBLE_WIDTH, BUBBLE_HEIGHT);
1578 rb->lcd_set_drawmode(DRMODE_SOLID);
1579 rb->lcd_update_rect(XOFS, 0, BB_WIDTH*BUBBLE_WIDTH, LCD_HEIGHT);
1581 /* find nearest position */
1582 nearrow = ((SHOTY+tempyofs)-
1583 (bb->compress*ROW_HEIGHT)+
1584 (ROW_HEIGHT/2))/ROW_HEIGHT;
1585 if(nearrow >= BB_HEIGHT) nearrow = BB_HEIGHT-1;
1587 if(nearrow%2) { /* odd row */
1588 nearcol = ((SHOTX+tempxofs)-
1589 (XOFS+ROW_INDENT)+
1590 (BUBBLE_WIDTH/2))/BUBBLE_WIDTH;
1591 if(nearcol >= BB_WIDTH-1) nearcol = BB_WIDTH-2;
1592 } else { /* even row */
1593 nearcol = ((SHOTX+tempxofs)-XOFS+(BUBBLE_WIDTH/2))/BUBBLE_WIDTH;
1594 if(nearcol >= BB_WIDTH) nearcol = BB_WIDTH-1;
1596 if(nearcol < 0) nearcol = 0;
1598 /* if nearest position is occupied attach to last position */
1599 if(bb->playboard[nearrow][nearcol].type >= 0) {
1600 bb->playboard[lastrow][lastcol].type = bubblecur;
1601 break;
1604 /* save last position */
1605 lastrow = nearrow;
1606 lastcol = nearcol;
1608 /* if collision with neighbor then attach shot */
1609 if(bubbles_collision(bb, SHOTY+tempyofs, SHOTX+tempxofs,
1610 nearrow, nearcol)) {
1611 bb->playboard[nearrow][nearcol].type = bubblecur;
1612 break;
1615 /* if at top then attach shot to the ceiling */
1616 if(nearrow == 0 && SHOTY+tempyofs <= bb->compress*ROW_HEIGHT) {
1617 bb->playboard[nearrow][nearcol].type = bubblecur;
1618 break;
1621 /* handle button events */
1622 buttonres = bubbles_handlebuttons(bb, true, 0);
1623 if(buttonres != BB_NONE) return buttonres;
1625 /* framerate limiting */
1626 currenttick = *rb->current_tick;
1627 if(currenttick-lasttick < HZ/MAX_FPS) {
1628 rb->sleep((HZ/MAX_FPS)-(currenttick-lasttick));
1629 } else {
1630 rb->yield();
1632 lasttick = currenttick;
1635 bubbles_drawboard(bb);
1636 rb->lcd_update();
1638 /* clear appropriate bubbles from playing board */
1639 if(bubbles_ingroup(bb, lastrow, lastcol)) {
1640 buttonres = bubbles_remove(bb);
1641 if(buttonres != BB_NONE) return buttonres;
1644 /* update shots and compress amount */
1645 bb->shots++;
1646 if(bb->shots >= NUM_COMPRESS) {
1647 bb->shots = 0;
1648 bb->compress++;
1651 return BB_NONE;
1654 /*****************************************************************************
1655 * bubbles_collision() determines if a fired bubble has collided with another
1656 * bubble.
1657 ******************************************************************************/
1658 static bool bubbles_collision(struct game_context* bb, int y, int x,
1659 int nearrow, int nearcol) {
1660 int nx, ny;
1661 int adj = nearrow%2;
1663 /* check neighbors */
1664 if(nearcol-1 >= 0) {
1665 if(bb->playboard[nearrow][nearcol-1].type >= 0) {
1666 nx = XOFS+(nearrow%2 ? ROW_INDENT : 0)+BUBBLE_WIDTH*(nearcol-1);
1667 ny = ROW_HEIGHT*nearrow+bb->compress*ROW_HEIGHT;
1668 if((x-nx)*(x-nx)+(y-ny)*(y-ny) < MIN_DISTANCE) return true;
1672 if(nearcol-1+adj >= 0) {
1673 if(nearrow-1 >= 0) {
1674 if(bb->playboard[nearrow-1][nearcol-1+adj].type >= 0) {
1675 nx = XOFS+((nearrow-1)%2 ? ROW_INDENT : 0)+
1676 BUBBLE_WIDTH*(nearcol-1+adj);
1677 ny = ROW_HEIGHT*(nearrow-1)+bb->compress*ROW_HEIGHT;
1678 if((x-nx)*(x-nx)+(y-ny)*(y-ny) < MIN_DISTANCE) return true;
1682 if(nearrow+1 < BB_HEIGHT) {
1683 if(bb->playboard[nearrow+1][nearcol-1+adj].type >= 0) {
1684 nx = XOFS+((nearrow+1)%2 ? ROW_INDENT : 0)+
1685 BUBBLE_WIDTH*(nearcol-1+adj);
1686 ny = ROW_HEIGHT*(nearrow+1)+bb->compress*ROW_HEIGHT;
1687 if((x-nx)*(x-nx)+(y-ny)*(y-ny) < MIN_DISTANCE) return true;
1692 if(nearcol+adj >= 0) {
1693 if(nearrow-1 >= 0) {
1694 if(bb->playboard[nearrow-1][nearcol+adj].type >= 0) {
1695 nx = XOFS+((nearrow-1)%2 ? ROW_INDENT : 0)+
1696 BUBBLE_WIDTH*(nearcol+adj);
1697 ny = ROW_HEIGHT*(nearrow-1)+bb->compress*ROW_HEIGHT;
1698 if((x-nx)*(x-nx)+(y-ny)*(y-ny) < MIN_DISTANCE) return true;
1702 if(nearrow+1 < BB_HEIGHT) {
1703 if(bb->playboard[nearrow+1][nearcol+adj].type >= 0) {
1704 nx = XOFS+((nearrow+1)%2 ? ROW_INDENT : 0)+
1705 BUBBLE_WIDTH*(nearcol+adj);
1706 ny = ROW_HEIGHT*(nearrow+1)+bb->compress*ROW_HEIGHT;
1707 if((x-nx)*(x-nx)+(y-ny)*(y-ny) < MIN_DISTANCE) return true;
1712 if(nearcol+1 < BB_WIDTH-adj) {
1713 if(bb->playboard[nearrow][nearcol+1].type >= 0) {
1714 nx = XOFS+(nearrow%2 ? ROW_INDENT : 0)+BUBBLE_WIDTH*(nearcol+1);
1715 ny = ROW_HEIGHT*nearrow+bb->compress*ROW_HEIGHT;
1716 if((x-nx)*(x-nx)+(y-ny)*(y-ny) < MIN_DISTANCE) return true;
1720 return false;
1723 /*****************************************************************************
1724 * bubbles_ingroup() marks all bubbles that form the current group.
1725 ******************************************************************************/
1726 static bool bubbles_ingroup(struct game_context* bb, int row, int col) {
1727 int i, j;
1728 int count;
1730 count = bubbles_searchgroup(bb, row, col);
1732 /* unmark group if too small */
1733 if(count < 3) {
1734 for(i=0; i<BB_HEIGHT; i++) {
1735 for(j=0; j<BB_WIDTH; j++) {
1736 bb->playboard[i][j].ingroup = false;
1740 return false;
1743 return true;
1746 /*****************************************************************************
1747 * bubbles_searchgroup() return the size of the group of bubbles of the same
1748 * type that the current bubble belongs to.
1749 ******************************************************************************/
1750 static int bubbles_searchgroup(struct game_context* bb, int row, int col) {
1751 int i, adj;
1752 int myrow, mycol, mytype;
1753 int count = 0;
1755 struct coord {
1756 int row;
1757 int col;
1758 } search[(2*BB_WIDTH-1)*(BB_HEIGHT/2)];
1760 /* search initial bubble */
1761 bb->playboard[row][col].ingroup = true;
1762 search[count].row = row;
1763 search[count].col = col;
1764 count++;
1766 /* breadth-first search neighbors */
1767 for(i=0; i<count; i++) {
1768 myrow = search[i].row;
1769 mycol = search[i].col;
1770 mytype = bb->playboard[myrow][mycol].type;
1771 adj = myrow%2;
1773 if(mycol-1 >= 0) {
1774 if(bb->playboard[myrow][mycol-1].type == mytype &&
1775 !bb->playboard[myrow][mycol-1].ingroup) {
1776 bb->playboard[myrow][mycol-1].ingroup = true;
1777 search[count].row = myrow;
1778 search[count].col = mycol-1;
1779 count++;
1783 if(mycol-1+adj >= 0) {
1784 if(myrow-1 >= 0) {
1785 if(bb->playboard[myrow-1][mycol-1+adj].type == mytype &&
1786 !bb->playboard[myrow-1][mycol-1+adj].ingroup) {
1787 bb->playboard[myrow-1][mycol-1+adj].ingroup = true;
1788 search[count].row = myrow-1;
1789 search[count].col = mycol-1+adj;
1790 count++;
1794 if(myrow+1 < BB_HEIGHT) {
1795 if(bb->playboard[myrow+1][mycol-1+adj].type == mytype &&
1796 !bb->playboard[myrow+1][mycol-1+adj].ingroup) {
1797 bb->playboard[myrow+1][mycol-1+adj].ingroup = true;
1798 search[count].row = myrow+1;
1799 search[count].col = mycol-1+adj;
1800 count++;
1805 if(mycol+adj >= 0) {
1806 if(myrow-1 >= 0) {
1807 if(bb->playboard[myrow-1][mycol+adj].type == mytype &&
1808 !bb->playboard[myrow-1][mycol+adj].ingroup) {
1809 bb->playboard[myrow-1][mycol+adj].ingroup = true;
1810 search[count].row = myrow-1;
1811 search[count].col = mycol+adj;
1812 count++;
1816 if(myrow+1 < BB_HEIGHT) {
1817 if(bb->playboard[myrow+1][mycol+adj].type == mytype &&
1818 !bb->playboard[myrow+1][mycol+adj].ingroup) {
1819 bb->playboard[myrow+1][mycol+adj].ingroup = true;
1820 search[count].row = myrow+1;
1821 search[count].col = mycol+adj;
1822 count++;
1827 if(mycol+1 < BB_WIDTH-adj) {
1828 if(bb->playboard[myrow][mycol+1].type == mytype &&
1829 !bb->playboard[myrow][mycol+1].ingroup) {
1830 bb->playboard[myrow][mycol+1].ingroup = true;
1831 search[count].row = myrow;
1832 search[count].col = mycol+1;
1833 count++;
1838 return count;
1841 /*****************************************************************************
1842 * bubbles_remove() removes all bubbles in the current group and all
1843 * unanchored bubbles from the play board.
1844 ******************************************************************************/
1845 static int bubbles_remove(struct game_context* bb) {
1846 int i, j;
1847 int buttonres;
1849 /* determine all anchored bubbles */
1850 for(j=0; j<BB_WIDTH; j++) {
1851 if(bb->playboard[0][j].type >= 0 && !bb->playboard[0][j].ingroup) {
1852 bubbles_anchored(bb, 0, j);
1856 /* mark bubbles to be deleted */
1857 for(i=0; i<BB_HEIGHT; i++) {
1858 for(j=0; j<BB_WIDTH; j++) {
1859 if(bb->playboard[i][j].type >= 0 &&
1860 (!bb->playboard[i][j].anchored || bb->playboard[i][j].ingroup)) {
1861 bb->playboard[i][j].delete = true;
1866 /* animate falling bubbles */
1867 buttonres = bubbles_fall(bb);
1868 if(buttonres != BB_NONE) return buttonres;
1870 /* remove bubbles */
1871 for(i=0; i<BB_HEIGHT; i++) {
1872 for(j=0; j<BB_WIDTH; j++) {
1873 if(bb->playboard[i][j].delete) {
1874 bb->playboard[i][j].ingroup = false;
1875 bb->playboard[i][j].type = -1;
1876 bb->playboard[i][j].delete = false;
1877 } else {
1878 bb->playboard[i][j].anchored = false;
1883 bubbles_getonboard(bb);
1885 return BB_NONE;
1888 /*****************************************************************************
1889 * bubbles_anchored() marks all bubbles that are anchored in some way to the
1890 * current bubble.
1891 ******************************************************************************/
1892 static void bubbles_anchored(struct game_context* bb, int row, int col) {
1893 int i, adj;
1894 int myrow, mycol, mytype;
1895 int count = 0;
1897 struct coord {
1898 int row;
1899 int col;
1900 } search[(2*BB_WIDTH-1)*(BB_HEIGHT/2)];
1902 /* search initial bubble */
1903 bb->playboard[row][col].anchored = true;
1904 search[count].row = row;
1905 search[count].col = col;
1906 count++;
1908 /* breadth-first search neighbors */
1909 for(i=0; i<count; i++) {
1910 myrow = search[i].row;
1911 mycol = search[i].col;
1912 mytype = bb->playboard[myrow][mycol].type;
1913 adj = myrow%2;
1915 if(mycol-1 >= 0) {
1916 if(bb->playboard[myrow][mycol-1].type >= 0 &&
1917 !bb->playboard[myrow][mycol-1].ingroup &&
1918 !bb->playboard[myrow][mycol-1].anchored) {
1919 bb->playboard[myrow][mycol-1].anchored = true;
1920 search[count].row = myrow;
1921 search[count].col = mycol-1;
1922 count++;
1926 if(mycol-1+adj >= 0) {
1927 if(myrow-1 >= 0) {
1928 if(bb->playboard[myrow-1][mycol-1+adj].type >= 0 &&
1929 !bb->playboard[myrow-1][mycol-1+adj].ingroup &&
1930 !bb->playboard[myrow-1][mycol-1+adj].anchored) {
1931 bb->playboard[myrow-1][mycol-1+adj].anchored = true;
1932 search[count].row = myrow-1;
1933 search[count].col = mycol-1+adj;
1934 count++;
1938 if(myrow+1 < BB_HEIGHT) {
1939 if(bb->playboard[myrow+1][mycol-1+adj].type >= 0 &&
1940 !bb->playboard[myrow+1][mycol-1+adj].ingroup &&
1941 !bb->playboard[myrow+1][mycol-1+adj].anchored) {
1942 bb->playboard[myrow+1][mycol-1+adj].anchored = true;
1943 search[count].row = myrow+1;
1944 search[count].col = mycol-1+adj;
1945 count++;
1950 if(mycol+adj >= 0) {
1951 if(myrow-1 >= 0) {
1952 if(bb->playboard[myrow-1][mycol+adj].type >= 0 &&
1953 !bb->playboard[myrow-1][mycol+adj].ingroup &&
1954 !bb->playboard[myrow-1][mycol+adj].anchored) {
1955 bb->playboard[myrow-1][mycol+adj].anchored = true;
1956 search[count].row = myrow-1;
1957 search[count].col = mycol+adj;
1958 count++;
1962 if(myrow+1 < BB_HEIGHT) {
1963 if(bb->playboard[myrow+1][mycol+adj].type >= 0 &&
1964 !bb->playboard[myrow+1][mycol+adj].ingroup &&
1965 !bb->playboard[myrow+1][mycol+adj].anchored) {
1966 bb->playboard[myrow+1][mycol+adj].anchored = true;
1967 search[count].row = myrow+1;
1968 search[count].col = mycol+adj;
1969 count++;
1974 if(mycol+1 < BB_WIDTH-adj) {
1975 if(bb->playboard[myrow][mycol+1].type >= 0 &&
1976 !bb->playboard[myrow][mycol+1].ingroup &&
1977 !bb->playboard[myrow][mycol+1].anchored) {
1978 bb->playboard[myrow][mycol+1].anchored = true;
1979 search[count].row = myrow;
1980 search[count].col = mycol+1;
1981 count++;
1987 /*****************************************************************************
1988 * bubbles_fall() makes removed bubbles fall from the screen.
1989 ******************************************************************************/
1990 static int bubbles_fall(struct game_context* bb) {
1991 int i, j;
1992 int count;
1993 int indent;
1994 int xofs, yofs;
1995 int buttonres;
1996 bool onscreen;
1997 long lasttick, currenttick;
1999 /* give all falling bubbles an x axis movement */
2000 for(i=0; i<BB_HEIGHT; i++) {
2001 for(j=0; j<BB_WIDTH; j++) {
2002 if(bb->playboard[i][j].delete) {
2003 bb->playboard[i][j].fallx = rb->rand()%25 - 12;
2004 bb->playboard[i][j].fallvel = rb->rand()%5 + 6;
2009 /* draw bubbles falling off the screen
2010 * follows y=x^2-8x scaled to bubble size
2012 lasttick = *rb->current_tick;
2014 for(count=1; ;count++) {
2015 onscreen = false;
2016 bubbles_drawboard(bb);
2018 for(i=0; i<BB_HEIGHT; i++) {
2019 for(j=0; j<BB_WIDTH; j++) {
2020 if(bb->playboard[i][j].delete) {
2021 indent = (i%2 ? ROW_INDENT : 0);
2022 xofs = ((bb->playboard[i][j].fallx*count)*BUBBLE_WIDTH)/48;
2023 yofs = ((count*count - bb->playboard[i][j].fallvel*count)*
2024 BUBBLE_HEIGHT)/20;
2026 /* draw bubble if it is still on the screen */
2027 if(ROW_HEIGHT*i+bb->compress*ROW_HEIGHT+yofs
2028 <= LCD_HEIGHT) {
2029 onscreen = true;
2031 rb->lcd_bitmap_part(bubbles_emblem, 0,
2032 EMBLEM_HEIGHT*bb->playboard[i][j].type, EMBLEM_WIDTH,
2033 XOFS+indent+BUBBLE_WIDTH*j+
2034 (BUBBLE_WIDTH-EMBLEM_WIDTH)/2+xofs,
2035 ROW_HEIGHT*i+(BUBBLE_HEIGHT-EMBLEM_HEIGHT)/2+
2036 bb->compress*ROW_HEIGHT+yofs,
2037 EMBLEM_WIDTH, EMBLEM_HEIGHT);
2038 rb->lcd_set_drawmode(DRMODE_FG);
2039 rb->lcd_mono_bitmap(
2040 (const unsigned char *)bubbles_bubble,
2041 XOFS+indent+BUBBLE_WIDTH*j+xofs,
2042 ROW_HEIGHT*i+bb->compress*ROW_HEIGHT+yofs,
2043 BUBBLE_WIDTH, BUBBLE_HEIGHT);
2044 rb->lcd_set_drawmode(DRMODE_SOLID);
2050 rb->lcd_update();
2052 /* break out if all bubbles are off the screen */
2053 if(!onscreen) break;
2055 /* handle button events */
2056 buttonres = bubbles_handlebuttons(bb, true, 0);
2057 if(buttonres != BB_NONE) return buttonres;
2059 /* framerate limiting */
2060 currenttick = *rb->current_tick;
2061 if(currenttick-lasttick < HZ/MAX_FPS) {
2062 rb->sleep((HZ/MAX_FPS)-(currenttick-lasttick));
2063 } else {
2064 rb->yield();
2066 lasttick = currenttick;
2069 return BB_NONE;
2072 /*****************************************************************************
2073 * bubbles_checklevel() checks the state of the playboard for a win or loss.
2074 ******************************************************************************/
2075 static int bubbles_checklevel(struct game_context* bb) {
2076 int i, j;
2077 int points;
2078 char str[13];
2080 bubbles_drawboard(bb);
2081 rb->lcd_update();
2083 /* check for bubbles below cut off point */
2084 for(i=0; i<=bb->compress; i++) {
2085 for(j=0; j<BB_WIDTH; j++) {
2086 if(bb->playboard[BB_HEIGHT-1-i][j].type >= 0) return BB_LOSE;
2090 /* check for bubbles above cut off point */
2091 for(i=0; i<BB_HEIGHT-1-bb->compress; i++) {
2092 for(j=0; j<BB_WIDTH; j++) {
2093 if(bb->playboard[i][j].type >= 0) return BB_NONE;
2097 /* level complete, record score */
2098 points = 100 - bb->elapsedlvl/100;
2099 if(points > 0) {
2100 bb->score += points;
2101 } else {
2102 points = 0;
2105 rb->snprintf(str, 12, "%d points", points);
2106 rb->splash(HZ, str);
2108 /* advance to the next level */
2109 if(!bubbles_nextlevel(bb)) {
2110 return BB_WIN;
2113 bubbles_drawboard(bb);
2114 rb->lcd_update();
2115 rb->snprintf(str, 12, "Level %d", bb->level);
2116 rb->splash(HZ, str);
2117 bubbles_drawboard(bb);
2118 rb->lcd_update();
2120 return BB_NONE;
2123 /*****************************************************************************
2124 * bubbles_recordscore() inserts a high score into the high scores list and
2125 * returns the high score position.
2126 ******************************************************************************/
2127 static int bubbles_recordscore(struct game_context* bb) {
2128 int i;
2129 int position = 0;
2130 unsigned int currentscore, currentlevel;
2131 unsigned int tempscore, templevel;
2133 if(bb->score > 0) {
2134 currentlevel = bb->level-1;
2135 currentscore = bb->score;
2137 for(i=0; i<NUM_SCORES; i++) {
2138 if(currentscore >= bb->highscores[i].score) {
2139 if(!position) {
2140 position = i+1;
2141 bb->dirty = true;
2143 templevel = bb->highscores[i].level;
2144 tempscore = bb->highscores[i].score;
2145 bb->highscores[i].level = currentlevel;
2146 bb->highscores[i].score = currentscore;
2147 currentlevel = templevel;
2148 currentscore = tempscore;
2153 return position;
2156 /*****************************************************************************
2157 * bubbles_loadscores() loads the high scores saved file.
2158 ******************************************************************************/
2159 static void bubbles_loadscores(struct game_context* bb) {
2160 int fd;
2162 bb->dirty = false;
2164 /* clear high scores */
2165 bb->highlevel = 0;
2166 rb->memset(bb->highscores, 0, sizeof(bb->highscores));
2168 /* open scores file */
2169 fd = rb->open(SCORE_FILE, O_RDONLY);
2170 if(fd < 0) return;
2172 /* read in high scores */
2173 rb->read(fd, &bb->highlevel, sizeof(bb->highlevel));
2174 if(rb->read(fd, bb->highscores, sizeof(bb->highscores)) <= 0) {
2175 /* scores are bad, reset */
2176 rb->memset(bb->highscores, 0, sizeof(bb->highscores));
2179 if( bb->highlevel >= NUM_LEVELS )
2180 bb->highlevel = NUM_LEVELS - 1;
2182 rb->close(fd);
2185 /*****************************************************************************
2186 * bubbles_savescores() saves the high scores saved file.
2187 ******************************************************************************/
2188 static void bubbles_savescores(struct game_context* bb) {
2189 int fd;
2191 /* write out the high scores to the save file */
2192 fd = rb->open(SCORE_FILE, O_WRONLY|O_CREAT);
2193 rb->write(fd, &bb->highlevel, sizeof(bb->highlevel));
2194 rb->write(fd, bb->highscores, sizeof(bb->highscores));
2195 rb->close(fd);
2196 bb->dirty = false;
2199 /*****************************************************************************
2200 * bubbles_displaycores() displays the high scores
2201 ******************************************************************************/
2202 static char * scores_get_name(int selected_item, void * data,
2203 char * buffer, size_t buffer_len)
2205 struct game_context* bb = (struct game_context*)data;
2206 rb->snprintf(buffer, buffer_len, "#%02d: %d, Lvl %d",
2207 selected_item+1,
2208 bb->highscores[selected_item].score,
2209 bb->highscores[selected_item].level);
2210 return buffer;
2212 static void bubbles_displayscores(struct game_context* bb) {
2213 struct simplelist_info info;
2214 rb->simplelist_info_init(&info, "High Scores", NUM_SCORES, (void*)bb);
2215 info.hide_selection = true;
2216 info.get_name = scores_get_name;
2217 rb->simplelist_show_list(&info);
2221 /*****************************************************************************
2222 * bubbles_loadgame() loads the saved game and returns load success.
2223 ******************************************************************************/
2224 static bool bubbles_loadgame(struct game_context* bb) {
2225 int fd;
2226 bool loaded = false;
2228 /* open game file */
2229 fd = rb->open(SAVE_FILE, O_RDONLY);
2230 if(fd < 0) return loaded;
2232 /* read in saved game */
2233 while(true) {
2234 if(rb->read(fd, &bb->score, sizeof(bb->score)) <= 0) break;
2235 if(rb->read(fd, &bb->level, sizeof(bb->level)) <= 0) break;
2236 if(rb->read(fd, &bb->angle, sizeof(bb->angle)) <= 0) break;
2237 if(rb->read(fd, &bb->shots, sizeof(bb->shots)) <= 0) break;
2238 if(rb->read(fd, &bb->compress, sizeof(bb->compress)) <= 0) break;
2239 if(rb->read(fd, &bb->onboardcnt, sizeof(bb->onboardcnt)) <= 0) break;
2240 if(rb->read(fd, bb->onboard, sizeof(bb->onboard)) <= 0) break;
2241 if(rb->read(fd, &bb->nextinq, sizeof(bb->nextinq)) <= 0) break;
2242 if(rb->read(fd, bb->queue, sizeof(bb->queue)) <= 0) break;
2243 if(rb->read(fd, &bb->elapsedlvl, sizeof(bb->elapsedlvl)) <= 0) break;
2244 if(rb->read(fd, bb->playboard, sizeof(bb->playboard)) <= 0) break;
2245 bb->resume = true;
2246 loaded = true;
2247 break;
2250 rb->close(fd);
2252 /* delete saved file */
2253 rb->remove(SAVE_FILE);
2254 return loaded;
2257 /*****************************************************************************
2258 * bubbles_savegame() saves the current game state.
2259 ******************************************************************************/
2260 static void bubbles_savegame(struct game_context* bb) {
2261 int fd;
2263 /* write out the game state to the save file */
2264 fd = rb->open(SAVE_FILE, O_WRONLY|O_CREAT);
2265 rb->write(fd, &bb->score, sizeof(bb->score));
2266 rb->write(fd, &bb->level, sizeof(bb->level));
2267 rb->write(fd, &bb->angle, sizeof(bb->angle));
2268 rb->write(fd, &bb->shots, sizeof(bb->shots));
2269 rb->write(fd, &bb->compress, sizeof(bb->compress));
2270 rb->write(fd, &bb->onboardcnt, sizeof(bb->onboardcnt));
2271 rb->write(fd, bb->onboard, sizeof(bb->onboard));
2272 rb->write(fd, &bb->nextinq, sizeof(bb->nextinq));
2273 rb->write(fd, bb->queue, sizeof(bb->queue));
2274 rb->write(fd, &bb->elapsedlvl, sizeof(bb->elapsedlvl));
2275 rb->write(fd, bb->playboard, sizeof(bb->playboard));
2276 rb->close(fd);
2278 bb->resume = true;
2281 /*****************************************************************************
2282 * bubbles_setcolors() set the foreground and background colors.
2283 ******************************************************************************/
2284 static inline void bubbles_setcolors(void) {
2285 #ifdef HAVE_LCD_COLOR
2286 rb->lcd_set_background(LCD_RGBPACK(181,181,222));
2287 rb->lcd_set_foreground(LCD_BLACK);
2288 #endif
2291 /*****************************************************************************
2292 * bubbles_callback() is the default event handler callback which is called
2293 * on usb connect and shutdown.
2294 ******************************************************************************/
2295 static void bubbles_callback(void* param) {
2296 struct game_context* bb = (struct game_context*) param;
2297 if(bb->dirty) {
2298 rb->splash(HZ/2, "Saving high scores...");
2299 bubbles_savescores(bb);
2303 /*****************************************************************************
2304 * bubbles_handlebuttons() handles button events during a game.
2305 ******************************************************************************/
2306 static int bubbles_handlebuttons(struct game_context* bb, bool animblock,
2307 int timeout) {
2308 int button;
2309 int buttonres;
2310 long start;
2311 const struct button_mapping *plugin_contexts[]
2312 #if CONFIG_KEYPAD != SANSA_E200_PAD
2313 = {generic_left_right_fire,generic_actions};
2314 #else
2315 = {generic_directions,generic_actions};
2316 #endif
2318 if (timeout < 0)
2319 timeout = 0;
2320 button = pluginlib_getaction(rb,timeout,plugin_contexts,2);
2321 #if defined(HAS_BUTTON_HOLD) && !defined(HAVE_REMOTE_LCD_AS_MAIN)
2322 /* FIXME: Should probably check remote hold here */
2323 if (rb->button_hold())
2324 button = BUBBLES_START;
2325 #endif
2327 switch(button){
2328 case BUBBLES_LEFT_REP:
2329 if(bb->angle > MIN_ANGLE) bb->angle -= ANGLE_STEP_REP;
2330 case BUBBLES_LEFT: /* change angle to the left */
2331 if(bb->angle > MIN_ANGLE) bb->angle -= ANGLE_STEP;
2332 break;
2334 case BUBBLES_RIGHT_REP:
2335 if(bb->angle < MAX_ANGLE) bb->angle += ANGLE_STEP_REP;
2336 case BUBBLES_RIGHT: /* change angle to the right */
2337 if(bb->angle < MAX_ANGLE) bb->angle += ANGLE_STEP;
2338 break;
2340 case BUBBLES_SELECT: /* fire the shot */
2341 if(!animblock) {
2342 bb->elapsedlvl += bb->elapsedshot;
2343 bb->elapsedshot = 0;
2344 buttonres = bubbles_fire(bb);
2345 if(buttonres != BB_NONE) return buttonres;
2346 buttonres = bubbles_checklevel(bb);
2347 if(buttonres != BB_NONE) return buttonres;
2348 bb->startedshot = *rb->current_tick;
2350 break;
2352 case BUBBLES_START: /* pause the game */
2353 start = *rb->current_tick;
2354 rb->splash(0, "Paused");
2355 while(pluginlib_getaction(rb,TIMEOUT_BLOCK,plugin_contexts,2)
2356 != (BUBBLES_START));
2357 bb->startedshot += *rb->current_tick-start;
2358 bubbles_drawboard(bb);
2359 rb->lcd_update();
2360 break;
2362 case BUBBLES_RESUME: /* save and end the game */
2363 if(!animblock) {
2364 rb->splash(HZ/2, "Saving game...");
2365 bubbles_savegame(bb);
2366 return BB_END;
2368 break;
2369 case BUBBLES_QUIT: /* end the game */
2370 return BB_END;
2372 case ACTION_UNKNOWN:
2373 case ACTION_NONE: /* no button pressed */
2374 break;
2376 default:
2377 if(rb->default_event_handler_ex(button, bubbles_callback,
2378 (void*) bb) == SYS_USB_CONNECTED)
2379 return BB_USB;
2380 break;
2383 return BB_NONE;
2386 /*****************************************************************************
2387 * bubbles() is the main game subroutine, it returns the final game status.
2388 ******************************************************************************/
2389 static int bubbles(struct game_context* bb) {
2390 int buttonres;
2391 unsigned int startlevel = 0;
2392 bool startgame = false;
2393 long timeout;
2395 bubbles_setcolors();
2397 /* don't resume by default */
2398 bb->resume = false;
2400 /********************
2401 * menu *
2402 ********************/
2403 MENUITEM_STRINGLIST(menu,"Bubbles Menu",NULL,
2404 "Start New Game", "Resume Game",
2405 "Level", "Display High Scores", "Quit");
2406 while(!startgame){
2407 switch (rb->do_menu(&menu, NULL, NULL, false))
2409 case 0: /* new game */
2410 bb->level = startlevel;
2411 startgame = true;
2412 break;
2413 case 1: /* resume game */
2414 if(!bubbles_loadgame(bb)) {
2415 rb->splash(HZ*2, "Nothing to resume");
2416 } else {
2417 startgame = true;
2419 break;
2420 case 2: /* choose level */
2421 startlevel++;
2422 rb->set_int("Choose start level", "", UNIT_INT, &startlevel, NULL, 1, 1, bb->highlevel+1, NULL);
2423 startlevel--;
2424 break;
2425 case 3: /* High scores */
2426 bubbles_displayscores(bb);
2427 break;
2428 case 4: /* quit */
2429 return BB_QUIT;
2430 case MENU_ATTACHED_USB:
2431 bubbles_callback(bb);
2432 return BB_USB;
2435 /********************
2436 * init *
2437 ********************/
2438 bubbles_init(bb);
2439 bubbles_drawboard(bb);
2440 rb->lcd_update();
2442 /**********************
2443 * play *
2444 **********************/
2445 bb->startedshot = *rb->current_tick;
2447 while(true) {
2448 /* refresh the board */
2449 bubbles_drawboard(bb);
2450 rb->lcd_update();
2452 /* manange idle framerate */
2453 bb->elapsedshot = *rb->current_tick-bb->startedshot;
2455 if(MAX_SHOTTIME-bb->elapsedshot < HZ/2) {
2456 timeout = MAX_SHOTTIME-bb->elapsedshot;
2457 } else {
2458 timeout = HZ/2;
2461 /* handle button events */
2462 buttonres = bubbles_handlebuttons(bb, false, timeout);
2463 if(buttonres != BB_NONE) return buttonres;
2465 /* handle timing */
2466 bb->elapsedshot = *rb->current_tick-bb->startedshot;
2468 if(bb->elapsedshot > MAX_SHOTTIME) {
2469 bb->elapsedlvl += bb->elapsedshot;
2470 bb->elapsedshot = 0;
2471 buttonres = bubbles_fire(bb);
2472 if(buttonres != BB_NONE) return buttonres;
2473 buttonres = bubbles_checklevel(bb);
2474 if(buttonres != BB_NONE) return buttonres;
2475 bb->startedshot = *rb->current_tick;
2480 /*****************************************************************************
2481 * plugin entry point.
2482 ******************************************************************************/
2483 enum plugin_status plugin_start(const struct plugin_api* api, const void* parameter) {
2484 struct game_context bb;
2485 bool exit = false;
2486 int position;
2488 /* plugin init */
2489 (void)parameter;
2490 rb = api;
2491 /* end of plugin init */
2493 /* more init */
2494 xlcd_init(rb);
2496 /* load files */
2497 rb->splash(0, "Loading...");
2498 bubbles_loadscores(&bb);
2499 rb->lcd_clear_display();
2501 /* start app */
2502 #if LCD_DEPTH > 1
2503 rb->lcd_set_backdrop(NULL);
2504 #endif
2505 rb->lcd_setfont(FONT_SYSFIXED);
2507 while(!exit) {
2508 switch(bubbles(&bb)){
2509 case BB_WIN:
2510 rb->splash(HZ*2, "You Win!");
2511 /* record high level */
2512 if( NUM_LEVELS-1 > bb.highlevel) {
2513 bb.highlevel = NUM_LEVELS-1;
2514 bb.dirty = true;
2517 /* record high score */
2518 if((position = bubbles_recordscore(&bb))) {
2519 rb->splashf(HZ*2, "New high score #%d!", position);
2521 break;
2523 case BB_LOSE:
2524 rb->splash(HZ*2, "Game Over");
2525 /* fall through to BB_END */
2527 case BB_END:
2528 if(!bb.resume) {
2529 /* record high level */
2530 if(bb.level-1 > bb.highlevel) {
2531 bb.highlevel = bb.level-1;
2532 bb.dirty = true;
2535 /* record high score */
2536 if((position = bubbles_recordscore(&bb))) {
2537 rb->splashf(HZ*2, "New high score #%d!", position);
2540 break;
2542 case BB_USB:
2543 rb->lcd_setfont(FONT_UI);
2544 return PLUGIN_USB_CONNECTED;
2546 case BB_QUIT:
2547 if(bb.dirty) {
2548 rb->splash(HZ/2, "Saving high scores...");
2549 bubbles_savescores(&bb);
2551 exit = true;
2552 break;
2554 default:
2555 break;
2559 rb->lcd_setfont(FONT_UI);
2560 return PLUGIN_OK;
2563 #endif