Prepare new maemo release
[maemo-rb.git] / apps / plugins / bubbles.c
blobeef4f4dc196d28ed877cbb0a830e5edce34873c8
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 #include "lib/xlcd.h"
27 #include "lib/pluginlib_actions.h"
28 #include "lib/fixedpoint.h"
29 #include "lib/playback_control.h"
30 #include "lib/highscore.h"
32 /* files */
33 #define SCORE_FILE PLUGIN_GAMES_DATA_DIR "/bubbles.score"
34 #define SAVE_FILE PLUGIN_GAMES_DATA_DIR "/bubbles.save"
35 #define DATA_FILE PLUGIN_GAMES_DATA_DIR "/bubbles.data"
37 /* final game return status */
38 enum {
39 BB_LOSE,
40 BB_QUIT_WITHOUT_SAVING,
41 BB_QUIT,
42 BB_USB,
43 BB_END,
44 BB_WIN,
45 BB_NONE,
48 /* play board dimension */
49 #define BB_HEIGHT 12
50 #define BB_WIDTH 8
51 #define BB_LEVEL_HEIGHT 10
53 /* various amounts */
54 #define NUM_SCORES 5
55 #define NUM_LEVELS 100
56 #define NUM_QUEUE 2
57 #define NUM_BUBBLES 8
58 #define MIN_ANGLE -76
59 #define MAX_ANGLE 76
60 #define NUM_COMPRESS 9
61 #define MAX_SHOTTIME 1000
63 /* keyboard layouts */
65 #ifdef HAVE_SCROLLWHEEL
66 /* sansas use the wheel instead of left/right if available */
67 #define BUBBLES_LEFT PLA_SCROLL_BACK
68 #define BUBBLES_LEFT_REP PLA_SCROLL_BACK_REPEAT
69 #define BUBBLES_RIGHT PLA_SCROLL_FWD
70 #define BUBBLES_RIGHT_REP PLA_SCROLL_FWD_REPEAT
71 #else
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 #endif
78 #define ANGLE_STEP 2
79 #define ANGLE_STEP_REP 4
81 #define BUBBLES_QUIT1 PLA_EXIT
82 #define BUBBLES_QUIT2 PLA_CANCEL
84 /* these are better off shooting with up */
85 #if (CONFIG_KEYPAD == SAMSUNG_YH_PAD) \
86 || (CONFIG_KEYPAD == ONDIO_PAD) \
87 || (CONFIG_KEYPAD == IRIVER_H10_PAD)
88 #define SHOOT_WITH_UP
89 #endif
91 #ifdef SHOOT_WITH_UP
92 #define BUBBLES_FIRE PLA_UP
93 #define BUBBLES_FIRE_REPEAT PLA_UP_REPEAT
94 #define BUBBLES_PAUSE PLA_SELECT
95 #else
96 #define BUBBLES_FIRE PLA_SELECT
97 #define BUBBLES_FIRE_REPEAT PLA_SELECT_REPEAT
98 #define BUBBLES_PAUSE PLA_UP
99 #endif
101 /* external bitmaps */
102 #ifdef HAVE_LCD_COLOR
103 #include "pluginbitmaps/bubbles_background.h"
104 #endif
105 #include "pluginbitmaps/bubbles_bubble.h"
106 #include "pluginbitmaps/bubbles_emblem.h"
108 #define BUBBLE_WIDTH BMPWIDTH_bubbles_bubble
109 #define BUBBLE_HEIGHT BMPHEIGHT_bubbles_bubble
110 #define EMBLEM_WIDTH BMPWIDTH_bubbles_emblem
111 #define EMBLEM_HEIGHT (BMPHEIGHT_bubbles_emblem/8)
113 /* bubbles will consume height of ROW_HEIGHT*(BB_HEIGHT-1)+BUBBLE_HEIGHT*3/2 */
114 /* 44x44 bubbles (m:robe 500) */
115 #if (LCD_WIDTH == 640) && (LCD_HEIGHT == 480)
116 #define XOFS 144
117 #define MAX_FPS 40
119 #elif (LCD_WIDTH == 480) && (LCD_HEIGHT == 640)
120 #define XOFS 128
121 #define MAX_FPS 40
123 /* 22x22 bubbles (iPod Video) */
124 #elif (LCD_HEIGHT == 240) && (LCD_WIDTH == 320)
125 #define XOFS 72
126 #define MAX_FPS 40
128 /* 22x22 bubbles (Gigabeat, Onda VX747) */
129 #elif ((LCD_HEIGHT == 320) || (LCD_HEIGHT == 400)) && (LCD_WIDTH == 240)
130 #define XOFS 64
131 #define MAX_FPS 30
133 /* 16x16 bubbles (H300, iPod Color, HDD6330) */
134 #elif (LCD_HEIGHT == 176) && (LCD_WIDTH == 220)
135 #define XOFS 46
136 #define MAX_FPS 30
138 /* 16x16 bubbles (Sansa E200) */
139 #elif (LCD_HEIGHT == 220) && (LCD_WIDTH == 176)
140 #define XOFS 24
141 #define MAX_FPS 30
142 #define YOFS 45
144 /* custom text positioning */
145 #define LEVEL_TXT_X 24
146 #define LEVEL_TXT_WIDTH 31
147 #define LEVEL_TXT_Y 5
148 #define SCORE_TXT_X 58
149 #define SCORE_TXT_WIDTH 31
150 #define SCORE_TXT_Y 5
151 #define NEXT_BB_X 112
152 #define NEXT_BB_WIDTH 31
153 #define NEXT_BB_Y 3
155 /* 12x12 bubbles (iPod Nano) */
156 #elif (LCD_HEIGHT == 132) && (LCD_WIDTH == 176)
157 #define XOFS 40
158 #define MAX_FPS 40
160 /* 12x12 bubbles (H100, H10, iAudio X5, HDD1630, iPod 3G, iPod 4G grayscale) */
161 #elif (LCD_HEIGHT == 128) && ((LCD_WIDTH == 160) || (LCD_WIDTH == 128))
162 #define XOFS 33
163 #define MAX_FPS 30
165 /* 12x12 bubbles (GoGear SA9200) */
166 #elif (LCD_HEIGHT == 160) && (LCD_WIDTH == 128)
167 #define XOFS 16
168 #define YOFS 32
169 #define ROW_HEIGHT 10
170 #define ROW_INDENT 6
171 #define MAX_FPS 30
173 /* custom text positioning */
174 #define LEVEL_TXT_X 2
175 #define LEVEL_TXT_WIDTH 31
176 #define LEVEL_TXT_Y 3
177 #define SCORE_TXT_X 34
178 #define SCORE_TXT_WIDTH 31
179 #define SCORE_TXT_Y 3
180 #define NEXT_BB_X 81
181 #define NEXT_BB_WIDTH 31
182 #define NEXT_BB_Y 2
184 /* 10x10 bubbles (iPod Mini) */
185 #elif (LCD_HEIGHT == 110) && (LCD_WIDTH == 138)
186 #define XOFS 33
187 #define MAX_FPS 30
189 /* 9x9 bubbles (iAudio M3) */
190 #elif (LCD_HEIGHT == 96) && (LCD_WIDTH == 128)
191 #define XOFS 45
192 #define MAX_FPS 30
194 /* 8x8 bubbles (Sansa C200) */
195 #elif ((LCD_HEIGHT == 80) && (LCD_WIDTH == 132))
196 #define XOFS 45
197 #define ROW_HEIGHT 6
198 #define MAX_FPS 30
200 /* 7x7 bubbles (Sansa Clip/m200) */
201 #elif (LCD_HEIGHT == 64 && LCD_WIDTH == 128)
202 #define XOFS 33
203 #define ROW_HEIGHT 5
204 #define MAX_FPS 30
206 /* 8x7 bubbles (Archos recorder, Ondio) */
207 #elif (LCD_HEIGHT == 64) && (LCD_WIDTH == 112)
208 #define XOFS 33
209 #define ROW_HEIGHT 5
210 #define MAX_FPS 20
212 /* 7x7 bubbles (Sansa Clip Zip) */
213 #elif (LCD_HEIGHT == 96 && LCD_WIDTH == 96)
214 #define XOFS 33
215 #define ROW_HEIGHT 5
216 #define MAX_FPS 30
218 /* custom text positioning */
219 #define LEVEL_TXT_X 1
220 #define LEVEL_TXT_WIDTH 31
221 #define LEVEL_TXT_Y 4
222 #define SCORE_TXT_X 1
223 #define SCORE_TXT_WIDTH 31
224 #define SCORE_TXT_Y 31
225 #define NEXT_BB_X 1
226 #define NEXT_BB_WIDTH 31
227 #define NEXT_BB_Y 72
229 #else
230 #error BUBBLES: Unsupported LCD type
231 #endif
233 #if !defined(ROW_HEIGHT)
234 #define ROW_HEIGHT (BUBBLE_WIDTH-(BUBBLE_WIDTH-EMBLEM_WIDTH)/2)
235 #endif
237 #if !defined(ROW_INDENT)
238 #define ROW_INDENT (BUBBLE_WIDTH/2)
239 #endif
241 #define TEXT_LINES (LCD_HEIGHT/8)
243 #ifndef YOFS
244 #define YOFS 0
245 #endif
247 /* shot position */
248 #define SHOTX XOFS+ROW_INDENT+BUBBLE_WIDTH*3
249 #define SHOTY (YOFS+ROW_HEIGHT*(BB_HEIGHT-1)+BUBBLE_HEIGHT/2)
251 /* collision distance squared */
252 #define MIN_DISTANCE ((BUBBLE_WIDTH*8)/10)*((BUBBLE_HEIGHT*8)/10)
254 /* levels */
255 char level[NUM_LEVELS][BB_LEVEL_HEIGHT][BB_WIDTH] = {
256 {{ 6, 6, 4, 4, 2, 2, 3, 3},
257 { 6, 6, 4, 4, 2, 2, 3, -1},
258 { 2, 2, 3, 3, 6, 6, 4, 4},
259 { 2, 3, 3, 6, 6, 4, 4, -1},
260 {-1, -1, -1, -1, -1, -1, -1, -1},
261 {-1, -1, -1, -1, -1, -1, -1, -1},
262 {-1, -1, -1, -1, -1, -1, -1, -1},
263 {-1, -1, -1, -1, -1, -1, -1, -1},
264 {-1, -1, -1, -1, -1, -1, -1, -1},
265 {-1, -1, -1, -1, -1, -1, -1, -1}},
266 {{-1, 7, 7, 7, 7, 7, 7, -1},
267 {-1, 1, 1, 1, 1, 1, -1, -1},
268 {-1, -1, 2, 2, 2, 2, -1, -1},
269 {-1, -1, -1, 2, -1, -1, -1, -1},
270 {-1, -1, -1, 2, 2, -1, -1, -1},
271 {-1, -1, -1, 5, -1, -1, -1, -1},
272 {-1, -1, -1, 5, 5, -1, -1, -1},
273 {-1, -1, -1, -1, -1, -1, -1, -1},
274 {-1, -1, -1, -1, -1, -1, -1, -1},
275 {-1, -1, -1, -1, -1, -1, -1, -1}},
276 {{-1, -1, 7, -1, -1, 7, -1, -1},
277 {-1, -1, 7, 1, 7, -1, -1, -1},
278 {-1, -1, -1, 1, 2, -1, -1, -1},
279 {-1, -1, 1, 2, 1, -1, -1, -1},
280 {-1, -1, -1, 2, 5, -1, -1, -1},
281 {-1, -1, 3, 5, 3, -1, -1, -1},
282 {-1, -1, -1, 5, 3, -1, -1, -1},
283 {-1, -1, -1, 3, -1, -1, -1, -1},
284 {-1, -1, -1, -1, -1, -1, -1, -1},
285 {-1, -1, -1, -1, -1, -1, -1, -1}},
286 {{-1, -1, -1, 0, 0, -1, -1, -1},
287 {-1, -1, 5, 0, 1, -1, -1, -1},
288 {-1, -1, 3, 5, 1, 6, -1, -1},
289 {-1, 4, 3, -1, 6, 7, -1, -1},
290 {-1, 7, 4, -1, -1, 7, 4, -1},
291 { 6, 7, -1, -1, -1, 4, 3, -1},
292 { 1, 6, -1, -1, -1, -1, 3, 5},
293 { 1, -1, -1, -1, -1, -1, 5, -1},
294 {-1, -1, -1, -1, -1, -1, -1, -1},
295 {-1, -1, -1, -1, -1, -1, -1, -1}},
296 {{-1, -1, 0, 0, 0, 0, -1, -1},
297 {-1, 0, 1, 1, 1, 0, -1, -1},
298 {-1, 0, 1, 0, 0, 1, 0, -1},
299 {-1, 0, 1, 1, 1, 0, -1, -1},
300 {-1, -1, 0, 0, 0, 0, -1, -1},
301 {-1, -1, 7, -1, 7, -1, -1, -1},
302 {-1, -1, 7, 7, 7, 7, -1, -1},
303 {-1, -1, -1, -1, -1, -1, -1, -1},
304 {-1, -1, -1, -1, -1, -1, -1, -1},
305 {-1, -1, -1, -1, -1, -1, -1, -1}},
306 {{-1, 4, 4, 4, 6, 6, 6, -1},
307 { 4, -1, -1, -1, -1, -1, 6, -1},
308 {-1, 4, -1, -1, -1, -1, 6, -1},
309 { 4, 2, 3, 1, 2, 3, 6, -1},
310 {-1, 3, 1, 2, 3, 1, 2, -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, -1, -1, -1, -1, -1, -1, -1}},
316 {{-1, 4, 4, 4, 6, 6, 6, -1},
317 { 4, -1, -1, -1, -1, -1, 6, -1},
318 {-1, 4, -1, -1, -1, -1, 6, -1},
319 { 4, 2, 3, 1, 2, 3, 6, -1},
320 {-1, 3, 1, 2, 3, 1, 2, -1},
321 {-1, 2, 3, 1, 2, 3, -1, -1},
322 {-1, -1, -1, -1, -1, -1, -1, -1},
323 {-1, -1, -1, -1, -1, -1, -1, -1},
324 {-1, -1, -1, -1, -1, -1, -1, -1},
325 {-1, -1, -1, -1, -1, -1, -1, -1}},
326 {{-1, 0, 0, -1, -1, 2, 2, -1},
327 {-1, 5, -1, -1, -1, 3, -1, -1},
328 {-1, 0, -1, -1, -1, 6, -1, -1},
329 {-1, 3, -1, -1, -1, 0, -1, -1},
330 {-1, 4, -1, -1, -1, 5, -1, -1},
331 {-1, 2, -1, -1, -1, 3, -1, -1},
332 {-1, 2, -1, -1, -1, 1, -1, -1},
333 {-1, 3, -1, -1, -1, 4, -1, -1},
334 {-1, -1, -1, -1, -1, -1, -1, -1},
335 {-1, -1, -1, -1, -1, -1, -1, -1}},
336 {{ 3, -1, -1, -1, -1, -1, -1, 3},
337 { 6, 3, 2, 4, 6, 3, 2, -1},
338 { 4, -1, -1, -1, -1, -1, -1, 4},
339 { 2, 4, 6, 3, 2, 4, 6, -1},
340 {-1, -1, -1, 6, -1, -1, -1, -1},
341 {-1, -1, -1, 3, -1, -1, -1, -1},
342 {-1, -1, -1, -1, -1, -1, -1, -1},
343 {-1, -1, -1, -1, -1, -1, -1, -1},
344 {-1, -1, -1, -1, -1, -1, -1, -1},
345 {-1, -1, -1, -1, -1, -1, -1, -1}},
346 {{-1, 2, -1, 1, -1, 1, -1, 2},
347 { 1, 2, -1, 2, 1, -1, 1, -1},
348 { 1, -1, 1, -1, 2, -1, 2, -1},
349 { 2, 1, -1, 1, 2, -1, 2, -1},
350 {-1, 2, -1, 2, -1, 2, -1, 2},
351 { 1, 2, -1, 2, 1, -1, 1, -1},
352 { 1, -1, 1, -1, 2, -1, 1, -1},
353 { 2, 2, -1, 1, 1, -1, 2, -1},
354 {-1, 2, -1, 1, -1, 1, -1, 1},
355 {-1, -1, -1, -1, -1, -1, -1, -1}},
356 {{-1, 7, 7, -1, -1, 5, 5, -1},
357 { 1, -1, -1, -1, -1, -1, 4, -1},
358 { 2, 1, -1, -1, -1, -1, 4, 3},
359 { 2, -1, -1, -1, -1, -1, 3, -1},
360 { 1, 2, -1, -1, -1, -1, 3, 4},
361 { 1, -1, -1, -1, -1, -1, 4, -1},
362 { 7, 1, -1, -1, -1, -1, 4, 5},
363 { 7, 7, -1, -1, -1, 5, 5, -1},
364 {-1, -1, -1, -1, -1, -1, -1, -1},
365 {-1, -1, -1, -1, -1, -1, -1, -1}},
366 {{ 7, 7, -1, -1, -1, -1, 5, 5},
367 { 1, 5, -1, -1, -1, 7, 4, -1},
368 { 2, 1, -1, -1, -1, -1, 4, 3},
369 { 2, -1, -1, -1, -1, -1, 3, -1},
370 { 1, 5, -1, -1, -1, -1, 7, 4},
371 { 1, -1, -1, -1, -1, -1, 4, -1},
372 { 7, 1, -1, -1, -1, -1, 4, 5},
373 { 7, 5, -1, -1, -1, 7, 5, -1},
374 {-1, -1, -1, -1, -1, -1, -1, -1},
375 {-1, -1, -1, -1, -1, -1, -1, -1}},
376 {{-1, -1, -1, 0, 0, -1, -1, -1},
377 {-1, -1, 5, 0, 1, -1, -1, -1},
378 {-1, -1, 3, 5, 1, 6, -1, -1},
379 {-1, 4, 3, 2, 6, 2, -1, -1},
380 {-1, 7, 4, 7, 2, 2, 4, -1},
381 { 6, 7, 7, 3, 3, 4, 3, -1},
382 { 1, 6, 1, 1, 1, 3, 3, 5},
383 { 1, 1, -1, -1, -1, -1, 5, -1},
384 {-1, -1, -1, -1, -1, -1, -1, -1},
385 {-1, -1, -1, -1, -1, -1, -1, -1}},
386 {{-1, -1, 0, -1, -1, 0, -1, -1},
387 {-1, 3, 3, -1, 3, 3, -1, -1},
388 {-1, 0, 2, 0, 0, 2, 0, -1},
389 {-1, 3, 3, -1, 3, 3, -1, -1},
390 {-1, -1, 0, -1, -1, 0, -1, -1},
391 {-1, -1, -1, -1, -1, -1, -1, -1},
392 {-1, -1, -1, -1, -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, -1, -1, -1, -1, -1}},
396 {{-1, -1, -1, 1, 1, -1, -1, -1},
397 {-1, -1, 2, 2, 2, -1, -1, -1},
398 {-1, -1, 3, 3, 3, 3, -1, -1},
399 {-1, 4, 4, 4, 4, 4, -1, -1},
400 {-1, 5, 5, 5, 5, 5, 5, -1},
401 {-1, -1, -1, 6, -1, -1, -1, -1},
402 {-1, -1, -1, 7, 7, -1, -1, -1},
403 {-1, -1, -1, 0, -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, 2, 5, -1, -1, -1},
407 {-1, 4, 3, -1, -1, -1, -1, -1},
408 { 6, 7, -1, 5, 2, -1, -1, -1},
409 {-1, -1, -1, -1, 3, 4, -1, -1},
410 {-1, -1, -1, 2, 5, -1, 7, 6},
411 {-1, 4, 3, -1, -1, -1, -1, -1},
412 { 6, 7, -1, 5, 2, -1, -1, -1},
413 {-1, -1, -1, -1, 3, 4, -1, -1},
414 {-1, -1, -1, -1, -1, -1, 7, 6},
415 {-1, -1, -1, -1, -1, -1, -1, -1}},
416 {{-1, -1, -1, 5, 5, -1, -1, -1},
417 {-1, -1, -1, 3, -1, -1, -1, -1},
418 {-1, -1, -1, 1, -1, -1, -1, -1},
419 {-1, -1, -1, 7, -1, -1, -1, -1},
420 {-1, -1, -1, 2, -1, -1, -1, -1},
421 {-1, -1, -1, 4, -1, -1, -1, -1},
422 {-1, -1, -1, 5, -1, -1, -1, -1},
423 {-1, -1, -1, 3, -1, -1, -1, -1},
424 {-1, -1, -1, -1, -1, -1, -1, -1},
425 {-1, -1, -1, -1, -1, -1, -1, -1}},
426 {{-1, -1, -1, 0, 1, -1, -1, -1},
427 {-1, -1, 0, 2, 7, 7, -1, -1},
428 {-1, -1, -1, 0, 1, 7, -1, -1},
429 {-1, 0, 0, 0, 0, -1, -1, -1},
430 {-1, 0, 0, 0, 1, 1, -1, -1},
431 { 0, 0, 0, 1, 1, 1, -1, -1},
432 {-1, 0, 0, 1, 1, 1, -1, -1},
433 {-1, 0, 0, 0, 7, 7, -1, -1},
434 {-1, -1, 7, 7, -1, -1, -1, -1},
435 {-1, -1, -1, -1, -1, -1, -1, -1}},
436 {{-1, 1, -1, -1, -1, -1, -1, -1},
437 { 1, -1, -1, -1, -1, -1, -1, -1},
438 {-1, 2, 3, 4, 7, 6, 5, -1},
439 {-1, -1, -1, -1, -1, -1, 1, -1},
440 {-1, -1, -1, -1, -1, -1, 1, -1},
441 {-1, 2, 3, 4, 7, 6, -1, -1},
442 {-1, 1, -1, -1, -1, -1, -1, -1},
443 { 1, -1, -1, -1, -1, -1, -1, -1},
444 {-1, 2, 3, 4, 7, 6, 5, -1},
445 {-1, -1, -1, -1, -1, -1, -1, -1}},
446 {{-1, 6, -1, -1, -1, -1, -1, -1},
447 { 5, -1, -1, -1, -1, -1, -1, -1},
448 { 2, 3, 4, 7, 6, 5, 2, 3},
449 {-1, -1, -1, -1, -1, -1, 4, -1},
450 {-1, -1, -1, -1, -1, -1, 7, -1},
451 {-1, 4, 3, 2, 5, 6, -1, -1},
452 {-1, 7, -1, -1, -1, -1, -1, -1},
453 { 6, -1, -1, -1, -1, -1, -1, -1},
454 { 5, 2, 3, 4, 7, 6, 5, -1},
455 {-1, -1, -1, -1, -1, -1, -1, -1}},
456 {{ 3, 2, 1, 0, 0, 1, 2, 3},
457 { 3, 2, 1, 0, 1, 2, 3, -1},
458 { 4, 3, 2, 1, 1, 2, 3, 4},
459 { 4, 3, 2, 1, 2, 3, 4, -1},
460 { 5, 4, 3, 2, 2, 3, 4, 5},
461 { 5, 4, 3, 2, 3, 4, 5, -1},
462 { 6, 5, 4, 3, 3, 4, 5, 6},
463 { 6, 5, 4, 3, 4, 5, 6, -1},
464 { 7, 6, 5, 4, 4, 5, 6, 7},
465 {-1, -1, -1, -1, -1, -1, -1, -1}},
466 {{-1, -1, -1, 5, 5, -1, -1, -1},
467 {-1, -1, -1, 3, -1, -1, -1, -1},
468 {-1, -1, -1, 2, 4, -1, -1, -1},
469 {-1, -1, -1, 6, -1, -1, -1, -1},
470 {-1, -1, -1, 2, 4, -1, -1, -1},
471 {-1, 2, -1, 5, -1, 4, -1, -1},
472 { 1, 0, 1, 0, 1, 0, 1, 0},
473 { 3, -1, 3, -1, 2, -1, 6, -1},
474 {-1, -1, -1, -1, -1, -1, -1, -1},
475 {-1, -1, -1, -1, -1, -1, -1, -1}},
476 {{-1, -1, -1, -1, 1, -1, -1, -1},
477 { 7, 4, 3, 5, -1, -1, -1, -1},
478 { 6, -1, -1, 1, -1, -1, -1, -1},
479 {-1, -1, -1, 5, 3, 4, 7, -1},
480 { 6, -1, -1, -1, 1, -1, -1, 6},
481 { 7, 4, 3, 5, -1, -1, -1, -1},
482 {-1, -1, -1, 1, -1, -1, -1, 6},
483 {-1, -1, -1, 5, 3, 4, 7, -1},
484 {-1, -1, -1, -1, -1, -1, -1, -1},
485 {-1, -1, -1, -1, -1, -1, -1, -1}},
486 {{-1, -1, -1, -1, 7, 3, 6, -1},
487 {-1, -1, 3, 7, 3, 6, 3, -1},
488 {-1, -1, 5, 7, 3, 6, 3, -1},
489 {-1, 6, 7, 3, 6, 7, -1, -1},
490 {-1, 7, 7, 3, 6, 1, -1, -1},
491 { 3, 7, 3, 6, 3, -1, -1, -1},
492 { 5, 6, 2, 7, 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 {{ 5, -1, -1, -1, -1, -1, -1, 5},
497 { 5, -1, 6, 6, 6, -1, 5, -1},
498 {-1, 5, 4, -1, -1, 4, 5, -1},
499 {-1, 3, -1, -1, -1, 3, -1, -1},
500 {-1, 6, 0, -1, -1, 0, 6, -1},
501 {-1, 3, -1, -1, -1, 3, -1, -1},
502 {-1, -1, 4, -1, -1, 4, -1, -1},
503 {-1, -1, 6, 6, 6, -1, -1, -1},
504 {-1, -1, -1, -1, -1, -1, -1, -1},
505 {-1, -1, -1, -1, -1, -1, -1, -1}},
506 {{-1, 7, 0, -1, -1, 0, 7, -1},
507 { 7, -1, 0, -1, 0, -1, 7, -1},
508 { 7, 1, -1, 0, 0, -1, 1, 7},
509 { 7, 1, 2, 0, 2, 1, 7, -1},
510 { 7, 6, 3, 2, 2, 3, 6, 7},
511 { 7, -1, 3, 2, 3, -1, 7, -1},
512 {-1, 7, 7, 3, 3, 7, 7, -1},
513 {-1, -1, -1, 3, -1, -1, -1, -1},
514 {-1, -1, -1, -1, -1, -1, -1, -1},
515 {-1, -1, -1, -1, -1, -1, -1, -1}},
516 {{-1, 3, -1, 1, -1, 7, -1, 6},
517 { 5, -1, 7, -1, 7, -1, 6, -1},
518 { 6, -1, 0, -1, 5, -1, 3, -1},
519 {-1, 2, -1, 1, -1, 5, -1, -1},
520 {-1, 4, -1, 3, -1, 4, -1, -1},
521 { 2, -1, 3, -1, 2, -1, -1, -1},
522 {-1, -1, 4, -1, 6, -1, -1, -1},
523 {-1, -1, -1, 5, -1, -1, -1, -1},
524 {-1, -1, -1, -1, -1, -1, -1, -1},
525 {-1, -1, -1, -1, -1, -1, -1, -1}},
526 {{-1, -1, -1, -1, 1, -1, -1, -1},
527 {-1, -1, -1, -1, 3, -1, -1, -1},
528 { 6, 1, 3, 1, 2, 1, 4, 1},
529 {-1, -1, -1, -1, 6, -1, -1, -1},
530 {-1, -1, -1, 4, 1, -1, -1, -1},
531 {-1, -1, 1, -1, 3, -1, -1, -1},
532 {-1, -1, -1, 2, 1, -1, -1, -1},
533 {-1, -1, -1, -1, 4, -1, -1, -1},
534 {-1, -1, -1, 6, 1, -1, -1, -1},
535 {-1, -1, -1, 6, -1, -1, -1, -1}},
536 {{-1, -1, -1, 5, 4, -1, -1, -1},
537 {-1, -1, 4, 1, 0, -1, -1, -1},
538 {-1, -1, -1, 2, 3, -1, -1, -1},
539 {-1, 1, 4, -1, 2, 2, -1, -1},
540 {-1, 3, 1, 2, 5, 1, 4, -1},
541 {-1, 4, 2, -1, 0, 4, -1, -1},
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, -1, -1, -1, -1, -1, -1}},
546 {{-1, -1, -1, -1, 1, -1, -1, -1},
547 {-1, -1, -1, 1, -1, -1, -1, -1},
548 {-1, 2, -1, -1, 1, -1, 5, -1},
549 { 5, -1, -1, 1, -1, -1, 0, -1},
550 {-1, 6, -1, -1, 1, -1, 4, -1},
551 {-1, 0, -1, 1, -1, 5, -1, -1},
552 {-1, -1, 5, 5, 0, 1, -1, -1},
553 {-1, -1, -1, -1, -1, -1, -1, -1},
554 {-1, -1, -1, -1, -1, -1, -1, -1},
555 {-1, -1, -1, -1, -1, -1, -1, -1}},
556 {{-1, -1, -1, 6, 3, -1, -1, -1},
557 {-1, -1, 3, 2, 6, -1, -1, -1},
558 {-1, -1, 2, 6, 3, 2, -1, -1},
559 {-1, 6, 3, 2, 6, 3, -1, -1},
560 {-1, 3, 2, 6, 3, 2, 6, -1},
561 { 2, 6, 3, 2, 6, 3, 2, -1},
562 { 6, 3, 2, 6, 3, 2, 6, 3},
563 {-1, -1, -1, -1, -1, -1, -1, -1},
564 {-1, -1, -1, -1, -1, -1, -1, -1},
565 {-1, -1, -1, -1, -1, -1, -1, -1}},
566 {{ 6, 6, 6, 6, 6, 6, 6, 6},
567 { 4, -1, -1, -1, -1, -1, -1, -1},
568 {-1, 3, 2, 5, 7, 6, 4, 3},
569 {-1, 5, -1, -1, -1, -1, -1, -1},
570 {-1, -1, 7, 6, 4, 3, 2, 5},
571 {-1, -1, 4, -1, -1, -1, -1, -1},
572 {-1, -1, -1, 3, 2, 5, 7, 6},
573 {-1, -1, -1, -1, -1, -1, -1, -1},
574 {-1, -1, -1, -1, -1, -1, -1, -1},
575 {-1, -1, -1, -1, -1, -1, -1, -1}},
576 {{ 1, -1, 7, -1, -1, 6, -1, 2},
577 { 6, -1, 1, -1, 6, 1, 3, -1},
578 {-1, 4, -1, 7, 2, -1, 7, -1},
579 { 2, 7, -1, -1, -1, 4, -1, -1},
580 { 6, -1, 3, 5, 0, 2, -1, 7},
581 { 1, -1, -1, -1, -1, -1, 1, -1},
582 {-1, 1, 4, 5, 7, 5, 1, -1},
583 {-1, -1, -1, -1, -1, -1, -1, -1},
584 {-1, -1, -1, -1, -1, -1, -1, -1},
585 {-1, -1, -1, -1, -1, -1, -1, -1}},
586 {{ 6, 6, 6, -1, -1, 6, 6, 6},
587 {-1, -1, 6, -1, 6, -1, -1, -1},
588 {-1, -1, 2, 3, 3, 2, -1, -1},
589 {-1, 3, -1, 5, -1, 3, -1, -1},
590 {-1, -1, 5, 3, 3, 5, -1, -1},
591 {-1, -1, 6, 1, 6, -1, -1, -1},
592 {-1, 4, 2, -1, -1, 2, 4, -1},
593 {-1, -1, -1, -1, -1, -1, -1, -1},
594 {-1, -1, -1, -1, -1, -1, -1, -1},
595 {-1, -1, -1, -1, -1, -1, -1, -1}},
596 {{-1, -1, -1, 5, 5, -1, -1, -1},
597 {-1, -1, 5, -1, -1, -1, -1, -1},
598 {-1, 3, 4, 6, 6, -1, -1, 5},
599 { 3, 3, 4, 6, 5, -1, 5, -1},
600 { 3, 2, 3, 6, 6, 5, 5, -1},
601 { 3, 3, 4, 6, 5, -1, 5, -1},
602 {-1, 3, 4, 6, 6, -1, -1, 5},
603 {-1, -1, 5, -1, -1, -1, -1, -1},
604 {-1, -1, -1, 5, 5, -1, -1, -1},
605 {-1, -1, -1, -1, -1, -1, -1, -1}},
606 {{ 1, -1, -1, -1, -1, -1, -1, 1},
607 { 1, -1, 2, 2, 2, -1, 1, -1},
608 {-1, 1, 2, 3, 3, 2, 1, -1},
609 { 6, 2, 3, -1, 3, 2, 6, -1},
610 { 6, 2, 3, -1, -1, 3, 2, 6},
611 { 6, 2, 3, -1, 3, 2, 6, -1},
612 { 3, 3, 3, 7, 7, 3, 3, 3},
613 { 0, 5, 0, 2, 0, 5, 0, -1},
614 {-1, -1, -1, -1, -1, -1, -1, -1},
615 {-1, -1, -1, -1, -1, -1, -1, -1}},
616 {{-1, -1, 7, 7, 7, -1, -1, -1},
617 {-1, 7, 2, 2, 7, -1, -1, -1},
618 {-1, 7, 5, 5, 5, 7, -1, -1},
619 { 7, 7, 7, 7, 7, 7, -1, -1},
620 {-1, -1, 6, -1, 6, -1, -1, -1},
621 {-1, 6, -1, -1, 6, -1, -1, -1},
622 {-1, 6, 4, 4, -1, 6, 4, 4},
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, -1, -1}},
626 {{-1, 3, 3, -1, 3, 3, 3, -1},
627 { 3, 7, 5, 4, 6, 5, 3, -1},
628 { 1, 3, 3, 3, -1, 3, 3, 1},
629 { 2, 1, 2, 1, 2, 1, 2, -1},
630 { 1, 3, 3, -1, 3, 3, 3, 1},
631 { 3, 5, 6, 4, 5, 7, 3, -1},
632 { 2, 3, 3, 3, -1, 3, 3, 2},
633 { 1, 1, 2, 2, 2, 1, 1, -1},
634 {-1, -1, -1, -1, -1, -1, -1, -1},
635 {-1, -1, -1, -1, -1, -1, -1, -1}},
636 {{-1, 6, 5, -1, -1, -1, -1, -1},
637 { 3, 1, 3, -1, -1, -1, -1, -1},
638 {-1, 5, 6, -1, -1, -1, -1, -1},
639 {-1, -1, 5, 3, -1, -1, -1, -1},
640 {-1, -1, 6, 1, 6, -1, -1, -1},
641 {-1, -1, 3, 5, -1, -1, -1, -1},
642 {-1, -1, -1, -1, 3, 6, -1, -1},
643 {-1, -1, -1, 5, 6, 5, -1, -1},
644 {-1, -1, -1, -1, 6, 3, -1, -1},
645 {-1, -1, -1, -1, -1, -1, -1, -1}},
646 {{ 6, 3, 7, 4, 5, 1, 6, 3},
647 { 5, 1, 6, 3, 7, 4, 5, -1},
648 { 6, 3, 7, 4, 5, 1, 6, 3},
649 {-1, -1, -1, -1, -1, -1, -1, -1},
650 {-1, -1, -1, -1, -1, -1, -1, -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 {-1, -1, -1, -1, -1, -1, -1, -1}},
656 {{-1, -1, -1, -1, -1, -1, 4, 4},
657 {-1, -1, 7, 7, 7, 4, 4, -1},
658 {-1, -1, -1, -1, -1, -1, 4, 4},
659 {-1, 1, -1, -1, -1, 7, -1, -1},
660 {-1, 1, 1, -1, -1, 7, -1, -1},
661 { 3, 3, 3, -1, 7, -1, -1, -1},
662 { 3, -1, 2, 3, 3, 3, -1, 3},
663 {-1, 2, -1, 3, -1, 3, 3, -1},
664 {-1, 2, -1, -1, -1, -1, -1, -1},
665 {-1, -1, -1, -1, -1, -1, -1, -1}},
666 {{-1, -1, 4, -1, -1, -1, -1, -1},
667 {-1, 7, 4, -1, -1, -1, -1, -1},
668 {-1, -1, 7, 4, -1, -1, -1, -1},
669 {-1, 4, 7, 4, -1, -1, -1, -1},
670 { 1, 1, 1, 1, 1, 1, 1, -1},
671 { 1, 2, 1, 2, 1, 1, -1, -1},
672 { 2, 2, 2, 2, 2, 2, 2, 2},
673 {-1, -1, -1, -1, -1, -1, -1, -1},
674 {-1, -1, -1, -1, -1, -1, -1, -1},
675 {-1, -1, -1, -1, -1, -1, -1, -1}},
676 {{ 0, -1, -1, -1, -1, -1, -1, 6},
677 { 6, 1, 4, 3, 7, 5, 0, -1},
678 { 0, -1, -1, -1, -1, -1, -1, 6},
679 { 6, 1, 4, 3, 7, 5, 0, -1},
680 { 0, -1, -1, -1, -1, -1, -1, 6},
681 { 6, 1, 4, 3, 7, 5, 0, -1},
682 {-1, -1, -1, -1, -1, -1, -1, -1},
683 {-1, -1, -1, -1, -1, -1, -1, -1},
684 {-1, -1, -1, -1, -1, -1, -1, -1},
685 {-1, -1, -1, -1, -1, -1, -1, -1}},
686 {{ 3, 3, 4, 6, 6, 4, 3, 3},
687 { 0, 3, 4, 6, 4, 3, 1, -1},
688 { 5, 1, 3, 4, 4, 3, 0, 1},
689 { 0, 1, 3, 4, 3, 1, 0, -1},
690 { 2, 1, 6, 3, 3, 0, 0, 1},
691 { 0, 3, 4, 3, 6, 1, 5, -1},
692 { 6, 1, 2, 6, 4, 0, 0, 2},
693 {-1, -1, -1, -1, -1, -1, -1, -1},
694 {-1, -1, -1, -1, -1, -1, -1, -1},
695 {-1, -1, -1, -1, -1, -1, -1, -1}},
696 {{ 6, 6, -1, -1, -1, -1, 4, 4},
697 { 4, 0, -1, -1, -1, 3, 6, -1},
698 { 0, 6, -1, -1, -1, -1, 4, 2},
699 { 7, -1, -1, -1, -1, -1, 7, -1},
700 { 4, 4, -1, -1, -1, -1, 5, 6},
701 { 6, 4, 7, 7, 5, 6, 4, -1},
702 {-1, 7, 6, 4, 6, 4, 7, -1},
703 {-1, 0, -1, 7, -1, 7, -1, -1},
704 {-1, -1, -1, -1, -1, -1, -1, -1},
705 {-1, -1, -1, -1, -1, -1, -1, -1}},
706 {{-1, 5, -1, -1, -1, -1, 4, -1},
707 {-1, 5, -1, -1, -1, 4, -1, -1},
708 {-1, -1, 5, 6, 6, 4, -1, -1},
709 {-1, -1, 2, -1, 2, -1, -1, -1},
710 { 0, 0, 6, -1, -1, 6, 1, 1},
711 {-1, -1, 2, -1, 2, -1, -1, -1},
712 {-1, -1, 7, 6, 6, 3, -1, -1},
713 {-1, 7, -1, -1, -1, 3, -1, -1},
714 {-1, 7, -1, -1, -1, -1, 3, -1},
715 {-1, -1, -1, -1, -1, -1, -1, -1}},
716 {{-1, 6, -1, -1, -1, -1, 2, -1},
717 { 1, 7, 1, 1, 1, 3, 1, -1},
718 {-1, -1, 4, 1, 1, 4, -1, -1},
719 {-1, 1, 3, 1, 7, 1, -1, -1},
720 {-1, -1, -1, 2, 6, -1, -1, -1},
721 {-1, -1, 1, 5, 1, -1, -1, -1},
722 {-1, -1, -1, -1, -1, -1, -1, -1},
723 {-1, -1, -1, -1, -1, -1, -1, -1},
724 {-1, -1, -1, -1, -1, -1, -1, -1},
725 {-1, -1, -1, -1, -1, -1, -1, -1}},
726 {{ 7, 7, 7, 7, 7, 7, 7, 7},
727 { 7, -1, -1, -1, -1, -1, 7, -1},
728 { 7, -1, -1, 2, 0, 5, 2, 2},
729 { 7, -1, -1, -1, 0, 3, 6, -1},
730 { 7, -1, -1, -1, -1, -1, 4, 0},
731 { 5, 5, -1, -1, -1, -1, -1, -1},
732 { 4, 3, 6, 2, -1, -1, -1, -1},
733 { 0, 2, 0, 4, -1, -1, -1, -1},
734 {-1, -1, -1, -1, -1, -1, -1, -1},
735 {-1, -1, -1, -1, -1, -1, -1, -1}},
736 {{-1, -1, 1, -1, -1, 1, -1, -1},
737 {-1, 4, -1, -1, 5, -1, -1, -1},
738 {-1, 7, -1, -1, 1, 1, 1, -1},
739 { 6, -1, -1, -1, -1, 7, -1, -1},
740 { 1, 1, 1, 1, -1, 4, -1, -1},
741 {-1, -1, 5, -1, -1, -1, -1, -1},
742 {-1, -1, 0, -1, -1, -1, -1, -1},
743 {-1, 3, -1, -1, -1, -1, -1, -1},
744 {-1, 1, -1, -1, -1, -1, -1, -1},
745 {-1, -1, -1, -1, -1, -1, -1, -1}},
746 {{-1, 7, 7, -1, -1, 7, 7, -1},
747 { 6, -1, 4, -1, 4, -1, 6, -1},
748 { 5, -1, -1, 3, 3, -1, -1, 5},
749 { 6, -1, -1, -1, -1, -1, 6, -1},
750 {-1, 7, -1, -1, -1, -1, 7, -1},
751 {-1, 4, -1, -1, -1, 4, -1, -1},
752 {-1, -1, 3, -1, -1, 3, -1, -1},
753 {-1, -1, 2, -1, 2, -1, -1, -1},
754 {-1, -1, -1, 5, 5, -1, -1, -1},
755 {-1, -1, -1, -1, -1, -1, -1, -1}},
756 {{-1, 0, 0, -1, -1, 0, 0, -1},
757 { 7, 4, 6, 6, 6, 4, 3, -1},
758 { 5, 6, 6, 6, 2, 6, 6, 3},
759 { 7, 4, 6, 6, 6, 4, 3, -1},
760 {-1, 0, 0, -1, -1, 0, 0, -1},
761 {-1, -1, -1, -1, -1, -1, -1, -1},
762 {-1, -1, -1, -1, -1, -1, -1, -1},
763 {-1, -1, -1, -1, -1, -1, -1, -1},
764 {-1, -1, -1, -1, -1, -1, -1, -1},
765 {-1, -1, -1, -1, -1, -1, -1, -1}},
766 {{-1, -1, -1, -1, -1, 7, 7, 7},
767 {-1, -1, -1, -1, 2, 7, 7, -1},
768 {-1, 0, 7, 7, 7, -1, 7, 7},
769 { 6, 7, 7, 7, -1, -1, -1, -1},
770 { 6, -1, -1, -1, 7, 7, 7, 7},
771 { 6, -1, -1, -1, -1, -1, -1, -1},
772 { 4, 2, 2, 2, 4, -1, 3, -1},
773 { 4, 4, 4, 4, 3, 3, 3, -1},
774 {-1, -1, -1, -1, -1, -1, -1, -1},
775 {-1, -1, -1, -1, -1, -1, -1, -1}},
776 {{ 4, -1, -1, 7, -1, 6, -1, 7},
777 { 7, 6, 7, -1, -1, 7, 4, -1},
778 {-1, -1, 7, -1, -1, 7, -1, -1},
779 {-1, 0, 0, 0, 0, 0, 3, -1},
780 {-1, -1, 0, 2, 2, 0, 6, 4},
781 {-1, -1, 0, 0, 0, 1, 3, -1},
782 {-1, -1, -1, 0, 0, -1, 3, 4},
783 {-1, -1, -1, 6, -1, 5, 6, -1},
784 {-1, -1, -1, -1, -1, -1, 1, 0},
785 {-1, -1, -1, -1, -1, -1, -1, -1}},
786 {{-1, 5, -1, -1, -1, -1, 5, -1},
787 { 0, -1, -1, 0, -1, -1, 0, -1},
788 { 0, 0, 0, 2, 2, 0, 0, 0},
789 { 0, -1, -1, 0, -1, -1, 0, -1},
790 {-1, 7, -1, 3, -1, -1, 7, -1},
791 {-1, -1, 3, 6, -1, -1, -1, -1},
792 {-1, -1, -1, 6, -1, -1, -1, -1},
793 {-1, 3, 6, -1, -1, -1, -1, -1},
794 {-1, 3, -1, -1, -1, -1, -1, -1},
795 {-1, -1, -1, -1, -1, -1, -1, -1}},
796 {{-1, -1, -1, 6, 5, -1, -1, -1},
797 {-1, -1, 2, 6, 3, -1, -1, -1},
798 {-1, -1, 5, 4, 7, 1, -1, -1},
799 {-1, 6, 2, 2, 3, 4, -1, -1},
800 {-1, -1, 3, 7, 3, 6, -1, -1},
801 {-1, -1, 1, 3, 2, -1, -1, -1},
802 {-1, -1, -1, 4, 5, -1, -1, -1},
803 {-1, -1, -1, 4, -1, -1, -1, -1},
804 {-1, -1, -1, -1, -1, -1, -1, -1},
805 {-1, -1, -1, -1, -1, -1, -1, -1}},
806 {{ 7, 7, -1, 2, 2, -1, 6, 6},
807 { 6, -1, -1, 6, -1, -1, 3, -1},
808 { 2, -1, -1, 1, -1, -1, 2, -1},
809 { 5, -1, -1, 3, -1, -1, 2, -1},
810 { 1, -1, -1, 2, -1, -1, 1, -1},
811 { 5, -1, -1, 2, -1, -1, 2, -1},
812 { 6, -1, -1, 1, -1, -1, 7, -1},
813 { 5, -1, -1, 5, -1, -1, 4, -1},
814 {-1, -1, -1, -1, -1, -1, -1, -1},
815 {-1, -1, -1, -1, -1, -1, -1, -1}},
816 {{-1, -1, -1, 6, 6, -1, -1, -1},
817 {-1, 0, 4, 4, 4, 0, -1, -1},
818 {-1, -1, -1, 6, 6, -1, -1, -1},
819 {-1, -1, 2, 7, 2, -1, -1, -1},
820 {-1, -1, -1, 6, 6, -1, -1, -1},
821 {-1, 0, 5, 5, 5, 0, -1, -1},
822 {-1, -1, -1, 3, 3, -1, -1, -1},
823 {-1, -1, -1, -1, -1, -1, -1, -1},
824 {-1, -1, -1, -1, -1, -1, -1, -1},
825 {-1, -1, -1, -1, -1, -1, -1, -1}},
826 {{-1, -1, 4, 1, 3, -1, -1, -1},
827 {-1, 1, -1, -1, 1, -1, -1, -1},
828 {-1, -1, 4, 1, 3, 4, 1, -1},
829 {-1, 1, 3, 4, -1, -1, 4, -1},
830 {-1, 3, -1, -1, 3, 4, 1, -1},
831 {-1, 1, 3, 4, 1, 3, -1, -1},
832 {-1, -1, 4, 1, -1, -1, -1, -1},
833 {-1, -1, -1, -1, -1, -1, -1, -1},
834 {-1, -1, -1, -1, -1, -1, -1, -1},
835 {-1, -1, -1, -1, -1, -1, -1, -1}},
836 {{-1, 6, 4, -1, 3, 2, 5, -1},
837 { 0, -1, -1, -1, -1, -1, 1, -1},
838 {-1, 2, 3, 5, -1, 4, 6, -1},
839 { 0, -1, -1, -1, -1, -1, 1, -1},
840 {-1, 4, 6, -1, 2, 5, 3, -1},
841 { 0, -1, -1, -1, -1, -1, 1, -1},
842 {-1, 5, 2, 3, -1, 4, 6, -1},
843 {-1, -1, -1, -1, -1, -1, -1, -1},
844 {-1, -1, -1, -1, -1, -1, -1, -1},
845 {-1, -1, -1, -1, -1, -1, -1, -1}},
846 {{-1, -1, -1, 6, 6, -1, -1, -1},
847 {-1, -1, 7, 6, 4, -1, -1, -1},
848 {-1, 2, 1, 7, 4, 1, 3, -1},
849 { 2, 1, 1, 1, 1, 1, 3, -1},
850 {-1, 2, 2, 2, 3, 3, 3, -1},
851 {-1, -1, -1, 5, -1, -1, -1, -1},
852 {-1, -1, -1, 2, 3, -1, -1, -1},
853 {-1, -1, -1, 5, -1, -1, -1, -1},
854 {-1, -1, 2, 2, 3, 3, -1, -1},
855 {-1, -1, -1, -1, -1, -1, -1, -1}},
856 {{ 4, -1, 5, -1, -1, 3, -1, 6},
857 { 2, -1, 3, -1, 2, -1, 4, -1},
858 { 4, -1, -1, 1, 0, -1, -1, 6},
859 { 6, -1, 2, 3, 5, -1, 4, -1},
860 { 4, -1, -1, 0, 1, -1, -1, 6},
861 { 2, -1, 5, -1, 3, -1, 4, -1},
862 { 4, -1, 3, -1, -1, 2, -1, 6},
863 { 6, -1, -1, -1, -1, -1, 4, -1},
864 {-1, -1, -1, -1, -1, -1, -1, -1},
865 {-1, -1, -1, -1, -1, -1, -1, -1}},
866 {{ 2, 6, 0, 5, 5, 1, 3, 4},
867 { 1, -1, -1, 2, -1, -1, 0, -1},
868 { 4, -1, -1, 3, 6, -1, -1, 2},
869 {-1, -1, -1, 0, -1, -1, -1, -1},
870 {-1, -1, -1, 1, 4, -1, -1, -1},
871 {-1, -1, -1, 2, -1, -1, -1, -1},
872 {-1, -1, -1, 6, 3, -1, -1, -1},
873 {-1, -1, -1, 5, -1, -1, -1, -1},
874 {-1, -1, -1, 4, 1, -1, -1, -1},
875 {-1, -1, -1, -1, -1, -1, -1, -1}},
876 {{-1, -1, -1, -1, 5, 1, 1, 3},
877 { 0, 5, 1, 0, 5, 3, 3, -1},
878 { 5, 1, 0, 5, 1, 0, 5, 1},
879 { 0, 5, 1, 0, 5, 1, 6, -1},
880 {-1, -1, -1, -1, 1, 6, 5, 1},
881 {-1, -1, -1, -1, 5, 1, 6, -1},
882 {-1, -1, -1, -1, 1, 0, 5, 1},
883 {-1, -1, -1, -1, 5, 1, 0, -1},
884 {-1, -1, -1, -1, -1, -1, -1, -1},
885 {-1, -1, -1, -1, -1, -1, -1, -1}},
886 {{-1, 0, 7, 3, -1, -1, 2, 2},
887 {-1, 0, 7, 3, -1, -1, 2, -1},
888 {-1, 0, 7, 3, -1, -1, 2, 2},
889 {-1, 0, 7, 3, -1, 3, 1, -1},
890 {-1, 0, 7, 3, -1, 6, 4, 5},
891 {-1, 0, 7, 3, -1, 7, 0, -1},
892 {-1, 0, 7, 3, -1, 2, 3, 4},
893 {-1, 0, 7, 3, -1, 5, 6, -1},
894 {-1, -1, -1, -1, -1, 7, 0, 1},
895 {-1, -1, -1, -1, -1, -1, -1, -1}},
896 {{-1, -1, -1, 7, 7, 7, 7, -1},
897 { 3, 4, 5, -1, -1, -1, 7, -1},
898 { 2, -1, -1, -1, -1, -1, -1, 3},
899 { 7, -1, -1, -1, -1, -1, 4, -1},
900 { 7, -1, -1, -1, 3, 4, 5, 6},
901 { 7, -1, -1, 2, 0, 1, 2, -1},
902 { 6, -1, -1, -1, 3, 4, 5, 6},
903 { 0, 1, -1, -1, -1, -1, -1, -1},
904 { 2, 3, 4, -1, -1, -1, -1, -1},
905 { 5, 6, 0, -1, -1, -1, -1, -1}},
906 {{-1, 7, -1, -1, -1, -1, 2, -1},
907 { 1, 1, -1, -1, -1, 3, 3, -1},
908 {-1, 2, -1, -1, -1, -1, 4, -1},
909 { 3, 3, -1, -1, -1, 5, 5, -1},
910 {-1, 4, -1, -1, -1, -1, 6, -1},
911 { 5, 5, -1, -1, -1, 1, 1, -1},
912 {-1, 6, -1, -1, -1, -1, 7, -1},
913 {-1, -1, -1, -1, -1, -1, -1, -1},
914 {-1, -1, -1, -1, -1, -1, -1, -1},
915 {-1, -1, -1, -1, -1, -1, -1, -1}},
916 {{-1, 4, -1, -1, -1, -1, 4, -1},
917 { 2, -1, -1, 1, -1, -1, 2, -1},
918 { 5, -1, -1, 0, 0, -1, -1, 5},
919 { 5, -1, -1, 1, -1, -1, 6, -1},
920 {-1, 4, 2, 7, 7, 5, 4, -1},
921 {-1, -1, -1, 6, -1, -1, -1, -1},
922 {-1, -1, -1, 3, 3, -1, -1, -1},
923 {-1, -1, -1, 7, -1, -1, -1, -1},
924 {-1, -1, -1, -1, -1, -1, -1, -1},
925 {-1, -1, -1, -1, -1, -1, -1, -1}},
926 {{-1, 1, -1, -1, 2, 3, 4, -1},
927 { 2, -1, -1, 3, 0, 4, -1, -1},
928 { 4, -1, -1, 2, 3, 1, -1, -1},
929 { 3, -1, 4, 3, 0, -1, -1, -1},
930 { 4, -1, -1, 2, 5, 1, -1, -1},
931 { 3, -1, 4, 5, 0, 4, -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, -1, -1, -1, -1, -1}},
936 {{ 2, -1, -1, 1, 1, -1, -1, 2},
937 { 2, -1, 3, 3, 3, -1, 2, -1},
938 {-1, 2, -1, 4, 4, -1, 2, -1},
939 {-1, 7, 7, 0, 7, 7, -1, -1},
940 {-1, -1, -1, 4, 4, -1, -1, -1},
941 {-1, -1, 5, 7, 5, -1, -1, -1},
942 { 6, 3, 2, 6, 4, 2, 3, 6},
943 { 5, -1, -1, -1, -1, -1, 1, -1},
944 {-1, -1, -1, -1, -1, -1, -1, -1},
945 {-1, -1, -1, -1, -1, -1, -1, -1}},
946 {{ 4, 2, 3, 5, 7, 1, 3, 6},
947 { 1, -1, -1, 1, -1, -1, 1, -1},
948 { 3, 0, 1, 3, 2, 4, 3, 5},
949 { 4, -1, -1, 4, -1, -1, 4, -1},
950 {-1, 5, -1, -1, 5, -1, -1, 5},
951 { 0, 3, 2, 0, 4, 5, 0, -1},
952 {-1, 6, -1, -1, 6, -1, -1, 6},
953 { 7, -1, -1, 7, -1, -1, 7, -1},
954 {-1, -1, -1, -1, -1, -1, -1, -1},
955 {-1, -1, -1, -1, -1, -1, -1, -1}},
956 {{-1, 5, 4, -1, 1, 1, -1, -1},
957 { 5, -1, 4, 1, -1, 1, -1, -1},
958 { 0, -1, -1, -1, -1, -1, 0, -1},
959 { 0, 6, 4, -1, -1, 4, 2, -1},
960 {-1, 4, 3, 5, 2, 6, 3, 6},
961 {-1, 2, 6, -1, -1, 5, 4, -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 {-1, -1, -1, -1, -1, -1, -1, -1}},
966 {{-1, -1, -1, 6, 6, -1, -1, -1},
967 {-1, -1, 5, 5, 4, -1, -1, -1},
968 {-1, -1, 1, 6, 6, 4, -1, -1},
969 {-1, 1, 7, 2, 5, 3, -1, -1},
970 {-1, 2, 7, 2, 1, 5, 3, -1},
971 { 2, 1, 3, 1, 4, 2, 7, -1},
972 {-1, 3, 1, 3, 4, 2, 7, -1},
973 {-1, 3, 5, 5, 6, 6, -1, -1},
974 {-1, -1, -1, -1, -1, -1, -1, -1},
975 {-1, -1, -1, -1, -1, -1, -1, -1}},
976 {{-1, -1, 7, 3, -1, -1, -1, -1},
977 {-1, 1, 7, 6, -1, -1, -1, -1},
978 {-1, 3, 7, 5, 1, 5, -1, -1},
979 { 7, 7, 0, 2, 4, 0, 4, -1},
980 { 7, 1, 4, 6, 5, 6, 5, 7},
981 { 1, 7, 7, 1, 7, 7, 1, -1},
982 {-1, -1, -1, -1, -1, -1, -1, -1},
983 {-1, -1, -1, -1, -1, -1, -1, -1},
984 {-1, -1, -1, -1, -1, -1, -1, -1},
985 {-1, -1, -1, -1, -1, -1, -1, -1}},
986 {{-1, -1, 1, -1, -1, 1, -1, -1},
987 {-1, 5, 6, 1, 5, 6, -1, -1},
988 {-1, 1, 1, 2, 2, 1, 1, -1},
989 { 4, 7, 1, 0, 1, 7, 4, -1},
990 {-1, 3, 7, 5, 7, 5, 3, -1},
991 {-1, 1, 1, 1, 1, 1, -1, -1},
992 {-1, -1, -1, -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 {{ 4, -1, -1, -1, 5, -1, -1, 4},
997 { 6, 6, 7, 6, -1, 4, 5, -1},
998 { 4, 2, 7, 5, 2, 2, 6, 4},
999 {-1, -1, 4, 1, -1, 5, 2, -1},
1000 {-1, 5, 2, 7, 7, -1, 7, 4},
1001 { 4, 6, 5, 4, -1, 4, 2, -1},
1002 {-1, -1, -1, 4, -1, 4, 1, -1},
1003 { 0, 0, 0, 5, -1, -1, -1, -1},
1004 {-1, -1, -1, -1, 0, 0, 0, 0},
1005 {-1, -1, -1, -1, -1, -1, -1, -1}},
1006 {{ 1, -1, -1, -1, 0, 0, -1, -1},
1007 { 2, -1, -1, 0, 1, 0, -1, -1},
1008 { 3, -1, -1, 0, 2, 2, 0, -1},
1009 { 4, -1, 0, 1, 1, 1, 0, -1},
1010 { 5, -1, -1, 0, 4, 4, 0, -1},
1011 { 6, -1, -1, 4, 4, 4, -1, -1},
1012 { 7, -1, -1, -1, 4, 4, -1, -1},
1013 {-1, -1, -1, 0, 1, 0, -1, -1},
1014 {-1, -1, -1, 0, 1, 1, 0, -1},
1015 {-1, -1, -1, -1, -1, -1, -1, -1}},
1016 {{-1, -1, 3, -1, -1, 1, 7, -1},
1017 {-1, 7, 4, -1, -1, 4, 3, -1},
1018 { 1, -1, -1, 0, 2, 0, -1, -1},
1019 { 5, 4, -1, 3, -1, -1, -1, -1},
1020 { 4, -1, 3, 6, 1, 1, 6, -1},
1021 {-1, 1, -1, -1, 4, -1, 1, -1},
1022 {-1, 7, 5, -1, -1, -1, 3, -1},
1023 {-1, -1, 3, -1, -1, -1, -1, -1},
1024 {-1, -1, -1, -1, -1, -1, -1, -1},
1025 {-1, -1, -1, -1, -1, -1, -1, -1}},
1026 {{ 1, -1, -1, -1, 1, -1, -1, -1},
1027 { 2, -1, -1, -1, 2, -1, -1, -1},
1028 {-1, 3, -1, -1, 3, 3, -1, -1},
1029 {-1, 4, -1, 4, -1, 4, -1, -1},
1030 {-1, 5, -1, -1, 5, 5, -1, -1},
1031 { 6, -1, -1, 7, 1, 7, -1, -1},
1032 { 7, -1, -1, -1, 6, 6, -1, -1},
1033 {-1, -1, -1, -1, -1, -1, -1, -1},
1034 {-1, -1, -1, -1, -1, -1, -1, -1},
1035 {-1, -1, -1, -1, -1, -1, -1, -1}},
1036 {{ 2, -1, -1, 6, -1, 2, 5, 1},
1037 { 5, -1, 4, -1, 4, -1, 4, -1},
1038 { 6, -1, -1, 3, -1, -1, -1, 3},
1039 { 4, 2, 0, -1, -1, -1, 5, -1},
1040 {-1, -1, -1, 6, -1, 3, 6, -1},
1041 {-1, -1, 5, -1, 5, -1, -1, -1},
1042 {-1, -1, -1, 3, -1, 4, 2, 5},
1043 {-1, -1, -1, -1, -1, -1, -1, -1},
1044 {-1, -1, -1, -1, -1, -1, -1, -1},
1045 {-1, -1, -1, -1, -1, -1, -1, -1}},
1046 {{ 6, -1, -1, -1, 4, -1, -1, 3},
1047 { 0, 3, -1, -1, 6, -1, 0, -1},
1048 {-1, -1, 7, -1, 1, -1, 3, -1},
1049 { 7, -1, 4, 7, -1, 2, -1, -1},
1050 { 5, 2, 3, 2, 1, 6, -1, 3},
1051 {-1, -1, 0, 4, 3, 5, 4, -1},
1052 {-1, 7, 6, -1, -1, 0, -1, -1},
1053 { 4, 3, -1, -1, -1, 4, 2, -1},
1054 { 0, -1, -1, -1, -1, -1, 6, -1},
1055 {-1, -1, -1, -1, -1, -1, -1, -1}},
1056 {{ 6, 1, 2, 5, 1, 6, 3, 0},
1057 {-1, -1, -1, -1, -1, -1, 4, -1},
1058 { 0, 5, 2, 7, 1, 6, 2, -1},
1059 { 3, -1, -1, -1, -1, -1, -1, -1},
1060 { 6, 7, 6, 4, 0, 5, 2, 6},
1061 {-1, -1, -1, -1, -1, -1, 1, -1},
1062 { 6, 1, 4, 0, 6, 2, 3, -1},
1063 { 0, -1, -1, -1, -1, -1, -1, -1},
1064 {-1, 0, 4, 5, 3, 7, 6, 0},
1065 {-1, -1, -1, -1, -1, -1, -1, -1}},
1066 {{-1, -1, -1, 0, 1, -1, -1, -1},
1067 {-1, -1, 0, 7, 0, -1, -1, -1},
1068 {-1, -1, 1, 2, 2, 0, -1, -1},
1069 {-1, 0, 7, 0, 7, 0, -1, -1},
1070 {-1, 6, -1, 7, 7, -1, 6, -1},
1071 { 4, 1, 6, 6, 6, 4, 1, -1},
1072 {-1, 5, -1, 7, 7, -1, 5, -1},
1073 {-1, -1, -1, -1, -1, -1, -1, -1},
1074 {-1, -1, -1, -1, -1, -1, -1, -1},
1075 {-1, -1, -1, -1, -1, -1, -1, -1}},
1076 {{-1, -1, -1, 5, 6, -1, -1, -1},
1077 {-1, -1, 3, 3, 3, -1, -1, -1},
1078 {-1, -1, 7, 5, 3, 7, -1, -1},
1079 {-1, 3, -1, 6, -1, 3, -1, -1},
1080 { 2, -1, -1, 3, 7, -1, -1, 1},
1081 { 2, 2, -1, 3, -1, 1, 1, -1},
1082 {-1, 0, 2, 5, 6, 1, 0, -1},
1083 {-1, -1, -1, 3, -1, -1, -1, -1},
1084 {-1, -1, -1, 3, 7, -1, -1, -1},
1085 {-1, -1, -1, -1, -1, -1, -1, -1}},
1086 {{-1, 6, -1, -1, -1, -1, 2, -1},
1087 {-1, 2, 6, 0, 6, 0, -1, -1},
1088 {-1, 0, -1, -1, -1, -1, -1, -1},
1089 { 6, -1, -1, -1, -1, -1, -1, -1},
1090 {-1, 3, 3, 2, 0, 6, 0, 0},
1091 {-1, 6, -1, -1, -1, -1, 0, -1},
1092 {-1, -1, -1, 6, 0, 2, 6, -1},
1093 {-1, 2, 0, -1, -1, -1, -1, -1},
1094 {-1, -1, -1, -1, -1, -1, -1, -1},
1095 {-1, -1, -1, -1, -1, -1, -1, -1}},
1096 {{ 0, 7, -1, -1, -1, -1, -1, -1},
1097 { 1, 5, -1, -1, -1, -1, -1, -1},
1098 { 7, 2, 5, -1, -1, -1, -1, -1},
1099 { 6, 3, 4, -1, -1, -1, -1, -1},
1100 { 5, 5, 4, 4, -1, -1, -1, -1},
1101 { 3, 3, 5, 3, -1, -1, -1, -1},
1102 { 1, 2, 2, 5, 3, -1, -1, -1},
1103 { 1, 0, 0, 7, 6, -1, -1, -1},
1104 { 3, 3, 5, 5, 7, 6, -1, -1},
1105 {-1, -1, -1, -1, -1, -1, -1, -1}},
1106 {{-1, -1, 2, 6, 6, 2, -1, -1},
1107 {-1, 2, 1, 1, 0, 2, -1, -1},
1108 {-1, 2, 3, 2, 2, 0, 2, -1},
1109 { 2, 3, 2, 5, 2, 7, 2, -1},
1110 { 2, 4, 2, 5, 2, 7, 2, 0},
1111 { 2, 4, 2, 6, 6, 2, 0, -1},
1112 {-1, 2, 5, 2, 2, 2, 7, 2},
1113 {-1, 2, 5, 6, 6, 7, 2, -1},
1114 {-1, -1, 2, 2, 2, 2, 2, -1},
1115 {-1, -1, -1, -1, -1, -1, -1, -1}},
1116 {{-1, -1, 0, -1, -1, 0, -1, -1},
1117 { 1, 0, 0, 1, 0, 0, 1, -1},
1118 { 1, 7, 7, 5, 5, 7, 7, 1},
1119 { 3, 2, -1, 2, -1, 2, 3, -1},
1120 { 3, 7, -1, 6, 6, -1, 7, 3},
1121 { 7, -1, -1, 6, -1, -1, 7, -1},
1122 { 4, 4, 5, -1, -1, 5, 4, 4},
1123 {-1, -1, -1, -1, -1, -1, -1, -1},
1124 {-1, -1, -1, -1, -1, -1, -1, -1},
1125 {-1, -1, -1, -1, -1, -1, -1, -1}},
1126 {{-1, 6, 3, -1, -1, 3, 6, -1},
1127 { 6, -1, 2, -1, 2, -1, 6, -1},
1128 { 2, -1, 0, 1, 1, 0, -1, 2},
1129 { 5, 0, -1, 7, -1, 0, 5, -1},
1130 {-1, 5, -1, 6, 6, -1, 5, -1},
1131 { 7, 1, 4, -1, 4, 1, 7, -1},
1132 { 7, -1, 4, -1, -1, 4, -1, 7},
1133 { 2, 0, -1, -1, -1, 0, 2, -1},
1134 {-1, 2, -1, -1, -1, -1, 2, -1},
1135 {-1, -1, -1, -1, -1, -1, -1, -1}},
1136 {{ 6, 1, -1, -1, -1, -1, 4, 0},
1137 { 2, 7, 5, 5, 5, 7, 3, -1},
1138 { 6, 1, -1, -1, -1, -1, 4, 0},
1139 { 2, 5, 7, 7, 7, 5, 3, -1},
1140 { 6, 1, -1, -1, -1, -1, 4, 0},
1141 { 2, 0, 6, 6, 6, 0, 3, -1},
1142 { 6, 1, -1, -1, -1, -1, 4, 0},
1143 {-1, -1, -1, -1, -1, -1, -1, -1},
1144 {-1, -1, -1, -1, -1, -1, -1, -1},
1145 {-1, -1, -1, -1, -1, -1, -1, -1}},
1146 {{ 5, -1, -1, 1, 1, -1, -1, 5},
1147 { 5, -1, 4, -1, 4, -1, 5, -1},
1148 {-1, 2, 4, -1, -1, 4, 2, -1},
1149 { 7, 2, -1, -1, -1, 2, 7, -1},
1150 { 0, -1, 0, 4, 4, 0, -1, 0},
1151 { 7, 2, -1, -1, -1, 2, 7, -1},
1152 {-1, 2, 3, -1, -1, 3, 2, -1},
1153 { 5, -1, 3, -1, 3, -1, 5, -1},
1154 { 5, -1, -1, 6, 6, -1, -1, 5},
1155 {-1, -1, -1, -1, -1, -1, -1, -1}},
1156 {{ 2, 2, -1, -1, -1, -1, 5, 5},
1157 { 5, -1, -1, -1, -1, -1, 2, -1},
1158 { 5, -1, -1, -1, -1, -1, -1, 2},
1159 { 1, -1, 1, 5, 1, -1, 3, -1},
1160 { 5, 2, 5, 3, 1, 2, 5, 2},
1161 { 2, 0, 5, -1, 2, 0, 5, -1},
1162 {-1, 3, 7, -1, -1, 3, 7, -1},
1163 {-1, -1, 2, 0, 5, -1, -1, -1},
1164 {-1, -1, -1, -1, -1, -1, -1, -1},
1165 {-1, -1, -1, -1, -1, -1, -1, -1}},
1166 {{ 0, 6, 5, 2, 3, 4, 1, 7},
1167 {-1, -1, -1, -1, 1, -1, -1, -1},
1168 {-1, -1, -1, 1, 1, -1, -1, -1},
1169 {-1, -1, 1, -1, -1, -1, -1, -1},
1170 { 7, 1, 4, 3, 2, 5, 6, 0},
1171 {-1, -1, -1, -1, 1, -1, -1, -1},
1172 {-1, -1, -1, 1, 1, -1, -1, -1},
1173 {-1, -1, 1, -1, -1, -1, -1, -1},
1174 { 0, 6, 5, 2, 3, 4, 1, 7},
1175 {-1, -1, -1, -1, -1, -1, -1, -1}},
1176 {{-1, -1, 1, -1, -1, 1, -1, -1},
1177 {-1, 2, 4, -1, 2, 4, -1, -1},
1178 {-1, 2, 3, 6, 5, 3, 2, -1},
1179 {-1, 6, 5, -1, 6, 5, -1, -1},
1180 {-1, -1, -1, 7, 7, -1, -1, -1},
1181 {-1, -1, -1, 7, -1, -1, -1, -1},
1182 { 1, -1, -1, 7, 7, -1, -1, 3},
1183 { 2, -1, -1, 7, -1, -1, 2, -1},
1184 {-1, 3, 4, 5, 6, 4, 1, -1},
1185 {-1, -1, -1, -1, -1, -1, -1, -1}},
1186 {{ 1, -1, -1, 2, 2, -1, -1, 2},
1187 { 1, 3, 7, 3, 7, 4, 2, -1},
1188 {-1, 1, 6, -1, -1, 6, 2, -1},
1189 { 6, -1, 7, 3, 7, -1, 6, -1},
1190 {-1, 4, 2, -1, -1, 1, 3, -1},
1191 {-1, -1, 2, 6, 1, -1, -1, -1},
1192 {-1, 4, 3, 3, 4, 4, 3, -1},
1193 {-1, -1, -1, -1, -1, -1, -1, -1},
1194 {-1, -1, -1, -1, -1, -1, -1, -1},
1195 {-1, -1, -1, -1, -1, -1, -1, -1}},
1196 {{-1, -1, -1, 5, 6, -1, -1, -1},
1197 {-1, -1, -1, 3, -1, -1, -1, -1},
1198 {-1, -1, -1, 1, 2, -1, -1, -1},
1199 {-1, -1, -1, 4, -1, -1, -1, -1},
1200 {-1, -1, -1, 5, 7, -1, -1, -1},
1201 {-1, -1, -1, 2, -1, -1, -1, -1},
1202 { 6, 5, 4, 3, 2, 1, 7, 5},
1203 {-1, -1, -1, -1, -1, -1, -1, -1},
1204 {-1, -1, -1, -1, -1, -1, -1, -1},
1205 {-1, -1, -1, -1, -1, -1, -1, -1}},
1206 {{-1, 0, -1, 1, -1, 2, -1, -1},
1207 {-1, 4, -1, 5, -1, 6, -1, -1},
1208 {-1, 7, -1, 0, -1, 2, -1, -1},
1209 {-1, 6, -1, 3, -1, 6, -1, -1},
1210 {-1, 1, -1, 1, -1, 2, -1, -1},
1211 {-1, 3, -1, 5, -1, 0, -1, -1},
1212 {-1, 2, -1, 4, -1, 6, -1, -1},
1213 {-1, 3, -1, 6, -1, 7, -1, -1},
1214 {-1, -1, -1, -1, -1, -1, -1, -1},
1215 {-1, -1, -1, -1, -1, -1, -1, -1}},
1216 {{ 1, 1, 2, 2, 3, 3, 4, 4},
1217 { 5, 5, 6, 7, 6, 5, 5, -1},
1218 { 6, 4, 3, 3, 2, 2, 1, 6},
1219 { 4, 6, 5, 7, 6, 3, 1, -1},
1220 {-1, -1, -1, -1, -1, -1, -1, -1},
1221 {-1, -1, -1, -1, -1, -1, -1, -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},
1225 {-1, -1, -1, -1, -1, -1, -1, -1}},
1226 {{ 7, 4, -1, 1, 2, -1, 4, 7},
1227 { 5, 5, -1, 2, -1, 4, 4, -1},
1228 {-1, 5, -1, 7, 7, -1, 4, -1},
1229 { 1, 0, 6, 7, 6, 0, 2, -1},
1230 {-1, 2, -1, 5, 3, -1, 1, -1},
1231 { 1, 1, -1, -1, -1, 2, 2, -1},
1232 { 6, 1, 4, -1, -1, 4, 2, 6},
1233 { 5, 3, -1, -1, -1, 3, 5, -1},
1234 {-1, -1, -1, -1, -1, -1, -1, -1},
1235 {-1, -1, -1, -1, -1, -1, -1, -1}},
1236 {{ 1, 5, 1, 0, 0, 1, 5, 1},
1237 { 1, 2, 5, -1, 5, 2, 1, -1},
1238 { 3, 6, 1, 2, 2, 1, 6, 3},
1239 { 4, 3, 4, -1, 4, 3, 4, -1},
1240 { 3, 4, 6, 5, 5, 6, 4, 3},
1241 { 0, 2, 3, -1, 3, 2, 0, -1},
1242 { 2, 3, 1, 5, 5, 1, 3, 2},
1243 {-1, -1, -1, -1, -1, -1, -1, -1},
1244 {-1, -1, -1, -1, -1, -1, -1, -1},
1245 {-1, -1, -1, -1, -1, -1, -1, -1}},
1246 {{ 3, 0, 2, 7, 5, 7, 6, 5},
1247 { 6, -1, 1, -1, 2, -1, 1, -1},
1248 {-1, 6, 4, 0, 3, 4, 5, -1},
1249 {-1, 5, -1, 1, -1, 4, -1, -1},
1250 {-1, 7, 3, 5, 6, 5, 3, -1},
1251 { 1, -1, 2, -1, 4, -1, 2, -1},
1252 { 6, 4, 4, 6, 6, 5, 5, 1},
1253 {-1, -1, -1, -1, -1, -1, -1, -1},
1254 {-1, -1, -1, -1, -1, -1, -1, -1},
1255 {-1, -1, -1, -1, -1, -1, -1, -1}}
1258 /* the tile struct
1259 * type is the bubble number 0-7
1260 * fallx is the x axis movement for the falling bubble
1261 * fallvel is the initial upward velocity for the falling bubble
1262 * ingroup denotes a bubble that is part of a group to be removed
1263 * anchored denotes a bubble that is anchored to the ceiling
1265 struct tile {
1266 int type;
1267 int fallx;
1268 int fallvel;
1269 bool ingroup;
1270 bool anchored;
1271 bool delete;
1274 /* the game context struct
1275 * score is the current score
1276 * level is the current level
1277 * angle is the current cannon direction
1278 * shots is the number of shots fired since last compression
1279 * compress is the height of the compressor
1280 * onboardcnt is the number of unique bubbles on the playing board
1281 * onboard is the unique bubbles on the playing board
1282 * nextinq is the pointer to the next bubble in the firing queue
1283 * queue is the circular buffer of bubbles to be fired
1284 * elapsedlvl is level elapsed time in 1/100s of seconds
1285 * elapsedshot is the shot elapsed time in 1/100s of seconds
1286 * startedshot is when the current shot began
1287 * playboard is the game playing board
1289 struct game_context {
1290 unsigned int score;
1291 unsigned int level;
1292 int angle;
1293 int shots;
1294 int compress;
1295 int onboardcnt;
1296 int onboard[NUM_BUBBLES];
1297 int nextinq;
1298 int queue[NUM_QUEUE];
1299 long elapsedlvl;
1300 long elapsedshot;
1301 long startedshot;
1302 struct tile playboard[BB_HEIGHT][BB_WIDTH];
1305 static struct highscore highscores[NUM_SCORES];
1307 /* used to denote available resume info */
1308 static bool resume = false;
1309 static bool resume_file = false;
1310 static unsigned int highlevel = 0; /* the highest level beaten */
1311 static unsigned int last_highlevel = 0;
1313 static void bubbles_init(struct game_context* bb);
1314 static bool bubbles_nextlevel(struct game_context* bb);
1315 static void bubbles_getonboard(struct game_context* bb);
1316 static void bubbles_drawboard(struct game_context* bb);
1317 static int bubbles_fire(struct game_context* bb);
1318 static bool bubbles_collision(struct game_context* bb, int y, int x,
1319 int nearrow, int nearcol);
1320 static bool bubbles_ingroup(struct game_context* bb, int row, int col);
1321 static int bubbles_searchgroup(struct game_context* bb, int row, int col);
1322 static int bubbles_remove(struct game_context* bb);
1323 static void bubbles_anchored(struct game_context* bb, int row, int col);
1324 static int bubbles_fall(struct game_context* bb);
1325 static int bubbles_checklevel(struct game_context* bb);
1326 static void bubbles_recordscore(struct game_context* bb);
1327 static bool bubbles_loadgame(struct game_context* bb);
1328 static void bubbles_savegame(struct game_context* bb);
1329 static inline void bubbles_setcolors(void);
1330 static void bubbles_callback(void* param);
1331 static int bubbles_handlebuttons(struct game_context* bb, bool animblock,
1332 int timeout);
1333 static int bubbles(struct game_context* bb);
1335 /*****************************************************************************
1336 * bubbles_init() initializes bubbles data structures.
1337 ******************************************************************************/
1338 static void bubbles_init(struct game_context* bb) {
1339 bubbles_setcolors();
1340 /* seed the rand generator */
1341 rb->srand(*rb->current_tick);
1343 /* check for resumed game */
1344 if (resume)
1346 resume = false;
1347 return;
1350 bb->score = 0;
1351 bubbles_nextlevel(bb);
1354 /*****************************************************************************
1355 * bubbles_nextlevel() sets up the game for the next level, returns false if
1356 * there are no more levels.
1357 ******************************************************************************/
1358 static bool bubbles_nextlevel(struct game_context* bb) {
1359 int i, j, pos;
1361 bb->level++;
1363 /* check if there are no more levels */
1364 if(bb->level > NUM_LEVELS) return false;
1366 /* save highest level */
1367 if (bb->level-1 > highlevel)
1368 highlevel = bb->level-1;
1370 /* set up the play board */
1371 rb->memset(bb->playboard, 0, sizeof(bb->playboard));
1372 for(i=0; i<BB_LEVEL_HEIGHT; i++) {
1373 for(j=0; j<BB_WIDTH; j++) {
1374 pos = (int)level[bb->level-1][i][j];
1375 if(pos >=0 && pos < NUM_BUBBLES) {
1376 bb->playboard[i][j].type = pos;
1377 } else {
1378 bb->playboard[i][j].type = -1;
1382 for(i=BB_LEVEL_HEIGHT; i<BB_HEIGHT; i++) {
1383 for(j=0; j<BB_WIDTH; j++) {
1384 bb->playboard[i][j].type = -1;
1388 /* fill first bubbles in shot queue */
1389 bubbles_getonboard(bb);
1390 for(i=0; i<NUM_QUEUE; i++) {
1391 bb->queue[i] = bb->onboard[rb->rand()%bb->onboardcnt];
1394 bb->angle = 0;
1395 bb->shots = 0;
1396 bb->compress = 0;
1397 bb->nextinq = 0;
1398 bb->elapsedlvl = 0;
1399 bb->elapsedshot = 0;
1401 return true;
1404 /*****************************************************************************
1405 * bubbles_getonboard() determines which bubble types are on the play board.
1406 ******************************************************************************/
1407 static void bubbles_getonboard(struct game_context* bb) {
1408 int i, j, k;
1409 bool found;
1411 bb->onboardcnt = 0;
1412 rb->memset(bb->onboard, -1, sizeof(bb->onboard));
1414 for(i=0; i<BB_HEIGHT; i++) {
1415 for(j=0; j<BB_WIDTH; j++) {
1416 if(bb->playboard[i][j].type >= 0) {
1417 found = false;
1419 for(k=0; k<bb->onboardcnt; k++) {
1420 if(bb->playboard[i][j].type == bb->onboard[k]) {
1421 found = true;
1422 break;
1426 if(!found) {
1427 bb->onboard[bb->onboardcnt] = bb->playboard[i][j].type;
1428 bb->onboardcnt++;
1431 if(bb->onboardcnt == NUM_BUBBLES) return;
1437 /*****************************************************************************
1438 * bubbles_drawboard() draws the game board to the buffer but does not update
1439 * the lcd.
1440 ******************************************************************************/
1441 static void bubbles_drawboard(struct game_context* bb) {
1442 int i, j;
1443 int w1, w2, h;
1444 int colmax, indent;
1445 int tipx, tipy;
1446 bool evenline = false;
1447 char *level = "Level";
1448 char *score = "Score";
1449 char *next = "Next";
1450 char *hurry = "HURRY!";
1451 char str[11];
1453 /* clear screen */
1454 rb->lcd_clear_display();
1455 int font = rb->screens[SCREEN_MAIN]->getuifont();
1456 h = rb->font_get(font)->height + 1;
1457 /* draw background */
1458 #ifdef HAVE_LCD_COLOR
1459 rb->lcd_bitmap(bubbles_background, 0, 0, LCD_WIDTH, LCD_HEIGHT);
1460 #endif
1462 /* display play board */
1463 for(i=0; i<BB_HEIGHT; i++) {
1464 colmax = BB_WIDTH;
1465 if(evenline) {
1466 colmax--;
1467 indent = ROW_INDENT;
1468 } else {
1469 indent = 0;
1471 evenline = !evenline;
1473 for(j=0; j<colmax; j++) {
1474 if(bb->playboard[i][j].type >= 0 && !bb->playboard[i][j].delete) {
1475 rb->lcd_bitmap_part(bubbles_emblem,
1476 0, EMBLEM_HEIGHT*bb->playboard[i][j].type,
1477 STRIDE( SCREEN_MAIN,
1478 BMPWIDTH_bubbles_emblem, BMPHEIGHT_bubbles_emblem),
1479 XOFS+indent+BUBBLE_WIDTH*j+(BUBBLE_WIDTH-EMBLEM_WIDTH)/2,
1480 YOFS+ROW_HEIGHT*i+(BUBBLE_HEIGHT-EMBLEM_HEIGHT)/2+bb->compress*ROW_HEIGHT,
1481 EMBLEM_WIDTH, EMBLEM_HEIGHT);
1482 rb->lcd_set_drawmode(DRMODE_FG);
1483 rb->lcd_mono_bitmap((const unsigned char *)bubbles_bubble,
1484 XOFS+indent+BUBBLE_WIDTH*j,
1485 YOFS+ROW_HEIGHT*i+bb->compress*ROW_HEIGHT,
1486 BUBBLE_WIDTH, BUBBLE_HEIGHT);
1487 rb->lcd_set_drawmode(DRMODE_SOLID);
1492 /* display bubble to be shot */
1493 rb->lcd_bitmap_part(bubbles_emblem,
1494 0, EMBLEM_HEIGHT*bb->queue[bb->nextinq],
1495 STRIDE( SCREEN_MAIN,
1496 BMPWIDTH_bubbles_emblem, BMPHEIGHT_bubbles_emblem),
1497 SHOTX+(BUBBLE_WIDTH-EMBLEM_WIDTH)/2,
1498 SHOTY+(BUBBLE_HEIGHT-EMBLEM_HEIGHT)/2,
1499 EMBLEM_WIDTH, EMBLEM_HEIGHT);
1500 rb->lcd_set_drawmode(DRMODE_FG);
1501 rb->lcd_mono_bitmap((const unsigned char *)bubbles_bubble,
1502 SHOTX, SHOTY,
1503 BUBBLE_WIDTH, BUBBLE_HEIGHT);
1504 rb->lcd_set_drawmode(DRMODE_SOLID);
1506 /* display next bubble to be shot */
1507 #ifndef NEXT_BB_X
1508 rb->lcd_bitmap_part(bubbles_emblem,
1509 0, EMBLEM_HEIGHT*bb->queue[(bb->nextinq+1)%NUM_QUEUE],
1510 STRIDE( SCREEN_MAIN,
1511 BMPWIDTH_bubbles_emblem, BMPHEIGHT_bubbles_emblem),
1512 XOFS/2-BUBBLE_WIDTH/2+(BUBBLE_WIDTH-EMBLEM_WIDTH)/2,
1513 SHOTY+(BUBBLE_HEIGHT-EMBLEM_HEIGHT)/2,
1514 EMBLEM_WIDTH, EMBLEM_HEIGHT);
1515 rb->lcd_set_drawmode(DRMODE_FG);
1516 rb->lcd_mono_bitmap((const unsigned char *)bubbles_bubble,
1517 XOFS/2-BUBBLE_WIDTH/2, SHOTY,
1518 BUBBLE_WIDTH, BUBBLE_HEIGHT);
1519 rb->lcd_set_drawmode(DRMODE_SOLID);
1520 #else
1521 rb->lcd_bitmap_part(bubbles_emblem,
1522 0, EMBLEM_HEIGHT*bb->queue[(bb->nextinq+1)%NUM_QUEUE],
1523 STRIDE( SCREEN_MAIN,
1524 BMPWIDTH_bubbles_emblem, BMPHEIGHT_bubbles_emblem),
1525 NEXT_BB_X + NEXT_BB_WIDTH/2-BUBBLE_WIDTH/2+(BUBBLE_WIDTH-EMBLEM_WIDTH)/2,
1526 NEXT_BB_Y + (BUBBLE_HEIGHT-EMBLEM_HEIGHT)/2 + h,
1527 EMBLEM_WIDTH, EMBLEM_HEIGHT);
1528 rb->lcd_set_drawmode(DRMODE_FG);
1529 rb->lcd_mono_bitmap((const unsigned char *)bubbles_bubble,
1530 NEXT_BB_X + NEXT_BB_WIDTH/2-BUBBLE_WIDTH/2, NEXT_BB_Y + h,
1531 BUBBLE_WIDTH, BUBBLE_HEIGHT);
1532 rb->lcd_set_drawmode(DRMODE_SOLID);
1533 #endif
1535 /* draw bounding lines */
1536 #ifndef HAVE_LCD_COLOR
1537 rb->lcd_vline(XOFS-1, 0, LCD_HEIGHT);
1538 rb->lcd_vline(XOFS+BUBBLE_WIDTH*BB_WIDTH, 0, LCD_HEIGHT);
1539 #endif
1540 rb->lcd_hline(XOFS, XOFS+BUBBLE_WIDTH*BB_WIDTH-1, YOFS+bb->compress*ROW_HEIGHT-1);
1541 rb->lcd_hline(XOFS, XOFS+BUBBLE_WIDTH*BB_WIDTH-1,
1542 YOFS+ROW_HEIGHT*(BB_HEIGHT-2)+BUBBLE_HEIGHT);
1544 /* draw arrow */
1545 tipx = SHOTX+BUBBLE_WIDTH/2+(((fp14_sin(bb->angle)>>4)*BUBBLE_WIDTH*3/2)>>10);
1546 tipy = SHOTY+BUBBLE_HEIGHT/2-(((fp14_cos(bb->angle)>>4)*BUBBLE_HEIGHT*3/2)>>10);
1548 rb->lcd_drawline(SHOTX+BUBBLE_WIDTH/2+(((fp14_sin(bb->angle)>>4)*BUBBLE_WIDTH/2)>>10),
1549 SHOTY+BUBBLE_HEIGHT/2-(((fp14_cos(bb->angle)>>4)*BUBBLE_HEIGHT/2)>>10),
1550 tipx, tipy);
1551 xlcd_filltriangle(tipx, tipy,
1552 tipx+(((fp14_sin(bb->angle-135)>>4)*BUBBLE_WIDTH/3)>>10),
1553 tipy-(((fp14_cos(bb->angle-135)>>4)*BUBBLE_HEIGHT/3)>>10),
1554 tipx+(((fp14_sin(bb->angle+135)>>4)*BUBBLE_WIDTH/3)>>10),
1555 tipy-(((fp14_cos(bb->angle+135)>>4)*BUBBLE_HEIGHT/3)>>10));
1557 /* draw text */
1558 rb->snprintf(str, 4, "%d", bb->level);
1559 rb->lcd_getstringsize(level, &w1, NULL);
1560 rb->lcd_getstringsize(str, &w2, NULL);
1561 #ifndef LEVEL_TXT_X
1562 rb->lcd_putsxy(XOFS/2-w1/2, 2, level);
1563 rb->lcd_putsxy(XOFS/2-w2/2, 2+h, str);
1564 #else
1565 rb->lcd_putsxy(LEVEL_TXT_X+(LEVEL_TXT_WIDTH/2-w1/2), LEVEL_TXT_Y, level);
1566 rb->lcd_putsxy(LEVEL_TXT_X+(LEVEL_TXT_WIDTH/2-w2/2), LEVEL_TXT_Y+h, str);
1567 #endif
1569 rb->snprintf(str, 10, "%d", bb->score);
1570 rb->lcd_getstringsize(score, &w1,NULL);
1571 rb->lcd_getstringsize(str, &w2, NULL);
1572 #ifndef SCORE_TXT_X
1573 rb->lcd_putsxy(XOFS/2-w1/2, 29, score);
1574 rb->lcd_putsxy(XOFS/2-w2/2, 29+h, str);
1575 #else
1576 rb->lcd_putsxy(SCORE_TXT_X+(SCORE_TXT_WIDTH/2-w1/2), SCORE_TXT_Y, score);
1577 rb->lcd_putsxy(SCORE_TXT_X+(SCORE_TXT_WIDTH/2-w2/2), SCORE_TXT_Y+h, str);
1578 #endif
1580 rb->lcd_getstringsize(next, &w1, NULL);
1581 #ifndef NEXT_BB_X
1582 rb->lcd_putsxy(XOFS/2-w1/2, SHOTY-h, next);
1583 #else
1584 rb->lcd_putsxy(NEXT_BB_X+(NEXT_BB_WIDTH/2-w1/2), NEXT_BB_Y, next);
1585 #endif
1588 if(bb->elapsedshot >= (MAX_SHOTTIME*7)/10) {
1589 rb->lcd_getstringsize(hurry, &w1, &h);
1590 /* screen is too small for the message to be centered (Clip Zip) */
1591 #if (LCD_WIDTH <= 96)
1592 rb->lcd_putsxy(LCD_WIDTH/2-w1/2+LCD_WIDTH/6, LCD_HEIGHT/2-h/2, hurry);
1593 #else
1594 rb->lcd_putsxy(LCD_WIDTH/2-w1/2, LCD_HEIGHT/2-h/2, hurry);
1595 #endif
1599 /*****************************************************************************
1600 * bubbles_fire() fires the current bubble, reloads the cannon, attaches
1601 * bubble to playboard, removes appropriate bubbles, and advances the
1602 * the compressor.
1603 ******************************************************************************/
1604 static int bubbles_fire(struct game_context* bb) {
1605 int bubblecur;
1606 long shotxinc, shotyinc;
1607 long shotxofs, shotyofs;
1608 int shotxdirec = 1;
1609 long tempxofs, tempyofs;
1610 int nearrow, nearcol;
1611 int lastrow = BB_HEIGHT-1;
1612 int lastcol = (BB_WIDTH-1)/2;
1613 int buttonres;
1614 long lasttick, currenttick;
1616 /* get current bubble */
1617 bubblecur = bb->queue[bb->nextinq];
1618 shotxinc = ((fp14_sin(bb->angle)>>4)*BUBBLE_WIDTH)/3;
1619 shotyinc = ((-1*(fp14_cos(bb->angle)>>4))*BUBBLE_HEIGHT)/3;
1620 shotxofs = shotyofs = 0;
1622 /* advance the queue */
1623 bb->queue[bb->nextinq] = bb->onboard[rb->rand()%bb->onboardcnt];
1624 bb->nextinq = (bb->nextinq+1)%NUM_QUEUE;
1625 bubbles_drawboard(bb);
1626 rb->lcd_update_rect(0, 0, XOFS, LCD_HEIGHT);
1628 /* move the bubble across the play board */
1629 lasttick = *rb->current_tick;
1631 while(true) {
1632 /* move the bubble one step */
1633 shotyofs += shotyinc;
1634 shotxofs += shotxinc*shotxdirec;
1636 /* check for bounce off sides */
1637 if(SHOTX+(shotxofs>>10) < XOFS) {
1638 shotxofs += 2*((XOFS<<10)-(((SHOTX)<<10)+shotxofs));
1639 shotxdirec *= -1;
1640 } else if(SHOTX+(shotxofs>>10) > XOFS+(BB_WIDTH-1)*BUBBLE_WIDTH) {
1641 shotxofs -= 2*((((SHOTX)<<10)+shotxofs)-
1642 ((XOFS<<10)+(((BB_WIDTH-1)*BUBBLE_WIDTH)<<10)));
1643 shotxdirec *= -1;
1646 tempxofs = shotxofs>>10;
1647 tempyofs = shotyofs>>10;
1649 /* display shot */
1650 bubbles_drawboard(bb);
1651 rb->lcd_bitmap_part(bubbles_emblem, 0, EMBLEM_HEIGHT*bubblecur,
1652 STRIDE( SCREEN_MAIN,
1653 BMPWIDTH_bubbles_emblem,
1654 BMPHEIGHT_bubbles_emblem),
1655 SHOTX+tempxofs+(BUBBLE_WIDTH-EMBLEM_WIDTH)/2,
1656 SHOTY+tempyofs+(BUBBLE_HEIGHT-EMBLEM_HEIGHT)/2,
1657 EMBLEM_WIDTH, EMBLEM_HEIGHT);
1658 rb->lcd_set_drawmode(DRMODE_FG);
1659 rb->lcd_mono_bitmap((const unsigned char *)bubbles_bubble,
1660 SHOTX+tempxofs, SHOTY+tempyofs,
1661 BUBBLE_WIDTH, BUBBLE_HEIGHT);
1662 rb->lcd_set_drawmode(DRMODE_SOLID);
1663 rb->lcd_update_rect(XOFS, 0, BB_WIDTH*BUBBLE_WIDTH, LCD_HEIGHT);
1665 /* find nearest position */
1666 nearrow = ((SHOTY+tempyofs)-
1667 (YOFS+bb->compress*ROW_HEIGHT)+
1668 (ROW_HEIGHT/2))/ROW_HEIGHT;
1669 if(nearrow >= BB_HEIGHT) nearrow = BB_HEIGHT-1;
1671 if(nearrow%2) { /* odd row */
1672 nearcol = ((SHOTX+tempxofs)-
1673 (XOFS+ROW_INDENT)+
1674 (BUBBLE_WIDTH/2))/BUBBLE_WIDTH;
1675 if(nearcol >= BB_WIDTH-1) nearcol = BB_WIDTH-2;
1676 } else { /* even row */
1677 nearcol = ((SHOTX+tempxofs)-XOFS+(BUBBLE_WIDTH/2))/BUBBLE_WIDTH;
1678 if(nearcol >= BB_WIDTH) nearcol = BB_WIDTH-1;
1680 if(nearcol < 0) nearcol = 0;
1682 /* if nearest position is occupied attach to last position */
1683 if(bb->playboard[nearrow][nearcol].type >= 0) {
1684 bb->playboard[lastrow][lastcol].type = bubblecur;
1685 break;
1688 /* save last position */
1689 lastrow = nearrow;
1690 lastcol = nearcol;
1692 /* if collision with neighbor then attach shot */
1693 if(bubbles_collision(bb, YOFS+SHOTY+tempyofs, SHOTX+tempxofs,
1694 nearrow, nearcol)) {
1695 bb->playboard[nearrow][nearcol].type = bubblecur;
1696 break;
1699 /* if at top then attach shot to the ceiling */
1700 if(nearrow == 0 && SHOTY+tempyofs <= YOFS+bb->compress*ROW_HEIGHT) {
1701 bb->playboard[nearrow][nearcol].type = bubblecur;
1702 break;
1705 /* handle button events */
1706 buttonres = bubbles_handlebuttons(bb, true, 0);
1707 if(buttonres != BB_NONE) return buttonres;
1709 /* framerate limiting */
1710 currenttick = *rb->current_tick;
1711 if(currenttick-lasttick < HZ/MAX_FPS) {
1712 rb->sleep((HZ/MAX_FPS)-(currenttick-lasttick));
1713 } else {
1714 rb->yield();
1716 lasttick = currenttick;
1719 bubbles_drawboard(bb);
1720 rb->lcd_update();
1722 /* clear appropriate bubbles from playing board */
1723 if(bubbles_ingroup(bb, lastrow, lastcol)) {
1724 buttonres = bubbles_remove(bb);
1725 if(buttonres != BB_NONE) return buttonres;
1728 /* update shots and compress amount */
1729 bb->shots++;
1730 if(bb->shots >= NUM_COMPRESS) {
1731 bb->shots = 0;
1732 bb->compress++;
1735 return BB_NONE;
1738 /*****************************************************************************
1739 * bubbles_collision() determines if a fired bubble has collided with another
1740 * bubble.
1741 ******************************************************************************/
1742 static bool bubbles_collision(struct game_context* bb, int y, int x,
1743 int nearrow, int nearcol) {
1744 int nx, ny;
1745 int adj = nearrow%2;
1747 /* check neighbors */
1748 if(nearcol-1 >= 0) {
1749 if(bb->playboard[nearrow][nearcol-1].type >= 0) {
1750 nx = XOFS+(nearrow%2 ? ROW_INDENT : 0)+BUBBLE_WIDTH*(nearcol-1);
1751 ny = YOFS+ROW_HEIGHT*nearrow+bb->compress*ROW_HEIGHT;
1752 if((x-nx)*(x-nx)+(y-ny)*(y-ny) < MIN_DISTANCE) return true;
1756 if(nearcol-1+adj >= 0) {
1757 if(nearrow-1 >= 0) {
1758 if(bb->playboard[nearrow-1][nearcol-1+adj].type >= 0) {
1759 nx = XOFS+((nearrow-1)%2 ? ROW_INDENT : 0)+
1760 BUBBLE_WIDTH*(nearcol-1+adj);
1761 ny = YOFS+ROW_HEIGHT*(nearrow-1)+bb->compress*ROW_HEIGHT;
1762 if((x-nx)*(x-nx)+(y-ny)*(y-ny) < MIN_DISTANCE) return true;
1766 if(nearrow+1 < BB_HEIGHT) {
1767 if(bb->playboard[nearrow+1][nearcol-1+adj].type >= 0) {
1768 nx = XOFS+((nearrow+1)%2 ? ROW_INDENT : 0)+
1769 BUBBLE_WIDTH*(nearcol-1+adj);
1770 ny = YOFS+ROW_HEIGHT*(nearrow+1)+bb->compress*ROW_HEIGHT;
1771 if((x-nx)*(x-nx)+(y-ny)*(y-ny) < MIN_DISTANCE) return true;
1776 if(nearcol+adj >= 0) {
1777 if(nearrow-1 >= 0) {
1778 if(bb->playboard[nearrow-1][nearcol+adj].type >= 0) {
1779 nx = XOFS+((nearrow-1)%2 ? ROW_INDENT : 0)+
1780 BUBBLE_WIDTH*(nearcol+adj);
1781 ny = YOFS+ROW_HEIGHT*(nearrow-1)+bb->compress*ROW_HEIGHT;
1782 if((x-nx)*(x-nx)+(y-ny)*(y-ny) < MIN_DISTANCE) return true;
1786 if(nearrow+1 < BB_HEIGHT) {
1787 if(bb->playboard[nearrow+1][nearcol+adj].type >= 0) {
1788 nx = XOFS+((nearrow+1)%2 ? ROW_INDENT : 0)+
1789 BUBBLE_WIDTH*(nearcol+adj);
1790 ny = YOFS+ROW_HEIGHT*(nearrow+1)+bb->compress*ROW_HEIGHT;
1791 if((x-nx)*(x-nx)+(y-ny)*(y-ny) < MIN_DISTANCE) return true;
1796 if(nearcol+1 < BB_WIDTH-adj) {
1797 if(bb->playboard[nearrow][nearcol+1].type >= 0) {
1798 nx = XOFS+(nearrow%2 ? ROW_INDENT : 0)+BUBBLE_WIDTH*(nearcol+1);
1799 ny = YOFS+ROW_HEIGHT*nearrow+bb->compress*ROW_HEIGHT;
1800 if((x-nx)*(x-nx)+(y-ny)*(y-ny) < MIN_DISTANCE) return true;
1804 return false;
1807 /*****************************************************************************
1808 * bubbles_ingroup() marks all bubbles that form the current group.
1809 ******************************************************************************/
1810 static bool bubbles_ingroup(struct game_context* bb, int row, int col) {
1811 int i, j;
1812 int count;
1814 count = bubbles_searchgroup(bb, row, col);
1816 /* unmark group if too small */
1817 if(count < 3) {
1818 for(i=0; i<BB_HEIGHT; i++) {
1819 for(j=0; j<BB_WIDTH; j++) {
1820 bb->playboard[i][j].ingroup = false;
1824 return false;
1827 return true;
1830 /*****************************************************************************
1831 * bubbles_searchgroup() return the size of the group of bubbles of the same
1832 * type that the current bubble belongs to.
1833 ******************************************************************************/
1834 static int bubbles_searchgroup(struct game_context* bb, int row, int col) {
1835 int i, adj;
1836 int myrow, mycol, mytype;
1837 int count = 0;
1839 struct coord {
1840 int row;
1841 int col;
1842 } search[(2*BB_WIDTH-1)*(BB_HEIGHT/2)];
1844 /* search initial bubble */
1845 bb->playboard[row][col].ingroup = true;
1846 search[count].row = row;
1847 search[count].col = col;
1848 count++;
1850 /* breadth-first search neighbors */
1851 for(i=0; i<count; i++) {
1852 myrow = search[i].row;
1853 mycol = search[i].col;
1854 mytype = bb->playboard[myrow][mycol].type;
1855 adj = myrow%2;
1857 if(mycol-1 >= 0) {
1858 if(bb->playboard[myrow][mycol-1].type == mytype &&
1859 !bb->playboard[myrow][mycol-1].ingroup) {
1860 bb->playboard[myrow][mycol-1].ingroup = true;
1861 search[count].row = myrow;
1862 search[count].col = mycol-1;
1863 count++;
1867 if(mycol-1+adj >= 0) {
1868 if(myrow-1 >= 0) {
1869 if(bb->playboard[myrow-1][mycol-1+adj].type == mytype &&
1870 !bb->playboard[myrow-1][mycol-1+adj].ingroup) {
1871 bb->playboard[myrow-1][mycol-1+adj].ingroup = true;
1872 search[count].row = myrow-1;
1873 search[count].col = mycol-1+adj;
1874 count++;
1878 if(myrow+1 < BB_HEIGHT) {
1879 if(bb->playboard[myrow+1][mycol-1+adj].type == mytype &&
1880 !bb->playboard[myrow+1][mycol-1+adj].ingroup) {
1881 bb->playboard[myrow+1][mycol-1+adj].ingroup = true;
1882 search[count].row = myrow+1;
1883 search[count].col = mycol-1+adj;
1884 count++;
1889 if(mycol+adj >= 0) {
1890 if(myrow-1 >= 0) {
1891 if(bb->playboard[myrow-1][mycol+adj].type == mytype &&
1892 !bb->playboard[myrow-1][mycol+adj].ingroup) {
1893 bb->playboard[myrow-1][mycol+adj].ingroup = true;
1894 search[count].row = myrow-1;
1895 search[count].col = mycol+adj;
1896 count++;
1900 if(myrow+1 < BB_HEIGHT) {
1901 if(bb->playboard[myrow+1][mycol+adj].type == mytype &&
1902 !bb->playboard[myrow+1][mycol+adj].ingroup) {
1903 bb->playboard[myrow+1][mycol+adj].ingroup = true;
1904 search[count].row = myrow+1;
1905 search[count].col = mycol+adj;
1906 count++;
1911 if(mycol+1 < BB_WIDTH-adj) {
1912 if(bb->playboard[myrow][mycol+1].type == mytype &&
1913 !bb->playboard[myrow][mycol+1].ingroup) {
1914 bb->playboard[myrow][mycol+1].ingroup = true;
1915 search[count].row = myrow;
1916 search[count].col = mycol+1;
1917 count++;
1922 return count;
1925 /*****************************************************************************
1926 * bubbles_remove() removes all bubbles in the current group and all
1927 * unanchored bubbles from the play board.
1928 ******************************************************************************/
1929 static int bubbles_remove(struct game_context* bb) {
1930 int i, j;
1931 int buttonres;
1933 /* determine all anchored bubbles */
1934 for(j=0; j<BB_WIDTH; j++) {
1935 if(bb->playboard[0][j].type >= 0 && !bb->playboard[0][j].ingroup) {
1936 bubbles_anchored(bb, 0, j);
1940 /* mark bubbles to be deleted */
1941 for(i=0; i<BB_HEIGHT; i++) {
1942 for(j=0; j<BB_WIDTH; j++) {
1943 if(bb->playboard[i][j].type >= 0 &&
1944 (!bb->playboard[i][j].anchored || bb->playboard[i][j].ingroup)) {
1945 bb->playboard[i][j].delete = true;
1950 /* animate falling bubbles */
1951 buttonres = bubbles_fall(bb);
1952 if(buttonres != BB_NONE) return buttonres;
1954 /* remove bubbles */
1955 for(i=0; i<BB_HEIGHT; i++) {
1956 for(j=0; j<BB_WIDTH; j++) {
1957 if(bb->playboard[i][j].delete) {
1958 bb->playboard[i][j].ingroup = false;
1959 bb->playboard[i][j].type = -1;
1960 bb->playboard[i][j].delete = false;
1961 } else {
1962 bb->playboard[i][j].anchored = false;
1967 bubbles_getonboard(bb);
1969 return BB_NONE;
1972 /*****************************************************************************
1973 * bubbles_anchored() marks all bubbles that are anchored in some way to the
1974 * current bubble.
1975 ******************************************************************************/
1976 static void bubbles_anchored(struct game_context* bb, int row, int col) {
1977 int i, adj;
1978 int myrow, mycol;
1979 int count = 0;
1981 struct coord {
1982 int row;
1983 int col;
1984 } search[(2*BB_WIDTH-1)*(BB_HEIGHT/2)];
1986 /* search initial bubble */
1987 bb->playboard[row][col].anchored = true;
1988 search[count].row = row;
1989 search[count].col = col;
1990 count++;
1992 /* breadth-first search neighbors */
1993 for(i=0; i<count; i++) {
1994 myrow = search[i].row;
1995 mycol = search[i].col;
1996 adj = myrow%2;
1998 if(mycol-1 >= 0) {
1999 if(bb->playboard[myrow][mycol-1].type >= 0 &&
2000 !bb->playboard[myrow][mycol-1].ingroup &&
2001 !bb->playboard[myrow][mycol-1].anchored) {
2002 bb->playboard[myrow][mycol-1].anchored = true;
2003 search[count].row = myrow;
2004 search[count].col = mycol-1;
2005 count++;
2009 if(mycol-1+adj >= 0) {
2010 if(myrow-1 >= 0) {
2011 if(bb->playboard[myrow-1][mycol-1+adj].type >= 0 &&
2012 !bb->playboard[myrow-1][mycol-1+adj].ingroup &&
2013 !bb->playboard[myrow-1][mycol-1+adj].anchored) {
2014 bb->playboard[myrow-1][mycol-1+adj].anchored = true;
2015 search[count].row = myrow-1;
2016 search[count].col = mycol-1+adj;
2017 count++;
2021 if(myrow+1 < BB_HEIGHT) {
2022 if(bb->playboard[myrow+1][mycol-1+adj].type >= 0 &&
2023 !bb->playboard[myrow+1][mycol-1+adj].ingroup &&
2024 !bb->playboard[myrow+1][mycol-1+adj].anchored) {
2025 bb->playboard[myrow+1][mycol-1+adj].anchored = true;
2026 search[count].row = myrow+1;
2027 search[count].col = mycol-1+adj;
2028 count++;
2033 if(mycol+adj >= 0) {
2034 if(myrow-1 >= 0) {
2035 if(bb->playboard[myrow-1][mycol+adj].type >= 0 &&
2036 !bb->playboard[myrow-1][mycol+adj].ingroup &&
2037 !bb->playboard[myrow-1][mycol+adj].anchored) {
2038 bb->playboard[myrow-1][mycol+adj].anchored = true;
2039 search[count].row = myrow-1;
2040 search[count].col = mycol+adj;
2041 count++;
2045 if(myrow+1 < BB_HEIGHT) {
2046 if(bb->playboard[myrow+1][mycol+adj].type >= 0 &&
2047 !bb->playboard[myrow+1][mycol+adj].ingroup &&
2048 !bb->playboard[myrow+1][mycol+adj].anchored) {
2049 bb->playboard[myrow+1][mycol+adj].anchored = true;
2050 search[count].row = myrow+1;
2051 search[count].col = mycol+adj;
2052 count++;
2057 if(mycol+1 < BB_WIDTH-adj) {
2058 if(bb->playboard[myrow][mycol+1].type >= 0 &&
2059 !bb->playboard[myrow][mycol+1].ingroup &&
2060 !bb->playboard[myrow][mycol+1].anchored) {
2061 bb->playboard[myrow][mycol+1].anchored = true;
2062 search[count].row = myrow;
2063 search[count].col = mycol+1;
2064 count++;
2070 /*****************************************************************************
2071 * bubbles_fall() makes removed bubbles fall from the screen.
2072 ******************************************************************************/
2073 static int bubbles_fall(struct game_context* bb) {
2074 int i, j;
2075 int count;
2076 int indent;
2077 int xofs, yofs;
2078 int buttonres;
2079 bool onscreen;
2080 long lasttick, currenttick;
2082 /* give all falling bubbles an x axis movement */
2083 for(i=0; i<BB_HEIGHT; i++) {
2084 for(j=0; j<BB_WIDTH; j++) {
2085 if(bb->playboard[i][j].delete) {
2086 bb->playboard[i][j].fallx = rb->rand()%25 - 12;
2087 bb->playboard[i][j].fallvel = rb->rand()%5 + 6;
2092 /* draw bubbles falling off the screen
2093 * follows y=x^2-8x scaled to bubble size
2095 lasttick = *rb->current_tick;
2097 for(count=1; ;count++) {
2098 onscreen = false;
2099 bubbles_drawboard(bb);
2101 for(i=0; i<BB_HEIGHT; i++) {
2102 for(j=0; j<BB_WIDTH; j++) {
2103 if(bb->playboard[i][j].delete) {
2104 indent = (i%2 ? ROW_INDENT : 0);
2105 xofs = ((bb->playboard[i][j].fallx*count)*BUBBLE_WIDTH)/48;
2106 yofs = ((count*count - bb->playboard[i][j].fallvel*count)*
2107 BUBBLE_HEIGHT)/20;
2109 /* draw bubble if it is still on the screen */
2110 if(YOFS+ROW_HEIGHT*i+bb->compress*ROW_HEIGHT+yofs
2111 <= LCD_HEIGHT) {
2112 onscreen = true;
2114 rb->lcd_bitmap_part(bubbles_emblem, 0,
2115 EMBLEM_HEIGHT*bb->playboard[i][j].type,
2116 STRIDE( SCREEN_MAIN,
2117 BMPWIDTH_bubbles_emblem,
2118 BMPHEIGHT_bubbles_emblem),
2119 XOFS+indent+BUBBLE_WIDTH*j+
2120 (BUBBLE_WIDTH-EMBLEM_WIDTH)/2+xofs,
2121 YOFS+ROW_HEIGHT*i+(BUBBLE_HEIGHT-EMBLEM_HEIGHT)/2+
2122 bb->compress*ROW_HEIGHT+yofs,
2123 EMBLEM_WIDTH, EMBLEM_HEIGHT);
2124 rb->lcd_set_drawmode(DRMODE_FG);
2125 rb->lcd_mono_bitmap(
2126 (const unsigned char *)bubbles_bubble,
2127 XOFS+indent+BUBBLE_WIDTH*j+xofs,
2128 YOFS+ROW_HEIGHT*i+bb->compress*ROW_HEIGHT+yofs,
2129 BUBBLE_WIDTH, BUBBLE_HEIGHT);
2130 rb->lcd_set_drawmode(DRMODE_SOLID);
2136 rb->lcd_update();
2138 /* break out if all bubbles are off the screen */
2139 if(!onscreen) break;
2141 /* handle button events */
2142 buttonres = bubbles_handlebuttons(bb, true, 0);
2143 if(buttonres != BB_NONE) return buttonres;
2145 /* framerate limiting */
2146 currenttick = *rb->current_tick;
2147 if(currenttick-lasttick < HZ/MAX_FPS) {
2148 rb->sleep((HZ/MAX_FPS)-(currenttick-lasttick));
2149 } else {
2150 rb->yield();
2152 lasttick = currenttick;
2155 return BB_NONE;
2158 /*****************************************************************************
2159 * bubbles_checklevel() checks the state of the playboard for a win or loss.
2160 ******************************************************************************/
2161 static int bubbles_checklevel(struct game_context* bb) {
2162 int i, j;
2163 int points;
2164 char str[13];
2166 bubbles_drawboard(bb);
2167 rb->lcd_update();
2169 /* check for bubbles below cut off point */
2170 for(i=0; i<=bb->compress; i++) {
2171 for(j=0; j<BB_WIDTH; j++) {
2172 if(bb->playboard[BB_HEIGHT-1-i][j].type >= 0) return BB_LOSE;
2176 /* check for bubbles above cut off point */
2177 for(i=0; i<BB_HEIGHT-1-bb->compress; i++) {
2178 for(j=0; j<BB_WIDTH; j++) {
2179 if(bb->playboard[i][j].type >= 0) return BB_NONE;
2183 /* level complete, record score */
2184 points = 100 - bb->elapsedlvl/100;
2185 if(points > 0) {
2186 bb->score += points;
2187 } else {
2188 points = 0;
2191 rb->snprintf(str, 12, "%d points", points);
2192 rb->splash(HZ, str);
2194 /* advance to the next level */
2195 if(!bubbles_nextlevel(bb)) {
2196 return BB_WIN;
2199 bubbles_drawboard(bb);
2200 rb->lcd_update();
2201 rb->snprintf(str, 12, "Level %d", bb->level);
2202 rb->splash(HZ, str);
2203 bubbles_drawboard(bb);
2204 rb->lcd_update();
2206 return BB_NONE;
2209 /*****************************************************************************
2210 * bubbles_recordscore() inserts a high score into the high scores list and
2211 * returns the high score position.
2212 ******************************************************************************/
2213 static void bubbles_recordscore(struct game_context* bb) {
2215 int position;
2217 position = highscore_update(bb->score, bb->level-1, "",
2218 highscores, NUM_SCORES);
2219 if (position != -1)
2221 if (position == 0)
2222 rb->splash(HZ*2, "New High Score");
2223 highscore_show(position, highscores, NUM_SCORES, true);
2227 /*****************************************************************************
2228 * bubbles_loaddata() loads highest level beaten.
2229 ******************************************************************************/
2230 static void bubbles_loaddata(void) {
2231 int fd;
2233 last_highlevel = highlevel = 0;
2234 /* open data file */
2235 fd = rb->open(DATA_FILE, O_RDONLY);
2236 if (fd < 0) return;
2238 /* read in saved game */
2239 if (rb->read(fd, &highlevel, sizeof(highlevel)) < (long)sizeof(highlevel))
2241 highlevel = 0;
2243 if (highlevel >= NUM_LEVELS)
2244 highlevel = NUM_LEVELS-1;
2245 last_highlevel = highlevel;
2247 rb->close(fd);
2250 /*****************************************************************************
2251 * bubbles_savedata() saves the current game state.
2252 ******************************************************************************/
2253 static void bubbles_savedata(void) {
2254 int fd;
2256 if (last_highlevel >= highlevel) /* no need to save */
2257 return;
2259 fd = rb->open(DATA_FILE, O_WRONLY|O_CREAT, 0666);
2260 if (fd < 0) return;
2262 rb->write(fd, &highlevel, sizeof(highlevel));
2264 rb->close(fd);
2267 /*****************************************************************************
2268 * bubbles_loadgame() loads the saved game and returns load success.
2269 ******************************************************************************/
2270 static bool bubbles_loadgame(struct game_context* bb) {
2271 int fd;
2273 bool ret = true;
2274 /* open game file */
2275 fd = rb->open(SAVE_FILE, O_RDONLY);
2276 if(fd < 0) return false;
2278 /* read in saved game */
2279 if(rb->read(fd, bb, sizeof(struct game_context))
2280 < (long)sizeof(struct game_context))
2282 ret = false;
2285 rb->close(fd);
2287 return ret;
2290 /*****************************************************************************
2291 * bubbles_savegame() saves the current game state.
2292 ******************************************************************************/
2293 static void bubbles_savegame(struct game_context* bb) {
2294 int fd;
2296 if (!resume) /* nothing to save */
2297 return;
2298 /* write out the game state to the save file */
2299 fd = rb->open(SAVE_FILE, O_WRONLY|O_CREAT, 0666);
2300 if (fd < 0)
2302 rb->splash(HZ/2, "Failed to save game");
2303 return;
2305 if (rb->write(fd, bb, sizeof(struct game_context)) <= 0)
2307 rb->splash(HZ/2, "Failed to save game");
2310 rb->close(fd);
2313 /*****************************************************************************
2314 * bubbles_setcolors() set the foreground and background colors.
2315 ******************************************************************************/
2316 static inline void bubbles_setcolors(void) {
2317 #ifdef HAVE_LCD_COLOR
2318 rb->lcd_set_background(LCD_RGBPACK(181,181,222));
2319 rb->lcd_set_foreground(LCD_BLACK);
2320 #endif
2323 /*****************************************************************************
2324 * bubbles_callback() is the default event handler callback which is called
2325 * on usb connect and shutdown.
2326 ******************************************************************************/
2327 static void bubbles_callback(void* param) {
2328 (void) param;
2329 highscore_save(SCORE_FILE, highscores, NUM_SCORES);
2332 /*****************************************************************************
2333 * bubbles_handlebuttons() handles button events during a game.
2334 ******************************************************************************/
2335 static int bubbles_handlebuttons(struct game_context* bb, bool animblock,
2336 int timeout) {
2337 int button;
2338 int buttonres;
2339 long start;
2340 const struct button_mapping *plugin_contexts[]
2341 = { pla_main_ctx,
2342 #ifdef HAVE_REMOTE_LCD
2343 pla_remote_ctx,
2344 #endif
2347 if (timeout < 0)
2348 timeout = 0;
2349 button = pluginlib_getaction(timeout,plugin_contexts,ARRAYLEN(plugin_contexts));
2350 #if defined(HAS_BUTTON_HOLD) && !defined(HAVE_REMOTE_LCD_AS_MAIN)
2351 /* FIXME: Should probably check remote hold here */
2352 if (rb->button_hold())
2353 button = BUBBLES_PAUSE;
2354 #endif
2356 switch(button){
2357 case BUBBLES_LEFT_REP:
2358 if(bb->angle > MIN_ANGLE) bb->angle -= ANGLE_STEP_REP;
2359 case BUBBLES_LEFT: /* change angle to the left */
2360 if(bb->angle > MIN_ANGLE) bb->angle -= ANGLE_STEP;
2361 break;
2363 case BUBBLES_RIGHT_REP:
2364 if(bb->angle < MAX_ANGLE) bb->angle += ANGLE_STEP_REP;
2365 case BUBBLES_RIGHT: /* change angle to the right */
2366 if(bb->angle < MAX_ANGLE) bb->angle += ANGLE_STEP;
2367 break;
2369 case BUBBLES_FIRE: /* fire the shot */
2370 case BUBBLES_FIRE_REPEAT:
2371 if(!animblock) {
2372 bb->elapsedlvl += bb->elapsedshot;
2373 bb->elapsedshot = 0;
2374 buttonres = bubbles_fire(bb);
2375 if(buttonres != BB_NONE) return buttonres;
2376 buttonres = bubbles_checklevel(bb);
2377 if(buttonres != BB_NONE) return buttonres;
2378 bb->startedshot = *rb->current_tick;
2380 break;
2382 case BUBBLES_PAUSE: /* pause the game */
2383 start = *rb->current_tick;
2384 rb->splash(0, "Paused");
2386 while(pluginlib_getaction(TIMEOUT_BLOCK,plugin_contexts,
2387 ARRAYLEN(plugin_contexts))
2388 != BUBBLES_PAUSE);
2389 bb->startedshot += *rb->current_tick-start;
2390 bubbles_drawboard(bb);
2391 rb->lcd_update();
2392 break;
2394 case BUBBLES_QUIT1:
2395 case BUBBLES_QUIT2: /* end the game */
2396 if(!animblock) {
2397 resume = true;
2398 return BB_END;
2400 break;
2402 case ACTION_UNKNOWN:
2403 case ACTION_NONE: /* no button pressed */
2404 break;
2406 default:
2407 if(rb->default_event_handler_ex(button, bubbles_callback,
2408 (void*) bb) == SYS_USB_CONNECTED)
2409 return BB_USB;
2410 break;
2413 return BB_NONE;
2416 static int bubbles_menu_cb(int action, const struct menu_item_ex *this_item)
2418 int i = ((intptr_t)this_item);
2419 if(action == ACTION_REQUEST_MENUITEM
2420 && !resume && (i==0))
2421 return ACTION_EXIT_MENUITEM;
2422 return action;
2425 /*****************************************************************************
2426 * bubbles_menu() is the initial menu at the start of the game.
2427 ******************************************************************************/
2428 static int bubbles_menu(struct game_context* bb) {
2429 static unsigned int startlevel = 0;
2430 int selected = 0;
2431 bool startgame = false;
2433 MENUITEM_STRINGLIST(menu,"Bubbles Menu",bubbles_menu_cb,
2434 "Resume Game", "Start New Game",
2435 "Level", "High Scores", "Playback Control",
2436 "Quit without Saving", "Quit");
2438 while(!startgame){
2439 switch (rb->do_menu(&menu, &selected, NULL, false))
2441 case 0: /* resume game */
2442 startgame = true;
2443 if(resume_file)
2444 rb->remove(SAVE_FILE);
2445 resume_file = false;
2446 break;
2447 case 1: /* new game */
2448 bb->level = startlevel;
2449 startgame = true;
2450 resume = false;
2451 resume_file = false;
2452 break;
2453 case 2: /* choose level */
2454 startlevel++;
2455 rb->set_int("Choose start level", "", UNIT_INT, &startlevel,
2456 NULL, 1, 1, highlevel+1, NULL);
2457 startlevel--;
2458 break;
2459 case 3: /* High scores */
2460 highscore_show(-1, highscores, NUM_SCORES, true);
2461 break;
2462 case 4: /* Playback Control */
2463 playback_control(NULL);
2464 break;
2465 case 5: /* quit but don't save */
2466 return BB_QUIT_WITHOUT_SAVING;
2467 case 6: /* save and quit */
2468 return BB_QUIT;
2469 case MENU_ATTACHED_USB:
2470 bubbles_callback(bb);
2471 return BB_USB;
2474 return 0;
2477 /*****************************************************************************
2478 * bubbles() is the main game subroutine, it returns the final game status.
2479 ******************************************************************************/
2480 static int bubbles(struct game_context* bb) {
2481 int buttonres;
2482 long timeout;
2484 /********************
2485 * menu *
2486 ********************/
2487 buttonres = bubbles_menu(bb);
2488 if(buttonres != 0)
2489 return buttonres;
2491 /********************
2492 * init *
2493 ********************/
2494 bubbles_init(bb);
2495 bubbles_drawboard(bb);
2496 rb->lcd_update();
2498 /**********************
2499 * play *
2500 **********************/
2501 bb->startedshot = *rb->current_tick;
2503 while(true) {
2504 /* refresh the board */
2505 bubbles_drawboard(bb);
2506 rb->lcd_update();
2508 /* manange idle framerate */
2509 bb->elapsedshot = *rb->current_tick-bb->startedshot;
2511 if(MAX_SHOTTIME-bb->elapsedshot < HZ/2) {
2512 timeout = MAX_SHOTTIME-bb->elapsedshot;
2513 } else {
2514 timeout = HZ/2;
2517 /* handle button events */
2518 buttonres = bubbles_handlebuttons(bb, false, timeout);
2519 if(buttonres != BB_NONE) return buttonres;
2521 /* handle timing */
2522 bb->elapsedshot = *rb->current_tick-bb->startedshot;
2524 if(bb->elapsedshot > MAX_SHOTTIME) {
2525 bb->elapsedlvl += bb->elapsedshot;
2526 bb->elapsedshot = 0;
2527 buttonres = bubbles_fire(bb);
2528 if(buttonres != BB_NONE) return buttonres;
2529 buttonres = bubbles_checklevel(bb);
2530 if(buttonres != BB_NONE) return buttonres;
2531 bb->startedshot = *rb->current_tick;
2536 /*****************************************************************************
2537 * plugin entry point.
2538 ******************************************************************************/
2539 enum plugin_status plugin_start(const void* parameter) {
2540 static struct game_context bb;
2541 bool exit = false;
2542 enum plugin_status ret = PLUGIN_OK;
2544 (void)parameter;
2546 /* load files */
2547 resume = bubbles_loadgame(&bb);
2548 resume_file = resume;
2549 bubbles_loaddata();
2550 highscore_load(SCORE_FILE, highscores, NUM_SCORES);
2551 rb->lcd_clear_display();
2553 /* start app */
2554 #if LCD_DEPTH > 1
2555 rb->lcd_set_backdrop(NULL);
2556 #endif
2557 rb->lcd_setfont(FONT_SYSFIXED);
2559 while(!exit) {
2560 switch(bubbles(&bb)){
2561 case BB_WIN:
2562 rb->splash(HZ*2, "You Win!");
2563 /* record high level */
2564 highlevel = NUM_LEVELS-1;
2565 /* record high score */
2566 bubbles_recordscore(&bb);
2567 break;
2569 case BB_LOSE:
2570 resume = false;
2571 rb->splash(HZ*2, "Game Over");
2572 /* record high score */
2573 bubbles_recordscore(&bb);
2574 /* fall through to BB_END */
2576 case BB_END:
2577 break;
2579 case BB_USB:
2580 ret = PLUGIN_USB_CONNECTED;
2581 exit = true;
2582 break;
2584 case BB_QUIT:
2585 rb->splash(HZ/3, "Saving game data ...");
2586 bubbles_savegame(&bb);
2587 bubbles_savedata();
2588 highscore_save(SCORE_FILE, highscores, NUM_SCORES);
2589 /* fall through */
2591 case BB_QUIT_WITHOUT_SAVING:
2592 exit = true;
2593 break;
2595 default:
2596 break;
2599 rb->lcd_setfont(FONT_UI);
2600 return ret;