FS#12076 - DB stats resurrection: If the filename was changed, require
[kugel-rb.git] / apps / plugins / bubbles.c
blobd9f76f7f72901ef0d7b1815ba68bb0733f264e9b
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 #else
213 #error BUBBLES: Unsupported LCD type
214 #endif
216 #if !defined(ROW_HEIGHT)
217 #define ROW_HEIGHT (BUBBLE_WIDTH-(BUBBLE_WIDTH-EMBLEM_WIDTH)/2)
218 #endif
220 #if !defined(ROW_INDENT)
221 #define ROW_INDENT (BUBBLE_WIDTH/2)
222 #endif
224 #define TEXT_LINES (LCD_HEIGHT/8)
226 #ifndef YOFS
227 #define YOFS 0
228 #endif
230 /* shot position */
231 #define SHOTX XOFS+ROW_INDENT+BUBBLE_WIDTH*3
232 #define SHOTY (YOFS+ROW_HEIGHT*(BB_HEIGHT-1)+BUBBLE_HEIGHT/2)
234 /* collision distance squared */
235 #define MIN_DISTANCE ((BUBBLE_WIDTH*8)/10)*((BUBBLE_HEIGHT*8)/10)
237 /* levels */
238 char level[NUM_LEVELS][BB_LEVEL_HEIGHT][BB_WIDTH] = {
239 {{ 6, 6, 4, 4, 2, 2, 3, 3},
240 { 6, 6, 4, 4, 2, 2, 3, -1},
241 { 2, 2, 3, 3, 6, 6, 4, 4},
242 { 2, 3, 3, 6, 6, 4, 4, -1},
243 {-1, -1, -1, -1, -1, -1, -1, -1},
244 {-1, -1, -1, -1, -1, -1, -1, -1},
245 {-1, -1, -1, -1, -1, -1, -1, -1},
246 {-1, -1, -1, -1, -1, -1, -1, -1},
247 {-1, -1, -1, -1, -1, -1, -1, -1},
248 {-1, -1, -1, -1, -1, -1, -1, -1}},
249 {{-1, 7, 7, 7, 7, 7, 7, -1},
250 {-1, 1, 1, 1, 1, 1, -1, -1},
251 {-1, -1, 2, 2, 2, 2, -1, -1},
252 {-1, -1, -1, 2, -1, -1, -1, -1},
253 {-1, -1, -1, 2, 2, -1, -1, -1},
254 {-1, -1, -1, 5, -1, -1, -1, -1},
255 {-1, -1, -1, 5, 5, -1, -1, -1},
256 {-1, -1, -1, -1, -1, -1, -1, -1},
257 {-1, -1, -1, -1, -1, -1, -1, -1},
258 {-1, -1, -1, -1, -1, -1, -1, -1}},
259 {{-1, -1, 7, -1, -1, 7, -1, -1},
260 {-1, -1, 7, 1, 7, -1, -1, -1},
261 {-1, -1, -1, 1, 2, -1, -1, -1},
262 {-1, -1, 1, 2, 1, -1, -1, -1},
263 {-1, -1, -1, 2, 5, -1, -1, -1},
264 {-1, -1, 3, 5, 3, -1, -1, -1},
265 {-1, -1, -1, 5, 3, -1, -1, -1},
266 {-1, -1, -1, 3, -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, 0, 0, -1, -1, -1},
270 {-1, -1, 5, 0, 1, -1, -1, -1},
271 {-1, -1, 3, 5, 1, 6, -1, -1},
272 {-1, 4, 3, -1, 6, 7, -1, -1},
273 {-1, 7, 4, -1, -1, 7, 4, -1},
274 { 6, 7, -1, -1, -1, 4, 3, -1},
275 { 1, 6, -1, -1, -1, -1, 3, 5},
276 { 1, -1, -1, -1, -1, -1, 5, -1},
277 {-1, -1, -1, -1, -1, -1, -1, -1},
278 {-1, -1, -1, -1, -1, -1, -1, -1}},
279 {{-1, -1, 0, 0, 0, 0, -1, -1},
280 {-1, 0, 1, 1, 1, 0, -1, -1},
281 {-1, 0, 1, 0, 0, 1, 0, -1},
282 {-1, 0, 1, 1, 1, 0, -1, -1},
283 {-1, -1, 0, 0, 0, 0, -1, -1},
284 {-1, -1, 7, -1, 7, -1, -1, -1},
285 {-1, -1, 7, 7, 7, 7, -1, -1},
286 {-1, -1, -1, -1, -1, -1, -1, -1},
287 {-1, -1, -1, -1, -1, -1, -1, -1},
288 {-1, -1, -1, -1, -1, -1, -1, -1}},
289 {{-1, 4, 4, 4, 6, 6, 6, -1},
290 { 4, -1, -1, -1, -1, -1, 6, -1},
291 {-1, 4, -1, -1, -1, -1, 6, -1},
292 { 4, 2, 3, 1, 2, 3, 6, -1},
293 {-1, 3, 1, 2, 3, 1, 2, -1},
294 {-1, -1, -1, -1, -1, -1, -1, -1},
295 {-1, -1, -1, -1, -1, -1, -1, -1},
296 {-1, -1, -1, -1, -1, -1, -1, -1},
297 {-1, -1, -1, -1, -1, -1, -1, -1},
298 {-1, -1, -1, -1, -1, -1, -1, -1}},
299 {{-1, 4, 4, 4, 6, 6, 6, -1},
300 { 4, -1, -1, -1, -1, -1, 6, -1},
301 {-1, 4, -1, -1, -1, -1, 6, -1},
302 { 4, 2, 3, 1, 2, 3, 6, -1},
303 {-1, 3, 1, 2, 3, 1, 2, -1},
304 {-1, 2, 3, 1, 2, 3, -1, -1},
305 {-1, -1, -1, -1, -1, -1, -1, -1},
306 {-1, -1, -1, -1, -1, -1, -1, -1},
307 {-1, -1, -1, -1, -1, -1, -1, -1},
308 {-1, -1, -1, -1, -1, -1, -1, -1}},
309 {{-1, 0, 0, -1, -1, 2, 2, -1},
310 {-1, 5, -1, -1, -1, 3, -1, -1},
311 {-1, 0, -1, -1, -1, 6, -1, -1},
312 {-1, 3, -1, -1, -1, 0, -1, -1},
313 {-1, 4, -1, -1, -1, 5, -1, -1},
314 {-1, 2, -1, -1, -1, 3, -1, -1},
315 {-1, 2, -1, -1, -1, 1, -1, -1},
316 {-1, 3, -1, -1, -1, 4, -1, -1},
317 {-1, -1, -1, -1, -1, -1, -1, -1},
318 {-1, -1, -1, -1, -1, -1, -1, -1}},
319 {{ 3, -1, -1, -1, -1, -1, -1, 3},
320 { 6, 3, 2, 4, 6, 3, 2, -1},
321 { 4, -1, -1, -1, -1, -1, -1, 4},
322 { 2, 4, 6, 3, 2, 4, 6, -1},
323 {-1, -1, -1, 6, -1, -1, -1, -1},
324 {-1, -1, -1, 3, -1, -1, -1, -1},
325 {-1, -1, -1, -1, -1, -1, -1, -1},
326 {-1, -1, -1, -1, -1, -1, -1, -1},
327 {-1, -1, -1, -1, -1, -1, -1, -1},
328 {-1, -1, -1, -1, -1, -1, -1, -1}},
329 {{-1, 2, -1, 1, -1, 1, -1, 2},
330 { 1, 2, -1, 2, 1, -1, 1, -1},
331 { 1, -1, 1, -1, 2, -1, 2, -1},
332 { 2, 1, -1, 1, 2, -1, 2, -1},
333 {-1, 2, -1, 2, -1, 2, -1, 2},
334 { 1, 2, -1, 2, 1, -1, 1, -1},
335 { 1, -1, 1, -1, 2, -1, 1, -1},
336 { 2, 2, -1, 1, 1, -1, 2, -1},
337 {-1, 2, -1, 1, -1, 1, -1, 1},
338 {-1, -1, -1, -1, -1, -1, -1, -1}},
339 {{-1, 7, 7, -1, -1, 5, 5, -1},
340 { 1, -1, -1, -1, -1, -1, 4, -1},
341 { 2, 1, -1, -1, -1, -1, 4, 3},
342 { 2, -1, -1, -1, -1, -1, 3, -1},
343 { 1, 2, -1, -1, -1, -1, 3, 4},
344 { 1, -1, -1, -1, -1, -1, 4, -1},
345 { 7, 1, -1, -1, -1, -1, 4, 5},
346 { 7, 7, -1, -1, -1, 5, 5, -1},
347 {-1, -1, -1, -1, -1, -1, -1, -1},
348 {-1, -1, -1, -1, -1, -1, -1, -1}},
349 {{ 7, 7, -1, -1, -1, -1, 5, 5},
350 { 1, 5, -1, -1, -1, 7, 4, -1},
351 { 2, 1, -1, -1, -1, -1, 4, 3},
352 { 2, -1, -1, -1, -1, -1, 3, -1},
353 { 1, 5, -1, -1, -1, -1, 7, 4},
354 { 1, -1, -1, -1, -1, -1, 4, -1},
355 { 7, 1, -1, -1, -1, -1, 4, 5},
356 { 7, 5, -1, -1, -1, 7, 5, -1},
357 {-1, -1, -1, -1, -1, -1, -1, -1},
358 {-1, -1, -1, -1, -1, -1, -1, -1}},
359 {{-1, -1, -1, 0, 0, -1, -1, -1},
360 {-1, -1, 5, 0, 1, -1, -1, -1},
361 {-1, -1, 3, 5, 1, 6, -1, -1},
362 {-1, 4, 3, 2, 6, 2, -1, -1},
363 {-1, 7, 4, 7, 2, 2, 4, -1},
364 { 6, 7, 7, 3, 3, 4, 3, -1},
365 { 1, 6, 1, 1, 1, 3, 3, 5},
366 { 1, 1, -1, -1, -1, -1, 5, -1},
367 {-1, -1, -1, -1, -1, -1, -1, -1},
368 {-1, -1, -1, -1, -1, -1, -1, -1}},
369 {{-1, -1, 0, -1, -1, 0, -1, -1},
370 {-1, 3, 3, -1, 3, 3, -1, -1},
371 {-1, 0, 2, 0, 0, 2, 0, -1},
372 {-1, 3, 3, -1, 3, 3, -1, -1},
373 {-1, -1, 0, -1, -1, 0, -1, -1},
374 {-1, -1, -1, -1, -1, -1, -1, -1},
375 {-1, -1, -1, -1, -1, -1, -1, -1},
376 {-1, -1, -1, -1, -1, -1, -1, -1},
377 {-1, -1, -1, -1, -1, -1, -1, -1},
378 {-1, -1, -1, -1, -1, -1, -1, -1}},
379 {{-1, -1, -1, 1, 1, -1, -1, -1},
380 {-1, -1, 2, 2, 2, -1, -1, -1},
381 {-1, -1, 3, 3, 3, 3, -1, -1},
382 {-1, 4, 4, 4, 4, 4, -1, -1},
383 {-1, 5, 5, 5, 5, 5, 5, -1},
384 {-1, -1, -1, 6, -1, -1, -1, -1},
385 {-1, -1, -1, 7, 7, -1, -1, -1},
386 {-1, -1, -1, 0, -1, -1, -1, -1},
387 {-1, -1, -1, -1, -1, -1, -1, -1},
388 {-1, -1, -1, -1, -1, -1, -1, -1}},
389 {{-1, -1, -1, 2, 5, -1, -1, -1},
390 {-1, 4, 3, -1, -1, -1, -1, -1},
391 { 6, 7, -1, 5, 2, -1, -1, -1},
392 {-1, -1, -1, -1, 3, 4, -1, -1},
393 {-1, -1, -1, 2, 5, -1, 7, 6},
394 {-1, 4, 3, -1, -1, -1, -1, -1},
395 { 6, 7, -1, 5, 2, -1, -1, -1},
396 {-1, -1, -1, -1, 3, 4, -1, -1},
397 {-1, -1, -1, -1, -1, -1, 7, 6},
398 {-1, -1, -1, -1, -1, -1, -1, -1}},
399 {{-1, -1, -1, 5, 5, -1, -1, -1},
400 {-1, -1, -1, 3, -1, -1, -1, -1},
401 {-1, -1, -1, 1, -1, -1, -1, -1},
402 {-1, -1, -1, 7, -1, -1, -1, -1},
403 {-1, -1, -1, 2, -1, -1, -1, -1},
404 {-1, -1, -1, 4, -1, -1, -1, -1},
405 {-1, -1, -1, 5, -1, -1, -1, -1},
406 {-1, -1, -1, 3, -1, -1, -1, -1},
407 {-1, -1, -1, -1, -1, -1, -1, -1},
408 {-1, -1, -1, -1, -1, -1, -1, -1}},
409 {{-1, -1, -1, 0, 1, -1, -1, -1},
410 {-1, -1, 0, 2, 7, 7, -1, -1},
411 {-1, -1, -1, 0, 1, 7, -1, -1},
412 {-1, 0, 0, 0, 0, -1, -1, -1},
413 {-1, 0, 0, 0, 1, 1, -1, -1},
414 { 0, 0, 0, 1, 1, 1, -1, -1},
415 {-1, 0, 0, 1, 1, 1, -1, -1},
416 {-1, 0, 0, 0, 7, 7, -1, -1},
417 {-1, -1, 7, 7, -1, -1, -1, -1},
418 {-1, -1, -1, -1, -1, -1, -1, -1}},
419 {{-1, 1, -1, -1, -1, -1, -1, -1},
420 { 1, -1, -1, -1, -1, -1, -1, -1},
421 {-1, 2, 3, 4, 7, 6, 5, -1},
422 {-1, -1, -1, -1, -1, -1, 1, -1},
423 {-1, -1, -1, -1, -1, -1, 1, -1},
424 {-1, 2, 3, 4, 7, 6, -1, -1},
425 {-1, 1, -1, -1, -1, -1, -1, -1},
426 { 1, -1, -1, -1, -1, -1, -1, -1},
427 {-1, 2, 3, 4, 7, 6, 5, -1},
428 {-1, -1, -1, -1, -1, -1, -1, -1}},
429 {{-1, 6, -1, -1, -1, -1, -1, -1},
430 { 5, -1, -1, -1, -1, -1, -1, -1},
431 { 2, 3, 4, 7, 6, 5, 2, 3},
432 {-1, -1, -1, -1, -1, -1, 4, -1},
433 {-1, -1, -1, -1, -1, -1, 7, -1},
434 {-1, 4, 3, 2, 5, 6, -1, -1},
435 {-1, 7, -1, -1, -1, -1, -1, -1},
436 { 6, -1, -1, -1, -1, -1, -1, -1},
437 { 5, 2, 3, 4, 7, 6, 5, -1},
438 {-1, -1, -1, -1, -1, -1, -1, -1}},
439 {{ 3, 2, 1, 0, 0, 1, 2, 3},
440 { 3, 2, 1, 0, 1, 2, 3, -1},
441 { 4, 3, 2, 1, 1, 2, 3, 4},
442 { 4, 3, 2, 1, 2, 3, 4, -1},
443 { 5, 4, 3, 2, 2, 3, 4, 5},
444 { 5, 4, 3, 2, 3, 4, 5, -1},
445 { 6, 5, 4, 3, 3, 4, 5, 6},
446 { 6, 5, 4, 3, 4, 5, 6, -1},
447 { 7, 6, 5, 4, 4, 5, 6, 7},
448 {-1, -1, -1, -1, -1, -1, -1, -1}},
449 {{-1, -1, -1, 5, 5, -1, -1, -1},
450 {-1, -1, -1, 3, -1, -1, -1, -1},
451 {-1, -1, -1, 2, 4, -1, -1, -1},
452 {-1, -1, -1, 6, -1, -1, -1, -1},
453 {-1, -1, -1, 2, 4, -1, -1, -1},
454 {-1, 2, -1, 5, -1, 4, -1, -1},
455 { 1, 0, 1, 0, 1, 0, 1, 0},
456 { 3, -1, 3, -1, 2, -1, 6, -1},
457 {-1, -1, -1, -1, -1, -1, -1, -1},
458 {-1, -1, -1, -1, -1, -1, -1, -1}},
459 {{-1, -1, -1, -1, 1, -1, -1, -1},
460 { 7, 4, 3, 5, -1, -1, -1, -1},
461 { 6, -1, -1, 1, -1, -1, -1, -1},
462 {-1, -1, -1, 5, 3, 4, 7, -1},
463 { 6, -1, -1, -1, 1, -1, -1, 6},
464 { 7, 4, 3, 5, -1, -1, -1, -1},
465 {-1, -1, -1, 1, -1, -1, -1, 6},
466 {-1, -1, -1, 5, 3, 4, 7, -1},
467 {-1, -1, -1, -1, -1, -1, -1, -1},
468 {-1, -1, -1, -1, -1, -1, -1, -1}},
469 {{-1, -1, -1, -1, 7, 3, 6, -1},
470 {-1, -1, 3, 7, 3, 6, 3, -1},
471 {-1, -1, 5, 7, 3, 6, 3, -1},
472 {-1, 6, 7, 3, 6, 7, -1, -1},
473 {-1, 7, 7, 3, 6, 1, -1, -1},
474 { 3, 7, 3, 6, 3, -1, -1, -1},
475 { 5, 6, 2, 7, 1, -1, -1, -1},
476 {-1, -1, -1, -1, -1, -1, -1, -1},
477 {-1, -1, -1, -1, -1, -1, -1, -1},
478 {-1, -1, -1, -1, -1, -1, -1, -1}},
479 {{ 5, -1, -1, -1, -1, -1, -1, 5},
480 { 5, -1, 6, 6, 6, -1, 5, -1},
481 {-1, 5, 4, -1, -1, 4, 5, -1},
482 {-1, 3, -1, -1, -1, 3, -1, -1},
483 {-1, 6, 0, -1, -1, 0, 6, -1},
484 {-1, 3, -1, -1, -1, 3, -1, -1},
485 {-1, -1, 4, -1, -1, 4, -1, -1},
486 {-1, -1, 6, 6, 6, -1, -1, -1},
487 {-1, -1, -1, -1, -1, -1, -1, -1},
488 {-1, -1, -1, -1, -1, -1, -1, -1}},
489 {{-1, 7, 0, -1, -1, 0, 7, -1},
490 { 7, -1, 0, -1, 0, -1, 7, -1},
491 { 7, 1, -1, 0, 0, -1, 1, 7},
492 { 7, 1, 2, 0, 2, 1, 7, -1},
493 { 7, 6, 3, 2, 2, 3, 6, 7},
494 { 7, -1, 3, 2, 3, -1, 7, -1},
495 {-1, 7, 7, 3, 3, 7, 7, -1},
496 {-1, -1, -1, 3, -1, -1, -1, -1},
497 {-1, -1, -1, -1, -1, -1, -1, -1},
498 {-1, -1, -1, -1, -1, -1, -1, -1}},
499 {{-1, 3, -1, 1, -1, 7, -1, 6},
500 { 5, -1, 7, -1, 7, -1, 6, -1},
501 { 6, -1, 0, -1, 5, -1, 3, -1},
502 {-1, 2, -1, 1, -1, 5, -1, -1},
503 {-1, 4, -1, 3, -1, 4, -1, -1},
504 { 2, -1, 3, -1, 2, -1, -1, -1},
505 {-1, -1, 4, -1, 6, -1, -1, -1},
506 {-1, -1, -1, 5, -1, -1, -1, -1},
507 {-1, -1, -1, -1, -1, -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, 3, -1, -1, -1},
511 { 6, 1, 3, 1, 2, 1, 4, 1},
512 {-1, -1, -1, -1, 6, -1, -1, -1},
513 {-1, -1, -1, 4, 1, -1, -1, -1},
514 {-1, -1, 1, -1, 3, -1, -1, -1},
515 {-1, -1, -1, 2, 1, -1, -1, -1},
516 {-1, -1, -1, -1, 4, -1, -1, -1},
517 {-1, -1, -1, 6, 1, -1, -1, -1},
518 {-1, -1, -1, 6, -1, -1, -1, -1}},
519 {{-1, -1, -1, 5, 4, -1, -1, -1},
520 {-1, -1, 4, 1, 0, -1, -1, -1},
521 {-1, -1, -1, 2, 3, -1, -1, -1},
522 {-1, 1, 4, -1, 2, 2, -1, -1},
523 {-1, 3, 1, 2, 5, 1, 4, -1},
524 {-1, 4, 2, -1, 0, 4, -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, -1, -1, -1, -1},
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, 2, -1, -1, 1, -1, 5, -1},
532 { 5, -1, -1, 1, -1, -1, 0, -1},
533 {-1, 6, -1, -1, 1, -1, 4, -1},
534 {-1, 0, -1, 1, -1, 5, -1, -1},
535 {-1, -1, 5, 5, 0, 1, -1, -1},
536 {-1, -1, -1, -1, -1, -1, -1, -1},
537 {-1, -1, -1, -1, -1, -1, -1, -1},
538 {-1, -1, -1, -1, -1, -1, -1, -1}},
539 {{-1, -1, -1, 6, 3, -1, -1, -1},
540 {-1, -1, 3, 2, 6, -1, -1, -1},
541 {-1, -1, 2, 6, 3, 2, -1, -1},
542 {-1, 6, 3, 2, 6, 3, -1, -1},
543 {-1, 3, 2, 6, 3, 2, 6, -1},
544 { 2, 6, 3, 2, 6, 3, 2, -1},
545 { 6, 3, 2, 6, 3, 2, 6, 3},
546 {-1, -1, -1, -1, -1, -1, -1, -1},
547 {-1, -1, -1, -1, -1, -1, -1, -1},
548 {-1, -1, -1, -1, -1, -1, -1, -1}},
549 {{ 6, 6, 6, 6, 6, 6, 6, 6},
550 { 4, -1, -1, -1, -1, -1, -1, -1},
551 {-1, 3, 2, 5, 7, 6, 4, 3},
552 {-1, 5, -1, -1, -1, -1, -1, -1},
553 {-1, -1, 7, 6, 4, 3, 2, 5},
554 {-1, -1, 4, -1, -1, -1, -1, -1},
555 {-1, -1, -1, 3, 2, 5, 7, 6},
556 {-1, -1, -1, -1, -1, -1, -1, -1},
557 {-1, -1, -1, -1, -1, -1, -1, -1},
558 {-1, -1, -1, -1, -1, -1, -1, -1}},
559 {{ 1, -1, 7, -1, -1, 6, -1, 2},
560 { 6, -1, 1, -1, 6, 1, 3, -1},
561 {-1, 4, -1, 7, 2, -1, 7, -1},
562 { 2, 7, -1, -1, -1, 4, -1, -1},
563 { 6, -1, 3, 5, 0, 2, -1, 7},
564 { 1, -1, -1, -1, -1, -1, 1, -1},
565 {-1, 1, 4, 5, 7, 5, 1, -1},
566 {-1, -1, -1, -1, -1, -1, -1, -1},
567 {-1, -1, -1, -1, -1, -1, -1, -1},
568 {-1, -1, -1, -1, -1, -1, -1, -1}},
569 {{ 6, 6, 6, -1, -1, 6, 6, 6},
570 {-1, -1, 6, -1, 6, -1, -1, -1},
571 {-1, -1, 2, 3, 3, 2, -1, -1},
572 {-1, 3, -1, 5, -1, 3, -1, -1},
573 {-1, -1, 5, 3, 3, 5, -1, -1},
574 {-1, -1, 6, 1, 6, -1, -1, -1},
575 {-1, 4, 2, -1, -1, 2, 4, -1},
576 {-1, -1, -1, -1, -1, -1, -1, -1},
577 {-1, -1, -1, -1, -1, -1, -1, -1},
578 {-1, -1, -1, -1, -1, -1, -1, -1}},
579 {{-1, -1, -1, 5, 5, -1, -1, -1},
580 {-1, -1, 5, -1, -1, -1, -1, -1},
581 {-1, 3, 4, 6, 6, -1, -1, 5},
582 { 3, 3, 4, 6, 5, -1, 5, -1},
583 { 3, 2, 3, 6, 6, 5, 5, -1},
584 { 3, 3, 4, 6, 5, -1, 5, -1},
585 {-1, 3, 4, 6, 6, -1, -1, 5},
586 {-1, -1, 5, -1, -1, -1, -1, -1},
587 {-1, -1, -1, 5, 5, -1, -1, -1},
588 {-1, -1, -1, -1, -1, -1, -1, -1}},
589 {{ 1, -1, -1, -1, -1, -1, -1, 1},
590 { 1, -1, 2, 2, 2, -1, 1, -1},
591 {-1, 1, 2, 3, 3, 2, 1, -1},
592 { 6, 2, 3, -1, 3, 2, 6, -1},
593 { 6, 2, 3, -1, -1, 3, 2, 6},
594 { 6, 2, 3, -1, 3, 2, 6, -1},
595 { 3, 3, 3, 7, 7, 3, 3, 3},
596 { 0, 5, 0, 2, 0, 5, 0, -1},
597 {-1, -1, -1, -1, -1, -1, -1, -1},
598 {-1, -1, -1, -1, -1, -1, -1, -1}},
599 {{-1, -1, 7, 7, 7, -1, -1, -1},
600 {-1, 7, 2, 2, 7, -1, -1, -1},
601 {-1, 7, 5, 5, 5, 7, -1, -1},
602 { 7, 7, 7, 7, 7, 7, -1, -1},
603 {-1, -1, 6, -1, 6, -1, -1, -1},
604 {-1, 6, -1, -1, 6, -1, -1, -1},
605 {-1, 6, 4, 4, -1, 6, 4, 4},
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, 3, 3, -1, 3, 3, 3, -1},
610 { 3, 7, 5, 4, 6, 5, 3, -1},
611 { 1, 3, 3, 3, -1, 3, 3, 1},
612 { 2, 1, 2, 1, 2, 1, 2, -1},
613 { 1, 3, 3, -1, 3, 3, 3, 1},
614 { 3, 5, 6, 4, 5, 7, 3, -1},
615 { 2, 3, 3, 3, -1, 3, 3, 2},
616 { 1, 1, 2, 2, 2, 1, 1, -1},
617 {-1, -1, -1, -1, -1, -1, -1, -1},
618 {-1, -1, -1, -1, -1, -1, -1, -1}},
619 {{-1, 6, 5, -1, -1, -1, -1, -1},
620 { 3, 1, 3, -1, -1, -1, -1, -1},
621 {-1, 5, 6, -1, -1, -1, -1, -1},
622 {-1, -1, 5, 3, -1, -1, -1, -1},
623 {-1, -1, 6, 1, 6, -1, -1, -1},
624 {-1, -1, 3, 5, -1, -1, -1, -1},
625 {-1, -1, -1, -1, 3, 6, -1, -1},
626 {-1, -1, -1, 5, 6, 5, -1, -1},
627 {-1, -1, -1, -1, 6, 3, -1, -1},
628 {-1, -1, -1, -1, -1, -1, -1, -1}},
629 {{ 6, 3, 7, 4, 5, 1, 6, 3},
630 { 5, 1, 6, 3, 7, 4, 5, -1},
631 { 6, 3, 7, 4, 5, 1, 6, 3},
632 {-1, -1, -1, -1, -1, -1, -1, -1},
633 {-1, -1, -1, -1, -1, -1, -1, -1},
634 {-1, -1, -1, -1, -1, -1, -1, -1},
635 {-1, -1, -1, -1, -1, -1, -1, -1},
636 {-1, -1, -1, -1, -1, -1, -1, -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, 4, 4},
640 {-1, -1, 7, 7, 7, 4, 4, -1},
641 {-1, -1, -1, -1, -1, -1, 4, 4},
642 {-1, 1, -1, -1, -1, 7, -1, -1},
643 {-1, 1, 1, -1, -1, 7, -1, -1},
644 { 3, 3, 3, -1, 7, -1, -1, -1},
645 { 3, -1, 2, 3, 3, 3, -1, 3},
646 {-1, 2, -1, 3, -1, 3, 3, -1},
647 {-1, 2, -1, -1, -1, -1, -1, -1},
648 {-1, -1, -1, -1, -1, -1, -1, -1}},
649 {{-1, -1, 4, -1, -1, -1, -1, -1},
650 {-1, 7, 4, -1, -1, -1, -1, -1},
651 {-1, -1, 7, 4, -1, -1, -1, -1},
652 {-1, 4, 7, 4, -1, -1, -1, -1},
653 { 1, 1, 1, 1, 1, 1, 1, -1},
654 { 1, 2, 1, 2, 1, 1, -1, -1},
655 { 2, 2, 2, 2, 2, 2, 2, 2},
656 {-1, -1, -1, -1, -1, -1, -1, -1},
657 {-1, -1, -1, -1, -1, -1, -1, -1},
658 {-1, -1, -1, -1, -1, -1, -1, -1}},
659 {{ 0, -1, -1, -1, -1, -1, -1, 6},
660 { 6, 1, 4, 3, 7, 5, 0, -1},
661 { 0, -1, -1, -1, -1, -1, -1, 6},
662 { 6, 1, 4, 3, 7, 5, 0, -1},
663 { 0, -1, -1, -1, -1, -1, -1, 6},
664 { 6, 1, 4, 3, 7, 5, 0, -1},
665 {-1, -1, -1, -1, -1, -1, -1, -1},
666 {-1, -1, -1, -1, -1, -1, -1, -1},
667 {-1, -1, -1, -1, -1, -1, -1, -1},
668 {-1, -1, -1, -1, -1, -1, -1, -1}},
669 {{ 3, 3, 4, 6, 6, 4, 3, 3},
670 { 0, 3, 4, 6, 4, 3, 1, -1},
671 { 5, 1, 3, 4, 4, 3, 0, 1},
672 { 0, 1, 3, 4, 3, 1, 0, -1},
673 { 2, 1, 6, 3, 3, 0, 0, 1},
674 { 0, 3, 4, 3, 6, 1, 5, -1},
675 { 6, 1, 2, 6, 4, 0, 0, 2},
676 {-1, -1, -1, -1, -1, -1, -1, -1},
677 {-1, -1, -1, -1, -1, -1, -1, -1},
678 {-1, -1, -1, -1, -1, -1, -1, -1}},
679 {{ 6, 6, -1, -1, -1, -1, 4, 4},
680 { 4, 0, -1, -1, -1, 3, 6, -1},
681 { 0, 6, -1, -1, -1, -1, 4, 2},
682 { 7, -1, -1, -1, -1, -1, 7, -1},
683 { 4, 4, -1, -1, -1, -1, 5, 6},
684 { 6, 4, 7, 7, 5, 6, 4, -1},
685 {-1, 7, 6, 4, 6, 4, 7, -1},
686 {-1, 0, -1, 7, -1, 7, -1, -1},
687 {-1, -1, -1, -1, -1, -1, -1, -1},
688 {-1, -1, -1, -1, -1, -1, -1, -1}},
689 {{-1, 5, -1, -1, -1, -1, 4, -1},
690 {-1, 5, -1, -1, -1, 4, -1, -1},
691 {-1, -1, 5, 6, 6, 4, -1, -1},
692 {-1, -1, 2, -1, 2, -1, -1, -1},
693 { 0, 0, 6, -1, -1, 6, 1, 1},
694 {-1, -1, 2, -1, 2, -1, -1, -1},
695 {-1, -1, 7, 6, 6, 3, -1, -1},
696 {-1, 7, -1, -1, -1, 3, -1, -1},
697 {-1, 7, -1, -1, -1, -1, 3, -1},
698 {-1, -1, -1, -1, -1, -1, -1, -1}},
699 {{-1, 6, -1, -1, -1, -1, 2, -1},
700 { 1, 7, 1, 1, 1, 3, 1, -1},
701 {-1, -1, 4, 1, 1, 4, -1, -1},
702 {-1, 1, 3, 1, 7, 1, -1, -1},
703 {-1, -1, -1, 2, 6, -1, -1, -1},
704 {-1, -1, 1, 5, 1, -1, -1, -1},
705 {-1, -1, -1, -1, -1, -1, -1, -1},
706 {-1, -1, -1, -1, -1, -1, -1, -1},
707 {-1, -1, -1, -1, -1, -1, -1, -1},
708 {-1, -1, -1, -1, -1, -1, -1, -1}},
709 {{ 7, 7, 7, 7, 7, 7, 7, 7},
710 { 7, -1, -1, -1, -1, -1, 7, -1},
711 { 7, -1, -1, 2, 0, 5, 2, 2},
712 { 7, -1, -1, -1, 0, 3, 6, -1},
713 { 7, -1, -1, -1, -1, -1, 4, 0},
714 { 5, 5, -1, -1, -1, -1, -1, -1},
715 { 4, 3, 6, 2, -1, -1, -1, -1},
716 { 0, 2, 0, 4, -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, 4, -1, -1, 5, -1, -1, -1},
721 {-1, 7, -1, -1, 1, 1, 1, -1},
722 { 6, -1, -1, -1, -1, 7, -1, -1},
723 { 1, 1, 1, 1, -1, 4, -1, -1},
724 {-1, -1, 5, -1, -1, -1, -1, -1},
725 {-1, -1, 0, -1, -1, -1, -1, -1},
726 {-1, 3, -1, -1, -1, -1, -1, -1},
727 {-1, 1, -1, -1, -1, -1, -1, -1},
728 {-1, -1, -1, -1, -1, -1, -1, -1}},
729 {{-1, 7, 7, -1, -1, 7, 7, -1},
730 { 6, -1, 4, -1, 4, -1, 6, -1},
731 { 5, -1, -1, 3, 3, -1, -1, 5},
732 { 6, -1, -1, -1, -1, -1, 6, -1},
733 {-1, 7, -1, -1, -1, -1, 7, -1},
734 {-1, 4, -1, -1, -1, 4, -1, -1},
735 {-1, -1, 3, -1, -1, 3, -1, -1},
736 {-1, -1, 2, -1, 2, -1, -1, -1},
737 {-1, -1, -1, 5, 5, -1, -1, -1},
738 {-1, -1, -1, -1, -1, -1, -1, -1}},
739 {{-1, 0, 0, -1, -1, 0, 0, -1},
740 { 7, 4, 6, 6, 6, 4, 3, -1},
741 { 5, 6, 6, 6, 2, 6, 6, 3},
742 { 7, 4, 6, 6, 6, 4, 3, -1},
743 {-1, 0, 0, -1, -1, 0, 0, -1},
744 {-1, -1, -1, -1, -1, -1, -1, -1},
745 {-1, -1, -1, -1, -1, -1, -1, -1},
746 {-1, -1, -1, -1, -1, -1, -1, -1},
747 {-1, -1, -1, -1, -1, -1, -1, -1},
748 {-1, -1, -1, -1, -1, -1, -1, -1}},
749 {{-1, -1, -1, -1, -1, 7, 7, 7},
750 {-1, -1, -1, -1, 2, 7, 7, -1},
751 {-1, 0, 7, 7, 7, -1, 7, 7},
752 { 6, 7, 7, 7, -1, -1, -1, -1},
753 { 6, -1, -1, -1, 7, 7, 7, 7},
754 { 6, -1, -1, -1, -1, -1, -1, -1},
755 { 4, 2, 2, 2, 4, -1, 3, -1},
756 { 4, 4, 4, 4, 3, 3, 3, -1},
757 {-1, -1, -1, -1, -1, -1, -1, -1},
758 {-1, -1, -1, -1, -1, -1, -1, -1}},
759 {{ 4, -1, -1, 7, -1, 6, -1, 7},
760 { 7, 6, 7, -1, -1, 7, 4, -1},
761 {-1, -1, 7, -1, -1, 7, -1, -1},
762 {-1, 0, 0, 0, 0, 0, 3, -1},
763 {-1, -1, 0, 2, 2, 0, 6, 4},
764 {-1, -1, 0, 0, 0, 1, 3, -1},
765 {-1, -1, -1, 0, 0, -1, 3, 4},
766 {-1, -1, -1, 6, -1, 5, 6, -1},
767 {-1, -1, -1, -1, -1, -1, 1, 0},
768 {-1, -1, -1, -1, -1, -1, -1, -1}},
769 {{-1, 5, -1, -1, -1, -1, 5, -1},
770 { 0, -1, -1, 0, -1, -1, 0, -1},
771 { 0, 0, 0, 2, 2, 0, 0, 0},
772 { 0, -1, -1, 0, -1, -1, 0, -1},
773 {-1, 7, -1, 3, -1, -1, 7, -1},
774 {-1, -1, 3, 6, -1, -1, -1, -1},
775 {-1, -1, -1, 6, -1, -1, -1, -1},
776 {-1, 3, 6, -1, -1, -1, -1, -1},
777 {-1, 3, -1, -1, -1, -1, -1, -1},
778 {-1, -1, -1, -1, -1, -1, -1, -1}},
779 {{-1, -1, -1, 6, 5, -1, -1, -1},
780 {-1, -1, 2, 6, 3, -1, -1, -1},
781 {-1, -1, 5, 4, 7, 1, -1, -1},
782 {-1, 6, 2, 2, 3, 4, -1, -1},
783 {-1, -1, 3, 7, 3, 6, -1, -1},
784 {-1, -1, 1, 3, 2, -1, -1, -1},
785 {-1, -1, -1, 4, 5, -1, -1, -1},
786 {-1, -1, -1, 4, -1, -1, -1, -1},
787 {-1, -1, -1, -1, -1, -1, -1, -1},
788 {-1, -1, -1, -1, -1, -1, -1, -1}},
789 {{ 7, 7, -1, 2, 2, -1, 6, 6},
790 { 6, -1, -1, 6, -1, -1, 3, -1},
791 { 2, -1, -1, 1, -1, -1, 2, -1},
792 { 5, -1, -1, 3, -1, -1, 2, -1},
793 { 1, -1, -1, 2, -1, -1, 1, -1},
794 { 5, -1, -1, 2, -1, -1, 2, -1},
795 { 6, -1, -1, 1, -1, -1, 7, -1},
796 { 5, -1, -1, 5, -1, -1, 4, -1},
797 {-1, -1, -1, -1, -1, -1, -1, -1},
798 {-1, -1, -1, -1, -1, -1, -1, -1}},
799 {{-1, -1, -1, 6, 6, -1, -1, -1},
800 {-1, 0, 4, 4, 4, 0, -1, -1},
801 {-1, -1, -1, 6, 6, -1, -1, -1},
802 {-1, -1, 2, 7, 2, -1, -1, -1},
803 {-1, -1, -1, 6, 6, -1, -1, -1},
804 {-1, 0, 5, 5, 5, 0, -1, -1},
805 {-1, -1, -1, 3, 3, -1, -1, -1},
806 {-1, -1, -1, -1, -1, -1, -1, -1},
807 {-1, -1, -1, -1, -1, -1, -1, -1},
808 {-1, -1, -1, -1, -1, -1, -1, -1}},
809 {{-1, -1, 4, 1, 3, -1, -1, -1},
810 {-1, 1, -1, -1, 1, -1, -1, -1},
811 {-1, -1, 4, 1, 3, 4, 1, -1},
812 {-1, 1, 3, 4, -1, -1, 4, -1},
813 {-1, 3, -1, -1, 3, 4, 1, -1},
814 {-1, 1, 3, 4, 1, 3, -1, -1},
815 {-1, -1, 4, 1, -1, -1, -1, -1},
816 {-1, -1, -1, -1, -1, -1, -1, -1},
817 {-1, -1, -1, -1, -1, -1, -1, -1},
818 {-1, -1, -1, -1, -1, -1, -1, -1}},
819 {{-1, 6, 4, -1, 3, 2, 5, -1},
820 { 0, -1, -1, -1, -1, -1, 1, -1},
821 {-1, 2, 3, 5, -1, 4, 6, -1},
822 { 0, -1, -1, -1, -1, -1, 1, -1},
823 {-1, 4, 6, -1, 2, 5, 3, -1},
824 { 0, -1, -1, -1, -1, -1, 1, -1},
825 {-1, 5, 2, 3, -1, 4, 6, -1},
826 {-1, -1, -1, -1, -1, -1, -1, -1},
827 {-1, -1, -1, -1, -1, -1, -1, -1},
828 {-1, -1, -1, -1, -1, -1, -1, -1}},
829 {{-1, -1, -1, 6, 6, -1, -1, -1},
830 {-1, -1, 7, 6, 4, -1, -1, -1},
831 {-1, 2, 1, 7, 4, 1, 3, -1},
832 { 2, 1, 1, 1, 1, 1, 3, -1},
833 {-1, 2, 2, 2, 3, 3, 3, -1},
834 {-1, -1, -1, 5, -1, -1, -1, -1},
835 {-1, -1, -1, 2, 3, -1, -1, -1},
836 {-1, -1, -1, 5, -1, -1, -1, -1},
837 {-1, -1, 2, 2, 3, 3, -1, -1},
838 {-1, -1, -1, -1, -1, -1, -1, -1}},
839 {{ 4, -1, 5, -1, -1, 3, -1, 6},
840 { 2, -1, 3, -1, 2, -1, 4, -1},
841 { 4, -1, -1, 1, 0, -1, -1, 6},
842 { 6, -1, 2, 3, 5, -1, 4, -1},
843 { 4, -1, -1, 0, 1, -1, -1, 6},
844 { 2, -1, 5, -1, 3, -1, 4, -1},
845 { 4, -1, 3, -1, -1, 2, -1, 6},
846 { 6, -1, -1, -1, -1, -1, 4, -1},
847 {-1, -1, -1, -1, -1, -1, -1, -1},
848 {-1, -1, -1, -1, -1, -1, -1, -1}},
849 {{ 2, 6, 0, 5, 5, 1, 3, 4},
850 { 1, -1, -1, 2, -1, -1, 0, -1},
851 { 4, -1, -1, 3, 6, -1, -1, 2},
852 {-1, -1, -1, 0, -1, -1, -1, -1},
853 {-1, -1, -1, 1, 4, -1, -1, -1},
854 {-1, -1, -1, 2, -1, -1, -1, -1},
855 {-1, -1, -1, 6, 3, -1, -1, -1},
856 {-1, -1, -1, 5, -1, -1, -1, -1},
857 {-1, -1, -1, 4, 1, -1, -1, -1},
858 {-1, -1, -1, -1, -1, -1, -1, -1}},
859 {{-1, -1, -1, -1, 5, 1, 1, 3},
860 { 0, 5, 1, 0, 5, 3, 3, -1},
861 { 5, 1, 0, 5, 1, 0, 5, 1},
862 { 0, 5, 1, 0, 5, 1, 6, -1},
863 {-1, -1, -1, -1, 1, 6, 5, 1},
864 {-1, -1, -1, -1, 5, 1, 6, -1},
865 {-1, -1, -1, -1, 1, 0, 5, 1},
866 {-1, -1, -1, -1, 5, 1, 0, -1},
867 {-1, -1, -1, -1, -1, -1, -1, -1},
868 {-1, -1, -1, -1, -1, -1, -1, -1}},
869 {{-1, 0, 7, 3, -1, -1, 2, 2},
870 {-1, 0, 7, 3, -1, -1, 2, -1},
871 {-1, 0, 7, 3, -1, -1, 2, 2},
872 {-1, 0, 7, 3, -1, 3, 1, -1},
873 {-1, 0, 7, 3, -1, 6, 4, 5},
874 {-1, 0, 7, 3, -1, 7, 0, -1},
875 {-1, 0, 7, 3, -1, 2, 3, 4},
876 {-1, 0, 7, 3, -1, 5, 6, -1},
877 {-1, -1, -1, -1, -1, 7, 0, 1},
878 {-1, -1, -1, -1, -1, -1, -1, -1}},
879 {{-1, -1, -1, 7, 7, 7, 7, -1},
880 { 3, 4, 5, -1, -1, -1, 7, -1},
881 { 2, -1, -1, -1, -1, -1, -1, 3},
882 { 7, -1, -1, -1, -1, -1, 4, -1},
883 { 7, -1, -1, -1, 3, 4, 5, 6},
884 { 7, -1, -1, 2, 0, 1, 2, -1},
885 { 6, -1, -1, -1, 3, 4, 5, 6},
886 { 0, 1, -1, -1, -1, -1, -1, -1},
887 { 2, 3, 4, -1, -1, -1, -1, -1},
888 { 5, 6, 0, -1, -1, -1, -1, -1}},
889 {{-1, 7, -1, -1, -1, -1, 2, -1},
890 { 1, 1, -1, -1, -1, 3, 3, -1},
891 {-1, 2, -1, -1, -1, -1, 4, -1},
892 { 3, 3, -1, -1, -1, 5, 5, -1},
893 {-1, 4, -1, -1, -1, -1, 6, -1},
894 { 5, 5, -1, -1, -1, 1, 1, -1},
895 {-1, 6, -1, -1, -1, -1, 7, -1},
896 {-1, -1, -1, -1, -1, -1, -1, -1},
897 {-1, -1, -1, -1, -1, -1, -1, -1},
898 {-1, -1, -1, -1, -1, -1, -1, -1}},
899 {{-1, 4, -1, -1, -1, -1, 4, -1},
900 { 2, -1, -1, 1, -1, -1, 2, -1},
901 { 5, -1, -1, 0, 0, -1, -1, 5},
902 { 5, -1, -1, 1, -1, -1, 6, -1},
903 {-1, 4, 2, 7, 7, 5, 4, -1},
904 {-1, -1, -1, 6, -1, -1, -1, -1},
905 {-1, -1, -1, 3, 3, -1, -1, -1},
906 {-1, -1, -1, 7, -1, -1, -1, -1},
907 {-1, -1, -1, -1, -1, -1, -1, -1},
908 {-1, -1, -1, -1, -1, -1, -1, -1}},
909 {{-1, 1, -1, -1, 2, 3, 4, -1},
910 { 2, -1, -1, 3, 0, 4, -1, -1},
911 { 4, -1, -1, 2, 3, 1, -1, -1},
912 { 3, -1, 4, 3, 0, -1, -1, -1},
913 { 4, -1, -1, 2, 5, 1, -1, -1},
914 { 3, -1, 4, 5, 0, 4, -1, -1},
915 {-1, -1, -1, -1, -1, -1, -1, -1},
916 {-1, -1, -1, -1, -1, -1, -1, -1},
917 {-1, -1, -1, -1, -1, -1, -1, -1},
918 {-1, -1, -1, -1, -1, -1, -1, -1}},
919 {{ 2, -1, -1, 1, 1, -1, -1, 2},
920 { 2, -1, 3, 3, 3, -1, 2, -1},
921 {-1, 2, -1, 4, 4, -1, 2, -1},
922 {-1, 7, 7, 0, 7, 7, -1, -1},
923 {-1, -1, -1, 4, 4, -1, -1, -1},
924 {-1, -1, 5, 7, 5, -1, -1, -1},
925 { 6, 3, 2, 6, 4, 2, 3, 6},
926 { 5, -1, -1, -1, -1, -1, 1, -1},
927 {-1, -1, -1, -1, -1, -1, -1, -1},
928 {-1, -1, -1, -1, -1, -1, -1, -1}},
929 {{ 4, 2, 3, 5, 7, 1, 3, 6},
930 { 1, -1, -1, 1, -1, -1, 1, -1},
931 { 3, 0, 1, 3, 2, 4, 3, 5},
932 { 4, -1, -1, 4, -1, -1, 4, -1},
933 {-1, 5, -1, -1, 5, -1, -1, 5},
934 { 0, 3, 2, 0, 4, 5, 0, -1},
935 {-1, 6, -1, -1, 6, -1, -1, 6},
936 { 7, -1, -1, 7, -1, -1, 7, -1},
937 {-1, -1, -1, -1, -1, -1, -1, -1},
938 {-1, -1, -1, -1, -1, -1, -1, -1}},
939 {{-1, 5, 4, -1, 1, 1, -1, -1},
940 { 5, -1, 4, 1, -1, 1, -1, -1},
941 { 0, -1, -1, -1, -1, -1, 0, -1},
942 { 0, 6, 4, -1, -1, 4, 2, -1},
943 {-1, 4, 3, 5, 2, 6, 3, 6},
944 {-1, 2, 6, -1, -1, 5, 4, -1},
945 {-1, -1, -1, -1, -1, -1, -1, -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, 6, 6, -1, -1, -1},
950 {-1, -1, 5, 5, 4, -1, -1, -1},
951 {-1, -1, 1, 6, 6, 4, -1, -1},
952 {-1, 1, 7, 2, 5, 3, -1, -1},
953 {-1, 2, 7, 2, 1, 5, 3, -1},
954 { 2, 1, 3, 1, 4, 2, 7, -1},
955 {-1, 3, 1, 3, 4, 2, 7, -1},
956 {-1, 3, 5, 5, 6, 6, -1, -1},
957 {-1, -1, -1, -1, -1, -1, -1, -1},
958 {-1, -1, -1, -1, -1, -1, -1, -1}},
959 {{-1, -1, 7, 3, -1, -1, -1, -1},
960 {-1, 1, 7, 6, -1, -1, -1, -1},
961 {-1, 3, 7, 5, 1, 5, -1, -1},
962 { 7, 7, 0, 2, 4, 0, 4, -1},
963 { 7, 1, 4, 6, 5, 6, 5, 7},
964 { 1, 7, 7, 1, 7, 7, 1, -1},
965 {-1, -1, -1, -1, -1, -1, -1, -1},
966 {-1, -1, -1, -1, -1, -1, -1, -1},
967 {-1, -1, -1, -1, -1, -1, -1, -1},
968 {-1, -1, -1, -1, -1, -1, -1, -1}},
969 {{-1, -1, 1, -1, -1, 1, -1, -1},
970 {-1, 5, 6, 1, 5, 6, -1, -1},
971 {-1, 1, 1, 2, 2, 1, 1, -1},
972 { 4, 7, 1, 0, 1, 7, 4, -1},
973 {-1, 3, 7, 5, 7, 5, 3, -1},
974 {-1, 1, 1, 1, 1, 1, -1, -1},
975 {-1, -1, -1, -1, -1, -1, -1, -1},
976 {-1, -1, -1, -1, -1, -1, -1, -1},
977 {-1, -1, -1, -1, -1, -1, -1, -1},
978 {-1, -1, -1, -1, -1, -1, -1, -1}},
979 {{ 4, -1, -1, -1, 5, -1, -1, 4},
980 { 6, 6, 7, 6, -1, 4, 5, -1},
981 { 4, 2, 7, 5, 2, 2, 6, 4},
982 {-1, -1, 4, 1, -1, 5, 2, -1},
983 {-1, 5, 2, 7, 7, -1, 7, 4},
984 { 4, 6, 5, 4, -1, 4, 2, -1},
985 {-1, -1, -1, 4, -1, 4, 1, -1},
986 { 0, 0, 0, 5, -1, -1, -1, -1},
987 {-1, -1, -1, -1, 0, 0, 0, 0},
988 {-1, -1, -1, -1, -1, -1, -1, -1}},
989 {{ 1, -1, -1, -1, 0, 0, -1, -1},
990 { 2, -1, -1, 0, 1, 0, -1, -1},
991 { 3, -1, -1, 0, 2, 2, 0, -1},
992 { 4, -1, 0, 1, 1, 1, 0, -1},
993 { 5, -1, -1, 0, 4, 4, 0, -1},
994 { 6, -1, -1, 4, 4, 4, -1, -1},
995 { 7, -1, -1, -1, 4, 4, -1, -1},
996 {-1, -1, -1, 0, 1, 0, -1, -1},
997 {-1, -1, -1, 0, 1, 1, 0, -1},
998 {-1, -1, -1, -1, -1, -1, -1, -1}},
999 {{-1, -1, 3, -1, -1, 1, 7, -1},
1000 {-1, 7, 4, -1, -1, 4, 3, -1},
1001 { 1, -1, -1, 0, 2, 0, -1, -1},
1002 { 5, 4, -1, 3, -1, -1, -1, -1},
1003 { 4, -1, 3, 6, 1, 1, 6, -1},
1004 {-1, 1, -1, -1, 4, -1, 1, -1},
1005 {-1, 7, 5, -1, -1, -1, 3, -1},
1006 {-1, -1, 3, -1, -1, -1, -1, -1},
1007 {-1, -1, -1, -1, -1, -1, -1, -1},
1008 {-1, -1, -1, -1, -1, -1, -1, -1}},
1009 {{ 1, -1, -1, -1, 1, -1, -1, -1},
1010 { 2, -1, -1, -1, 2, -1, -1, -1},
1011 {-1, 3, -1, -1, 3, 3, -1, -1},
1012 {-1, 4, -1, 4, -1, 4, -1, -1},
1013 {-1, 5, -1, -1, 5, 5, -1, -1},
1014 { 6, -1, -1, 7, 1, 7, -1, -1},
1015 { 7, -1, -1, -1, 6, 6, -1, -1},
1016 {-1, -1, -1, -1, -1, -1, -1, -1},
1017 {-1, -1, -1, -1, -1, -1, -1, -1},
1018 {-1, -1, -1, -1, -1, -1, -1, -1}},
1019 {{ 2, -1, -1, 6, -1, 2, 5, 1},
1020 { 5, -1, 4, -1, 4, -1, 4, -1},
1021 { 6, -1, -1, 3, -1, -1, -1, 3},
1022 { 4, 2, 0, -1, -1, -1, 5, -1},
1023 {-1, -1, -1, 6, -1, 3, 6, -1},
1024 {-1, -1, 5, -1, 5, -1, -1, -1},
1025 {-1, -1, -1, 3, -1, 4, 2, 5},
1026 {-1, -1, -1, -1, -1, -1, -1, -1},
1027 {-1, -1, -1, -1, -1, -1, -1, -1},
1028 {-1, -1, -1, -1, -1, -1, -1, -1}},
1029 {{ 6, -1, -1, -1, 4, -1, -1, 3},
1030 { 0, 3, -1, -1, 6, -1, 0, -1},
1031 {-1, -1, 7, -1, 1, -1, 3, -1},
1032 { 7, -1, 4, 7, -1, 2, -1, -1},
1033 { 5, 2, 3, 2, 1, 6, -1, 3},
1034 {-1, -1, 0, 4, 3, 5, 4, -1},
1035 {-1, 7, 6, -1, -1, 0, -1, -1},
1036 { 4, 3, -1, -1, -1, 4, 2, -1},
1037 { 0, -1, -1, -1, -1, -1, 6, -1},
1038 {-1, -1, -1, -1, -1, -1, -1, -1}},
1039 {{ 6, 1, 2, 5, 1, 6, 3, 0},
1040 {-1, -1, -1, -1, -1, -1, 4, -1},
1041 { 0, 5, 2, 7, 1, 6, 2, -1},
1042 { 3, -1, -1, -1, -1, -1, -1, -1},
1043 { 6, 7, 6, 4, 0, 5, 2, 6},
1044 {-1, -1, -1, -1, -1, -1, 1, -1},
1045 { 6, 1, 4, 0, 6, 2, 3, -1},
1046 { 0, -1, -1, -1, -1, -1, -1, -1},
1047 {-1, 0, 4, 5, 3, 7, 6, 0},
1048 {-1, -1, -1, -1, -1, -1, -1, -1}},
1049 {{-1, -1, -1, 0, 1, -1, -1, -1},
1050 {-1, -1, 0, 7, 0, -1, -1, -1},
1051 {-1, -1, 1, 2, 2, 0, -1, -1},
1052 {-1, 0, 7, 0, 7, 0, -1, -1},
1053 {-1, 6, -1, 7, 7, -1, 6, -1},
1054 { 4, 1, 6, 6, 6, 4, 1, -1},
1055 {-1, 5, -1, 7, 7, -1, 5, -1},
1056 {-1, -1, -1, -1, -1, -1, -1, -1},
1057 {-1, -1, -1, -1, -1, -1, -1, -1},
1058 {-1, -1, -1, -1, -1, -1, -1, -1}},
1059 {{-1, -1, -1, 5, 6, -1, -1, -1},
1060 {-1, -1, 3, 3, 3, -1, -1, -1},
1061 {-1, -1, 7, 5, 3, 7, -1, -1},
1062 {-1, 3, -1, 6, -1, 3, -1, -1},
1063 { 2, -1, -1, 3, 7, -1, -1, 1},
1064 { 2, 2, -1, 3, -1, 1, 1, -1},
1065 {-1, 0, 2, 5, 6, 1, 0, -1},
1066 {-1, -1, -1, 3, -1, -1, -1, -1},
1067 {-1, -1, -1, 3, 7, -1, -1, -1},
1068 {-1, -1, -1, -1, -1, -1, -1, -1}},
1069 {{-1, 6, -1, -1, -1, -1, 2, -1},
1070 {-1, 2, 6, 0, 6, 0, -1, -1},
1071 {-1, 0, -1, -1, -1, -1, -1, -1},
1072 { 6, -1, -1, -1, -1, -1, -1, -1},
1073 {-1, 3, 3, 2, 0, 6, 0, 0},
1074 {-1, 6, -1, -1, -1, -1, 0, -1},
1075 {-1, -1, -1, 6, 0, 2, 6, -1},
1076 {-1, 2, 0, -1, -1, -1, -1, -1},
1077 {-1, -1, -1, -1, -1, -1, -1, -1},
1078 {-1, -1, -1, -1, -1, -1, -1, -1}},
1079 {{ 0, 7, -1, -1, -1, -1, -1, -1},
1080 { 1, 5, -1, -1, -1, -1, -1, -1},
1081 { 7, 2, 5, -1, -1, -1, -1, -1},
1082 { 6, 3, 4, -1, -1, -1, -1, -1},
1083 { 5, 5, 4, 4, -1, -1, -1, -1},
1084 { 3, 3, 5, 3, -1, -1, -1, -1},
1085 { 1, 2, 2, 5, 3, -1, -1, -1},
1086 { 1, 0, 0, 7, 6, -1, -1, -1},
1087 { 3, 3, 5, 5, 7, 6, -1, -1},
1088 {-1, -1, -1, -1, -1, -1, -1, -1}},
1089 {{-1, -1, 2, 6, 6, 2, -1, -1},
1090 {-1, 2, 1, 1, 0, 2, -1, -1},
1091 {-1, 2, 3, 2, 2, 0, 2, -1},
1092 { 2, 3, 2, 5, 2, 7, 2, -1},
1093 { 2, 4, 2, 5, 2, 7, 2, 0},
1094 { 2, 4, 2, 6, 6, 2, 0, -1},
1095 {-1, 2, 5, 2, 2, 2, 7, 2},
1096 {-1, 2, 5, 6, 6, 7, 2, -1},
1097 {-1, -1, 2, 2, 2, 2, 2, -1},
1098 {-1, -1, -1, -1, -1, -1, -1, -1}},
1099 {{-1, -1, 0, -1, -1, 0, -1, -1},
1100 { 1, 0, 0, 1, 0, 0, 1, -1},
1101 { 1, 7, 7, 5, 5, 7, 7, 1},
1102 { 3, 2, -1, 2, -1, 2, 3, -1},
1103 { 3, 7, -1, 6, 6, -1, 7, 3},
1104 { 7, -1, -1, 6, -1, -1, 7, -1},
1105 { 4, 4, 5, -1, -1, 5, 4, 4},
1106 {-1, -1, -1, -1, -1, -1, -1, -1},
1107 {-1, -1, -1, -1, -1, -1, -1, -1},
1108 {-1, -1, -1, -1, -1, -1, -1, -1}},
1109 {{-1, 6, 3, -1, -1, 3, 6, -1},
1110 { 6, -1, 2, -1, 2, -1, 6, -1},
1111 { 2, -1, 0, 1, 1, 0, -1, 2},
1112 { 5, 0, -1, 7, -1, 0, 5, -1},
1113 {-1, 5, -1, 6, 6, -1, 5, -1},
1114 { 7, 1, 4, -1, 4, 1, 7, -1},
1115 { 7, -1, 4, -1, -1, 4, -1, 7},
1116 { 2, 0, -1, -1, -1, 0, 2, -1},
1117 {-1, 2, -1, -1, -1, -1, 2, -1},
1118 {-1, -1, -1, -1, -1, -1, -1, -1}},
1119 {{ 6, 1, -1, -1, -1, -1, 4, 0},
1120 { 2, 7, 5, 5, 5, 7, 3, -1},
1121 { 6, 1, -1, -1, -1, -1, 4, 0},
1122 { 2, 5, 7, 7, 7, 5, 3, -1},
1123 { 6, 1, -1, -1, -1, -1, 4, 0},
1124 { 2, 0, 6, 6, 6, 0, 3, -1},
1125 { 6, 1, -1, -1, -1, -1, 4, 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 {{ 5, -1, -1, 1, 1, -1, -1, 5},
1130 { 5, -1, 4, -1, 4, -1, 5, -1},
1131 {-1, 2, 4, -1, -1, 4, 2, -1},
1132 { 7, 2, -1, -1, -1, 2, 7, -1},
1133 { 0, -1, 0, 4, 4, 0, -1, 0},
1134 { 7, 2, -1, -1, -1, 2, 7, -1},
1135 {-1, 2, 3, -1, -1, 3, 2, -1},
1136 { 5, -1, 3, -1, 3, -1, 5, -1},
1137 { 5, -1, -1, 6, 6, -1, -1, 5},
1138 {-1, -1, -1, -1, -1, -1, -1, -1}},
1139 {{ 2, 2, -1, -1, -1, -1, 5, 5},
1140 { 5, -1, -1, -1, -1, -1, 2, -1},
1141 { 5, -1, -1, -1, -1, -1, -1, 2},
1142 { 1, -1, 1, 5, 1, -1, 3, -1},
1143 { 5, 2, 5, 3, 1, 2, 5, 2},
1144 { 2, 0, 5, -1, 2, 0, 5, -1},
1145 {-1, 3, 7, -1, -1, 3, 7, -1},
1146 {-1, -1, 2, 0, 5, -1, -1, -1},
1147 {-1, -1, -1, -1, -1, -1, -1, -1},
1148 {-1, -1, -1, -1, -1, -1, -1, -1}},
1149 {{ 0, 6, 5, 2, 3, 4, 1, 7},
1150 {-1, -1, -1, -1, 1, -1, -1, -1},
1151 {-1, -1, -1, 1, 1, -1, -1, -1},
1152 {-1, -1, 1, -1, -1, -1, -1, -1},
1153 { 7, 1, 4, 3, 2, 5, 6, 0},
1154 {-1, -1, -1, -1, 1, -1, -1, -1},
1155 {-1, -1, -1, 1, 1, -1, -1, -1},
1156 {-1, -1, 1, -1, -1, -1, -1, -1},
1157 { 0, 6, 5, 2, 3, 4, 1, 7},
1158 {-1, -1, -1, -1, -1, -1, -1, -1}},
1159 {{-1, -1, 1, -1, -1, 1, -1, -1},
1160 {-1, 2, 4, -1, 2, 4, -1, -1},
1161 {-1, 2, 3, 6, 5, 3, 2, -1},
1162 {-1, 6, 5, -1, 6, 5, -1, -1},
1163 {-1, -1, -1, 7, 7, -1, -1, -1},
1164 {-1, -1, -1, 7, -1, -1, -1, -1},
1165 { 1, -1, -1, 7, 7, -1, -1, 3},
1166 { 2, -1, -1, 7, -1, -1, 2, -1},
1167 {-1, 3, 4, 5, 6, 4, 1, -1},
1168 {-1, -1, -1, -1, -1, -1, -1, -1}},
1169 {{ 1, -1, -1, 2, 2, -1, -1, 2},
1170 { 1, 3, 7, 3, 7, 4, 2, -1},
1171 {-1, 1, 6, -1, -1, 6, 2, -1},
1172 { 6, -1, 7, 3, 7, -1, 6, -1},
1173 {-1, 4, 2, -1, -1, 1, 3, -1},
1174 {-1, -1, 2, 6, 1, -1, -1, -1},
1175 {-1, 4, 3, 3, 4, 4, 3, -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, 5, 6, -1, -1, -1},
1180 {-1, -1, -1, 3, -1, -1, -1, -1},
1181 {-1, -1, -1, 1, 2, -1, -1, -1},
1182 {-1, -1, -1, 4, -1, -1, -1, -1},
1183 {-1, -1, -1, 5, 7, -1, -1, -1},
1184 {-1, -1, -1, 2, -1, -1, -1, -1},
1185 { 6, 5, 4, 3, 2, 1, 7, 5},
1186 {-1, -1, -1, -1, -1, -1, -1, -1},
1187 {-1, -1, -1, -1, -1, -1, -1, -1},
1188 {-1, -1, -1, -1, -1, -1, -1, -1}},
1189 {{-1, 0, -1, 1, -1, 2, -1, -1},
1190 {-1, 4, -1, 5, -1, 6, -1, -1},
1191 {-1, 7, -1, 0, -1, 2, -1, -1},
1192 {-1, 6, -1, 3, -1, 6, -1, -1},
1193 {-1, 1, -1, 1, -1, 2, -1, -1},
1194 {-1, 3, -1, 5, -1, 0, -1, -1},
1195 {-1, 2, -1, 4, -1, 6, -1, -1},
1196 {-1, 3, -1, 6, -1, 7, -1, -1},
1197 {-1, -1, -1, -1, -1, -1, -1, -1},
1198 {-1, -1, -1, -1, -1, -1, -1, -1}},
1199 {{ 1, 1, 2, 2, 3, 3, 4, 4},
1200 { 5, 5, 6, 7, 6, 5, 5, -1},
1201 { 6, 4, 3, 3, 2, 2, 1, 6},
1202 { 4, 6, 5, 7, 6, 3, 1, -1},
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, -1, -1, -1, -1, -1, -1, -1},
1207 {-1, -1, -1, -1, -1, -1, -1, -1},
1208 {-1, -1, -1, -1, -1, -1, -1, -1}},
1209 {{ 7, 4, -1, 1, 2, -1, 4, 7},
1210 { 5, 5, -1, 2, -1, 4, 4, -1},
1211 {-1, 5, -1, 7, 7, -1, 4, -1},
1212 { 1, 0, 6, 7, 6, 0, 2, -1},
1213 {-1, 2, -1, 5, 3, -1, 1, -1},
1214 { 1, 1, -1, -1, -1, 2, 2, -1},
1215 { 6, 1, 4, -1, -1, 4, 2, 6},
1216 { 5, 3, -1, -1, -1, 3, 5, -1},
1217 {-1, -1, -1, -1, -1, -1, -1, -1},
1218 {-1, -1, -1, -1, -1, -1, -1, -1}},
1219 {{ 1, 5, 1, 0, 0, 1, 5, 1},
1220 { 1, 2, 5, -1, 5, 2, 1, -1},
1221 { 3, 6, 1, 2, 2, 1, 6, 3},
1222 { 4, 3, 4, -1, 4, 3, 4, -1},
1223 { 3, 4, 6, 5, 5, 6, 4, 3},
1224 { 0, 2, 3, -1, 3, 2, 0, -1},
1225 { 2, 3, 1, 5, 5, 1, 3, 2},
1226 {-1, -1, -1, -1, -1, -1, -1, -1},
1227 {-1, -1, -1, -1, -1, -1, -1, -1},
1228 {-1, -1, -1, -1, -1, -1, -1, -1}},
1229 {{ 3, 0, 2, 7, 5, 7, 6, 5},
1230 { 6, -1, 1, -1, 2, -1, 1, -1},
1231 {-1, 6, 4, 0, 3, 4, 5, -1},
1232 {-1, 5, -1, 1, -1, 4, -1, -1},
1233 {-1, 7, 3, 5, 6, 5, 3, -1},
1234 { 1, -1, 2, -1, 4, -1, 2, -1},
1235 { 6, 4, 4, 6, 6, 5, 5, 1},
1236 {-1, -1, -1, -1, -1, -1, -1, -1},
1237 {-1, -1, -1, -1, -1, -1, -1, -1},
1238 {-1, -1, -1, -1, -1, -1, -1, -1}}
1241 /* the tile struct
1242 * type is the bubble number 0-7
1243 * fallx is the x axis movement for the falling bubble
1244 * fallvel is the initial upward velocity for the falling bubble
1245 * ingroup denotes a bubble that is part of a group to be removed
1246 * anchored denotes a bubble that is anchored to the ceiling
1248 struct tile {
1249 int type;
1250 int fallx;
1251 int fallvel;
1252 bool ingroup;
1253 bool anchored;
1254 bool delete;
1257 /* the game context struct
1258 * score is the current score
1259 * level is the current level
1260 * angle is the current cannon direction
1261 * shots is the number of shots fired since last compression
1262 * compress is the height of the compressor
1263 * onboardcnt is the number of unique bubbles on the playing board
1264 * onboard is the unique bubbles on the playing board
1265 * nextinq is the pointer to the next bubble in the firing queue
1266 * queue is the circular buffer of bubbles to be fired
1267 * elapsedlvl is level elapsed time in 1/100s of seconds
1268 * elapsedshot is the shot elapsed time in 1/100s of seconds
1269 * startedshot is when the current shot began
1270 * playboard is the game playing board
1272 struct game_context {
1273 unsigned int score;
1274 unsigned int level;
1275 int angle;
1276 int shots;
1277 int compress;
1278 int onboardcnt;
1279 int onboard[NUM_BUBBLES];
1280 int nextinq;
1281 int queue[NUM_QUEUE];
1282 long elapsedlvl;
1283 long elapsedshot;
1284 long startedshot;
1285 struct tile playboard[BB_HEIGHT][BB_WIDTH];
1288 static struct highscore highscores[NUM_SCORES];
1290 /* used to denote available resume info */
1291 static bool resume = false;
1292 static bool resume_file = false;
1293 static unsigned int highlevel = 0; /* the highest level beaten */
1294 static unsigned int last_highlevel = 0;
1296 static void bubbles_init(struct game_context* bb);
1297 static bool bubbles_nextlevel(struct game_context* bb);
1298 static void bubbles_getonboard(struct game_context* bb);
1299 static void bubbles_drawboard(struct game_context* bb);
1300 static int bubbles_fire(struct game_context* bb);
1301 static bool bubbles_collision(struct game_context* bb, int y, int x,
1302 int nearrow, int nearcol);
1303 static bool bubbles_ingroup(struct game_context* bb, int row, int col);
1304 static int bubbles_searchgroup(struct game_context* bb, int row, int col);
1305 static int bubbles_remove(struct game_context* bb);
1306 static void bubbles_anchored(struct game_context* bb, int row, int col);
1307 static int bubbles_fall(struct game_context* bb);
1308 static int bubbles_checklevel(struct game_context* bb);
1309 static void bubbles_recordscore(struct game_context* bb);
1310 static bool bubbles_loadgame(struct game_context* bb);
1311 static void bubbles_savegame(struct game_context* bb);
1312 static inline void bubbles_setcolors(void);
1313 static void bubbles_callback(void* param);
1314 static int bubbles_handlebuttons(struct game_context* bb, bool animblock,
1315 int timeout);
1316 static int bubbles(struct game_context* bb);
1318 /*****************************************************************************
1319 * bubbles_init() initializes bubbles data structures.
1320 ******************************************************************************/
1321 static void bubbles_init(struct game_context* bb) {
1322 bubbles_setcolors();
1323 /* seed the rand generator */
1324 rb->srand(*rb->current_tick);
1326 /* check for resumed game */
1327 if (resume)
1329 resume = false;
1330 return;
1333 bb->score = 0;
1334 bubbles_nextlevel(bb);
1337 /*****************************************************************************
1338 * bubbles_nextlevel() sets up the game for the next level, returns false if
1339 * there are no more levels.
1340 ******************************************************************************/
1341 static bool bubbles_nextlevel(struct game_context* bb) {
1342 int i, j, pos;
1344 bb->level++;
1346 /* check if there are no more levels */
1347 if(bb->level > NUM_LEVELS) return false;
1349 /* save highest level */
1350 if (bb->level-1 > highlevel)
1351 highlevel = bb->level-1;
1353 /* set up the play board */
1354 rb->memset(bb->playboard, 0, sizeof(bb->playboard));
1355 for(i=0; i<BB_LEVEL_HEIGHT; i++) {
1356 for(j=0; j<BB_WIDTH; j++) {
1357 pos = (int)level[bb->level-1][i][j];
1358 if(pos >=0 && pos < NUM_BUBBLES) {
1359 bb->playboard[i][j].type = pos;
1360 } else {
1361 bb->playboard[i][j].type = -1;
1365 for(i=BB_LEVEL_HEIGHT; i<BB_HEIGHT; i++) {
1366 for(j=0; j<BB_WIDTH; j++) {
1367 bb->playboard[i][j].type = -1;
1371 /* fill first bubbles in shot queue */
1372 bubbles_getonboard(bb);
1373 for(i=0; i<NUM_QUEUE; i++) {
1374 bb->queue[i] = bb->onboard[rb->rand()%bb->onboardcnt];
1377 bb->angle = 0;
1378 bb->shots = 0;
1379 bb->compress = 0;
1380 bb->nextinq = 0;
1381 bb->elapsedlvl = 0;
1382 bb->elapsedshot = 0;
1384 return true;
1387 /*****************************************************************************
1388 * bubbles_getonboard() determines which bubble types are on the play board.
1389 ******************************************************************************/
1390 static void bubbles_getonboard(struct game_context* bb) {
1391 int i, j, k;
1392 bool found;
1394 bb->onboardcnt = 0;
1395 rb->memset(bb->onboard, -1, sizeof(bb->onboard));
1397 for(i=0; i<BB_HEIGHT; i++) {
1398 for(j=0; j<BB_WIDTH; j++) {
1399 if(bb->playboard[i][j].type >= 0) {
1400 found = false;
1402 for(k=0; k<bb->onboardcnt; k++) {
1403 if(bb->playboard[i][j].type == bb->onboard[k]) {
1404 found = true;
1405 break;
1409 if(!found) {
1410 bb->onboard[bb->onboardcnt] = bb->playboard[i][j].type;
1411 bb->onboardcnt++;
1414 if(bb->onboardcnt == NUM_BUBBLES) return;
1420 /*****************************************************************************
1421 * bubbles_drawboard() draws the game board to the buffer but does not update
1422 * the lcd.
1423 ******************************************************************************/
1424 static void bubbles_drawboard(struct game_context* bb) {
1425 int i, j;
1426 int w1, w2, h;
1427 int colmax, indent;
1428 int tipx, tipy;
1429 bool evenline = false;
1430 char *level = "Level";
1431 char *score = "Score";
1432 char *next = "Next";
1433 char *hurry = "HURRY!";
1434 char str[11];
1436 /* clear screen */
1437 rb->lcd_clear_display();
1438 int font = rb->screens[SCREEN_MAIN]->getfont();
1439 h = rb->font_get(font)->height + 1;
1440 /* draw background */
1441 #ifdef HAVE_LCD_COLOR
1442 rb->lcd_bitmap(bubbles_background, 0, 0, LCD_WIDTH, LCD_HEIGHT);
1443 #endif
1445 /* display play board */
1446 for(i=0; i<BB_HEIGHT; i++) {
1447 colmax = BB_WIDTH;
1448 if(evenline) {
1449 colmax--;
1450 indent = ROW_INDENT;
1451 } else {
1452 indent = 0;
1454 evenline = !evenline;
1456 for(j=0; j<colmax; j++) {
1457 if(bb->playboard[i][j].type >= 0 && !bb->playboard[i][j].delete) {
1458 rb->lcd_bitmap_part(bubbles_emblem,
1459 0, EMBLEM_HEIGHT*bb->playboard[i][j].type,
1460 STRIDE( SCREEN_MAIN,
1461 BMPWIDTH_bubbles_emblem, BMPHEIGHT_bubbles_emblem),
1462 XOFS+indent+BUBBLE_WIDTH*j+(BUBBLE_WIDTH-EMBLEM_WIDTH)/2,
1463 YOFS+ROW_HEIGHT*i+(BUBBLE_HEIGHT-EMBLEM_HEIGHT)/2+bb->compress*ROW_HEIGHT,
1464 EMBLEM_WIDTH, EMBLEM_HEIGHT);
1465 rb->lcd_set_drawmode(DRMODE_FG);
1466 rb->lcd_mono_bitmap((const unsigned char *)bubbles_bubble,
1467 XOFS+indent+BUBBLE_WIDTH*j,
1468 YOFS+ROW_HEIGHT*i+bb->compress*ROW_HEIGHT,
1469 BUBBLE_WIDTH, BUBBLE_HEIGHT);
1470 rb->lcd_set_drawmode(DRMODE_SOLID);
1475 /* display bubble to be shot */
1476 rb->lcd_bitmap_part(bubbles_emblem,
1477 0, EMBLEM_HEIGHT*bb->queue[bb->nextinq],
1478 STRIDE( SCREEN_MAIN,
1479 BMPWIDTH_bubbles_emblem, BMPHEIGHT_bubbles_emblem),
1480 SHOTX+(BUBBLE_WIDTH-EMBLEM_WIDTH)/2,
1481 SHOTY+(BUBBLE_HEIGHT-EMBLEM_HEIGHT)/2,
1482 EMBLEM_WIDTH, EMBLEM_HEIGHT);
1483 rb->lcd_set_drawmode(DRMODE_FG);
1484 rb->lcd_mono_bitmap((const unsigned char *)bubbles_bubble,
1485 SHOTX, SHOTY,
1486 BUBBLE_WIDTH, BUBBLE_HEIGHT);
1487 rb->lcd_set_drawmode(DRMODE_SOLID);
1489 /* display next bubble to be shot */
1490 #ifndef NEXT_BB_X
1491 rb->lcd_bitmap_part(bubbles_emblem,
1492 0, EMBLEM_HEIGHT*bb->queue[(bb->nextinq+1)%NUM_QUEUE],
1493 STRIDE( SCREEN_MAIN,
1494 BMPWIDTH_bubbles_emblem, BMPHEIGHT_bubbles_emblem),
1495 XOFS/2-BUBBLE_WIDTH/2+(BUBBLE_WIDTH-EMBLEM_WIDTH)/2,
1496 SHOTY+(BUBBLE_HEIGHT-EMBLEM_HEIGHT)/2,
1497 EMBLEM_WIDTH, EMBLEM_HEIGHT);
1498 rb->lcd_set_drawmode(DRMODE_FG);
1499 rb->lcd_mono_bitmap((const unsigned char *)bubbles_bubble,
1500 XOFS/2-BUBBLE_WIDTH/2, SHOTY,
1501 BUBBLE_WIDTH, BUBBLE_HEIGHT);
1502 rb->lcd_set_drawmode(DRMODE_SOLID);
1503 #else
1504 rb->lcd_bitmap_part(bubbles_emblem,
1505 0, EMBLEM_HEIGHT*bb->queue[(bb->nextinq+1)%NUM_QUEUE],
1506 STRIDE( SCREEN_MAIN,
1507 BMPWIDTH_bubbles_emblem, BMPHEIGHT_bubbles_emblem),
1508 NEXT_BB_X + NEXT_BB_WIDTH/2-BUBBLE_WIDTH/2+(BUBBLE_WIDTH-EMBLEM_WIDTH)/2,
1509 NEXT_BB_Y + (BUBBLE_HEIGHT-EMBLEM_HEIGHT)/2 + h,
1510 EMBLEM_WIDTH, EMBLEM_HEIGHT);
1511 rb->lcd_set_drawmode(DRMODE_FG);
1512 rb->lcd_mono_bitmap((const unsigned char *)bubbles_bubble,
1513 NEXT_BB_X + NEXT_BB_WIDTH/2-BUBBLE_WIDTH/2, NEXT_BB_Y + h,
1514 BUBBLE_WIDTH, BUBBLE_HEIGHT);
1515 rb->lcd_set_drawmode(DRMODE_SOLID);
1516 #endif
1518 /* draw bounding lines */
1519 #ifndef HAVE_LCD_COLOR
1520 rb->lcd_vline(XOFS-1, 0, LCD_HEIGHT);
1521 rb->lcd_vline(XOFS+BUBBLE_WIDTH*BB_WIDTH, 0, LCD_HEIGHT);
1522 #endif
1523 rb->lcd_hline(XOFS, XOFS+BUBBLE_WIDTH*BB_WIDTH-1, YOFS+bb->compress*ROW_HEIGHT-1);
1524 rb->lcd_hline(XOFS, XOFS+BUBBLE_WIDTH*BB_WIDTH-1,
1525 YOFS+ROW_HEIGHT*(BB_HEIGHT-2)+BUBBLE_HEIGHT);
1527 /* draw arrow */
1528 tipx = SHOTX+BUBBLE_WIDTH/2+(((fp14_sin(bb->angle)>>4)*BUBBLE_WIDTH*3/2)>>10);
1529 tipy = SHOTY+BUBBLE_HEIGHT/2-(((fp14_cos(bb->angle)>>4)*BUBBLE_HEIGHT*3/2)>>10);
1531 rb->lcd_drawline(SHOTX+BUBBLE_WIDTH/2+(((fp14_sin(bb->angle)>>4)*BUBBLE_WIDTH/2)>>10),
1532 SHOTY+BUBBLE_HEIGHT/2-(((fp14_cos(bb->angle)>>4)*BUBBLE_HEIGHT/2)>>10),
1533 tipx, tipy);
1534 xlcd_filltriangle(tipx, tipy,
1535 tipx+(((fp14_sin(bb->angle-135)>>4)*BUBBLE_WIDTH/3)>>10),
1536 tipy-(((fp14_cos(bb->angle-135)>>4)*BUBBLE_HEIGHT/3)>>10),
1537 tipx+(((fp14_sin(bb->angle+135)>>4)*BUBBLE_WIDTH/3)>>10),
1538 tipy-(((fp14_cos(bb->angle+135)>>4)*BUBBLE_HEIGHT/3)>>10));
1540 /* draw text */
1541 rb->snprintf(str, 4, "%d", bb->level);
1542 rb->lcd_getstringsize(level, &w1, NULL);
1543 rb->lcd_getstringsize(str, &w2, NULL);
1544 #ifndef LEVEL_TXT_X
1545 rb->lcd_putsxy(XOFS/2-w1/2, 2, level);
1546 rb->lcd_putsxy(XOFS/2-w2/2, 2+h, str);
1547 #else
1548 rb->lcd_putsxy(LEVEL_TXT_X+(LEVEL_TXT_WIDTH/2-w1/2), LEVEL_TXT_Y, level);
1549 rb->lcd_putsxy(LEVEL_TXT_X+(LEVEL_TXT_WIDTH/2-w2/2), LEVEL_TXT_Y+h, str);
1550 #endif
1552 rb->snprintf(str, 10, "%d", bb->score);
1553 rb->lcd_getstringsize(score, &w1,NULL);
1554 rb->lcd_getstringsize(str, &w2, NULL);
1555 #ifndef SCORE_TXT_X
1556 rb->lcd_putsxy(XOFS/2-w1/2, 29, score);
1557 rb->lcd_putsxy(XOFS/2-w2/2, 29+h, str);
1558 #else
1559 rb->lcd_putsxy(SCORE_TXT_X+(SCORE_TXT_WIDTH/2-w1/2), SCORE_TXT_Y, score);
1560 rb->lcd_putsxy(SCORE_TXT_X+(SCORE_TXT_WIDTH/2-w2/2), SCORE_TXT_Y+h, str);
1561 #endif
1563 rb->lcd_getstringsize(next, &w1, NULL);
1564 #ifndef NEXT_BB_X
1565 rb->lcd_putsxy(XOFS/2-w1/2, SHOTY-h, next);
1566 #else
1567 rb->lcd_putsxy(NEXT_BB_X+(NEXT_BB_WIDTH/2-w1/2), NEXT_BB_Y, next);
1568 #endif
1571 if(bb->elapsedshot >= (MAX_SHOTTIME*7)/10) {
1572 rb->lcd_getstringsize(hurry, &w1, &h);
1573 rb->lcd_putsxy(LCD_WIDTH/2-w1/2, LCD_HEIGHT/2-h/2, hurry);
1577 /*****************************************************************************
1578 * bubbles_fire() fires the current bubble, reloads the cannon, attaches
1579 * bubble to playboard, removes appropriate bubbles, and advances the
1580 * the compressor.
1581 ******************************************************************************/
1582 static int bubbles_fire(struct game_context* bb) {
1583 int bubblecur;
1584 long shotxinc, shotyinc;
1585 long shotxofs, shotyofs;
1586 int shotxdirec = 1;
1587 long tempxofs, tempyofs;
1588 int nearrow, nearcol;
1589 int lastrow = BB_HEIGHT-1;
1590 int lastcol = (BB_WIDTH-1)/2;
1591 int buttonres;
1592 long lasttick, currenttick;
1594 /* get current bubble */
1595 bubblecur = bb->queue[bb->nextinq];
1596 shotxinc = ((fp14_sin(bb->angle)>>4)*BUBBLE_WIDTH)/3;
1597 shotyinc = ((-1*(fp14_cos(bb->angle)>>4))*BUBBLE_HEIGHT)/3;
1598 shotxofs = shotyofs = 0;
1600 /* advance the queue */
1601 bb->queue[bb->nextinq] = bb->onboard[rb->rand()%bb->onboardcnt];
1602 bb->nextinq = (bb->nextinq+1)%NUM_QUEUE;
1603 bubbles_drawboard(bb);
1604 rb->lcd_update_rect(0, 0, XOFS, LCD_HEIGHT);
1606 /* move the bubble across the play board */
1607 lasttick = *rb->current_tick;
1609 while(true) {
1610 /* move the bubble one step */
1611 shotyofs += shotyinc;
1612 shotxofs += shotxinc*shotxdirec;
1614 /* check for bounce off sides */
1615 if(SHOTX+(shotxofs>>10) < XOFS) {
1616 shotxofs += 2*((XOFS<<10)-(((SHOTX)<<10)+shotxofs));
1617 shotxdirec *= -1;
1618 } else if(SHOTX+(shotxofs>>10) > XOFS+(BB_WIDTH-1)*BUBBLE_WIDTH) {
1619 shotxofs -= 2*((((SHOTX)<<10)+shotxofs)-
1620 ((XOFS<<10)+(((BB_WIDTH-1)*BUBBLE_WIDTH)<<10)));
1621 shotxdirec *= -1;
1624 tempxofs = shotxofs>>10;
1625 tempyofs = shotyofs>>10;
1627 /* display shot */
1628 bubbles_drawboard(bb);
1629 rb->lcd_bitmap_part(bubbles_emblem, 0, EMBLEM_HEIGHT*bubblecur,
1630 STRIDE( SCREEN_MAIN,
1631 BMPWIDTH_bubbles_emblem,
1632 BMPHEIGHT_bubbles_emblem),
1633 SHOTX+tempxofs+(BUBBLE_WIDTH-EMBLEM_WIDTH)/2,
1634 SHOTY+tempyofs+(BUBBLE_HEIGHT-EMBLEM_HEIGHT)/2,
1635 EMBLEM_WIDTH, EMBLEM_HEIGHT);
1636 rb->lcd_set_drawmode(DRMODE_FG);
1637 rb->lcd_mono_bitmap((const unsigned char *)bubbles_bubble,
1638 SHOTX+tempxofs, SHOTY+tempyofs,
1639 BUBBLE_WIDTH, BUBBLE_HEIGHT);
1640 rb->lcd_set_drawmode(DRMODE_SOLID);
1641 rb->lcd_update_rect(XOFS, 0, BB_WIDTH*BUBBLE_WIDTH, LCD_HEIGHT);
1643 /* find nearest position */
1644 nearrow = ((SHOTY+tempyofs)-
1645 (YOFS+bb->compress*ROW_HEIGHT)+
1646 (ROW_HEIGHT/2))/ROW_HEIGHT;
1647 if(nearrow >= BB_HEIGHT) nearrow = BB_HEIGHT-1;
1649 if(nearrow%2) { /* odd row */
1650 nearcol = ((SHOTX+tempxofs)-
1651 (XOFS+ROW_INDENT)+
1652 (BUBBLE_WIDTH/2))/BUBBLE_WIDTH;
1653 if(nearcol >= BB_WIDTH-1) nearcol = BB_WIDTH-2;
1654 } else { /* even row */
1655 nearcol = ((SHOTX+tempxofs)-XOFS+(BUBBLE_WIDTH/2))/BUBBLE_WIDTH;
1656 if(nearcol >= BB_WIDTH) nearcol = BB_WIDTH-1;
1658 if(nearcol < 0) nearcol = 0;
1660 /* if nearest position is occupied attach to last position */
1661 if(bb->playboard[nearrow][nearcol].type >= 0) {
1662 bb->playboard[lastrow][lastcol].type = bubblecur;
1663 break;
1666 /* save last position */
1667 lastrow = nearrow;
1668 lastcol = nearcol;
1670 /* if collision with neighbor then attach shot */
1671 if(bubbles_collision(bb, YOFS+SHOTY+tempyofs, SHOTX+tempxofs,
1672 nearrow, nearcol)) {
1673 bb->playboard[nearrow][nearcol].type = bubblecur;
1674 break;
1677 /* if at top then attach shot to the ceiling */
1678 if(nearrow == 0 && SHOTY+tempyofs <= YOFS+bb->compress*ROW_HEIGHT) {
1679 bb->playboard[nearrow][nearcol].type = bubblecur;
1680 break;
1683 /* handle button events */
1684 buttonres = bubbles_handlebuttons(bb, true, 0);
1685 if(buttonres != BB_NONE) return buttonres;
1687 /* framerate limiting */
1688 currenttick = *rb->current_tick;
1689 if(currenttick-lasttick < HZ/MAX_FPS) {
1690 rb->sleep((HZ/MAX_FPS)-(currenttick-lasttick));
1691 } else {
1692 rb->yield();
1694 lasttick = currenttick;
1697 bubbles_drawboard(bb);
1698 rb->lcd_update();
1700 /* clear appropriate bubbles from playing board */
1701 if(bubbles_ingroup(bb, lastrow, lastcol)) {
1702 buttonres = bubbles_remove(bb);
1703 if(buttonres != BB_NONE) return buttonres;
1706 /* update shots and compress amount */
1707 bb->shots++;
1708 if(bb->shots >= NUM_COMPRESS) {
1709 bb->shots = 0;
1710 bb->compress++;
1713 return BB_NONE;
1716 /*****************************************************************************
1717 * bubbles_collision() determines if a fired bubble has collided with another
1718 * bubble.
1719 ******************************************************************************/
1720 static bool bubbles_collision(struct game_context* bb, int y, int x,
1721 int nearrow, int nearcol) {
1722 int nx, ny;
1723 int adj = nearrow%2;
1725 /* check neighbors */
1726 if(nearcol-1 >= 0) {
1727 if(bb->playboard[nearrow][nearcol-1].type >= 0) {
1728 nx = XOFS+(nearrow%2 ? ROW_INDENT : 0)+BUBBLE_WIDTH*(nearcol-1);
1729 ny = YOFS+ROW_HEIGHT*nearrow+bb->compress*ROW_HEIGHT;
1730 if((x-nx)*(x-nx)+(y-ny)*(y-ny) < MIN_DISTANCE) return true;
1734 if(nearcol-1+adj >= 0) {
1735 if(nearrow-1 >= 0) {
1736 if(bb->playboard[nearrow-1][nearcol-1+adj].type >= 0) {
1737 nx = XOFS+((nearrow-1)%2 ? ROW_INDENT : 0)+
1738 BUBBLE_WIDTH*(nearcol-1+adj);
1739 ny = YOFS+ROW_HEIGHT*(nearrow-1)+bb->compress*ROW_HEIGHT;
1740 if((x-nx)*(x-nx)+(y-ny)*(y-ny) < MIN_DISTANCE) return true;
1744 if(nearrow+1 < BB_HEIGHT) {
1745 if(bb->playboard[nearrow+1][nearcol-1+adj].type >= 0) {
1746 nx = XOFS+((nearrow+1)%2 ? ROW_INDENT : 0)+
1747 BUBBLE_WIDTH*(nearcol-1+adj);
1748 ny = YOFS+ROW_HEIGHT*(nearrow+1)+bb->compress*ROW_HEIGHT;
1749 if((x-nx)*(x-nx)+(y-ny)*(y-ny) < MIN_DISTANCE) return true;
1754 if(nearcol+adj >= 0) {
1755 if(nearrow-1 >= 0) {
1756 if(bb->playboard[nearrow-1][nearcol+adj].type >= 0) {
1757 nx = XOFS+((nearrow-1)%2 ? ROW_INDENT : 0)+
1758 BUBBLE_WIDTH*(nearcol+adj);
1759 ny = YOFS+ROW_HEIGHT*(nearrow-1)+bb->compress*ROW_HEIGHT;
1760 if((x-nx)*(x-nx)+(y-ny)*(y-ny) < MIN_DISTANCE) return true;
1764 if(nearrow+1 < BB_HEIGHT) {
1765 if(bb->playboard[nearrow+1][nearcol+adj].type >= 0) {
1766 nx = XOFS+((nearrow+1)%2 ? ROW_INDENT : 0)+
1767 BUBBLE_WIDTH*(nearcol+adj);
1768 ny = YOFS+ROW_HEIGHT*(nearrow+1)+bb->compress*ROW_HEIGHT;
1769 if((x-nx)*(x-nx)+(y-ny)*(y-ny) < MIN_DISTANCE) return true;
1774 if(nearcol+1 < BB_WIDTH-adj) {
1775 if(bb->playboard[nearrow][nearcol+1].type >= 0) {
1776 nx = XOFS+(nearrow%2 ? ROW_INDENT : 0)+BUBBLE_WIDTH*(nearcol+1);
1777 ny = YOFS+ROW_HEIGHT*nearrow+bb->compress*ROW_HEIGHT;
1778 if((x-nx)*(x-nx)+(y-ny)*(y-ny) < MIN_DISTANCE) return true;
1782 return false;
1785 /*****************************************************************************
1786 * bubbles_ingroup() marks all bubbles that form the current group.
1787 ******************************************************************************/
1788 static bool bubbles_ingroup(struct game_context* bb, int row, int col) {
1789 int i, j;
1790 int count;
1792 count = bubbles_searchgroup(bb, row, col);
1794 /* unmark group if too small */
1795 if(count < 3) {
1796 for(i=0; i<BB_HEIGHT; i++) {
1797 for(j=0; j<BB_WIDTH; j++) {
1798 bb->playboard[i][j].ingroup = false;
1802 return false;
1805 return true;
1808 /*****************************************************************************
1809 * bubbles_searchgroup() return the size of the group of bubbles of the same
1810 * type that the current bubble belongs to.
1811 ******************************************************************************/
1812 static int bubbles_searchgroup(struct game_context* bb, int row, int col) {
1813 int i, adj;
1814 int myrow, mycol, mytype;
1815 int count = 0;
1817 struct coord {
1818 int row;
1819 int col;
1820 } search[(2*BB_WIDTH-1)*(BB_HEIGHT/2)];
1822 /* search initial bubble */
1823 bb->playboard[row][col].ingroup = true;
1824 search[count].row = row;
1825 search[count].col = col;
1826 count++;
1828 /* breadth-first search neighbors */
1829 for(i=0; i<count; i++) {
1830 myrow = search[i].row;
1831 mycol = search[i].col;
1832 mytype = bb->playboard[myrow][mycol].type;
1833 adj = myrow%2;
1835 if(mycol-1 >= 0) {
1836 if(bb->playboard[myrow][mycol-1].type == mytype &&
1837 !bb->playboard[myrow][mycol-1].ingroup) {
1838 bb->playboard[myrow][mycol-1].ingroup = true;
1839 search[count].row = myrow;
1840 search[count].col = mycol-1;
1841 count++;
1845 if(mycol-1+adj >= 0) {
1846 if(myrow-1 >= 0) {
1847 if(bb->playboard[myrow-1][mycol-1+adj].type == mytype &&
1848 !bb->playboard[myrow-1][mycol-1+adj].ingroup) {
1849 bb->playboard[myrow-1][mycol-1+adj].ingroup = true;
1850 search[count].row = myrow-1;
1851 search[count].col = mycol-1+adj;
1852 count++;
1856 if(myrow+1 < BB_HEIGHT) {
1857 if(bb->playboard[myrow+1][mycol-1+adj].type == mytype &&
1858 !bb->playboard[myrow+1][mycol-1+adj].ingroup) {
1859 bb->playboard[myrow+1][mycol-1+adj].ingroup = true;
1860 search[count].row = myrow+1;
1861 search[count].col = mycol-1+adj;
1862 count++;
1867 if(mycol+adj >= 0) {
1868 if(myrow-1 >= 0) {
1869 if(bb->playboard[myrow-1][mycol+adj].type == mytype &&
1870 !bb->playboard[myrow-1][mycol+adj].ingroup) {
1871 bb->playboard[myrow-1][mycol+adj].ingroup = true;
1872 search[count].row = myrow-1;
1873 search[count].col = mycol+adj;
1874 count++;
1878 if(myrow+1 < BB_HEIGHT) {
1879 if(bb->playboard[myrow+1][mycol+adj].type == mytype &&
1880 !bb->playboard[myrow+1][mycol+adj].ingroup) {
1881 bb->playboard[myrow+1][mycol+adj].ingroup = true;
1882 search[count].row = myrow+1;
1883 search[count].col = mycol+adj;
1884 count++;
1889 if(mycol+1 < BB_WIDTH-adj) {
1890 if(bb->playboard[myrow][mycol+1].type == mytype &&
1891 !bb->playboard[myrow][mycol+1].ingroup) {
1892 bb->playboard[myrow][mycol+1].ingroup = true;
1893 search[count].row = myrow;
1894 search[count].col = mycol+1;
1895 count++;
1900 return count;
1903 /*****************************************************************************
1904 * bubbles_remove() removes all bubbles in the current group and all
1905 * unanchored bubbles from the play board.
1906 ******************************************************************************/
1907 static int bubbles_remove(struct game_context* bb) {
1908 int i, j;
1909 int buttonres;
1911 /* determine all anchored bubbles */
1912 for(j=0; j<BB_WIDTH; j++) {
1913 if(bb->playboard[0][j].type >= 0 && !bb->playboard[0][j].ingroup) {
1914 bubbles_anchored(bb, 0, j);
1918 /* mark bubbles to be deleted */
1919 for(i=0; i<BB_HEIGHT; i++) {
1920 for(j=0; j<BB_WIDTH; j++) {
1921 if(bb->playboard[i][j].type >= 0 &&
1922 (!bb->playboard[i][j].anchored || bb->playboard[i][j].ingroup)) {
1923 bb->playboard[i][j].delete = true;
1928 /* animate falling bubbles */
1929 buttonres = bubbles_fall(bb);
1930 if(buttonres != BB_NONE) return buttonres;
1932 /* remove bubbles */
1933 for(i=0; i<BB_HEIGHT; i++) {
1934 for(j=0; j<BB_WIDTH; j++) {
1935 if(bb->playboard[i][j].delete) {
1936 bb->playboard[i][j].ingroup = false;
1937 bb->playboard[i][j].type = -1;
1938 bb->playboard[i][j].delete = false;
1939 } else {
1940 bb->playboard[i][j].anchored = false;
1945 bubbles_getonboard(bb);
1947 return BB_NONE;
1950 /*****************************************************************************
1951 * bubbles_anchored() marks all bubbles that are anchored in some way to the
1952 * current bubble.
1953 ******************************************************************************/
1954 static void bubbles_anchored(struct game_context* bb, int row, int col) {
1955 int i, adj;
1956 int myrow, mycol;
1957 int count = 0;
1959 struct coord {
1960 int row;
1961 int col;
1962 } search[(2*BB_WIDTH-1)*(BB_HEIGHT/2)];
1964 /* search initial bubble */
1965 bb->playboard[row][col].anchored = true;
1966 search[count].row = row;
1967 search[count].col = col;
1968 count++;
1970 /* breadth-first search neighbors */
1971 for(i=0; i<count; i++) {
1972 myrow = search[i].row;
1973 mycol = search[i].col;
1974 adj = myrow%2;
1976 if(mycol-1 >= 0) {
1977 if(bb->playboard[myrow][mycol-1].type >= 0 &&
1978 !bb->playboard[myrow][mycol-1].ingroup &&
1979 !bb->playboard[myrow][mycol-1].anchored) {
1980 bb->playboard[myrow][mycol-1].anchored = true;
1981 search[count].row = myrow;
1982 search[count].col = mycol-1;
1983 count++;
1987 if(mycol-1+adj >= 0) {
1988 if(myrow-1 >= 0) {
1989 if(bb->playboard[myrow-1][mycol-1+adj].type >= 0 &&
1990 !bb->playboard[myrow-1][mycol-1+adj].ingroup &&
1991 !bb->playboard[myrow-1][mycol-1+adj].anchored) {
1992 bb->playboard[myrow-1][mycol-1+adj].anchored = true;
1993 search[count].row = myrow-1;
1994 search[count].col = mycol-1+adj;
1995 count++;
1999 if(myrow+1 < BB_HEIGHT) {
2000 if(bb->playboard[myrow+1][mycol-1+adj].type >= 0 &&
2001 !bb->playboard[myrow+1][mycol-1+adj].ingroup &&
2002 !bb->playboard[myrow+1][mycol-1+adj].anchored) {
2003 bb->playboard[myrow+1][mycol-1+adj].anchored = true;
2004 search[count].row = myrow+1;
2005 search[count].col = mycol-1+adj;
2006 count++;
2011 if(mycol+adj >= 0) {
2012 if(myrow-1 >= 0) {
2013 if(bb->playboard[myrow-1][mycol+adj].type >= 0 &&
2014 !bb->playboard[myrow-1][mycol+adj].ingroup &&
2015 !bb->playboard[myrow-1][mycol+adj].anchored) {
2016 bb->playboard[myrow-1][mycol+adj].anchored = true;
2017 search[count].row = myrow-1;
2018 search[count].col = mycol+adj;
2019 count++;
2023 if(myrow+1 < BB_HEIGHT) {
2024 if(bb->playboard[myrow+1][mycol+adj].type >= 0 &&
2025 !bb->playboard[myrow+1][mycol+adj].ingroup &&
2026 !bb->playboard[myrow+1][mycol+adj].anchored) {
2027 bb->playboard[myrow+1][mycol+adj].anchored = true;
2028 search[count].row = myrow+1;
2029 search[count].col = mycol+adj;
2030 count++;
2035 if(mycol+1 < BB_WIDTH-adj) {
2036 if(bb->playboard[myrow][mycol+1].type >= 0 &&
2037 !bb->playboard[myrow][mycol+1].ingroup &&
2038 !bb->playboard[myrow][mycol+1].anchored) {
2039 bb->playboard[myrow][mycol+1].anchored = true;
2040 search[count].row = myrow;
2041 search[count].col = mycol+1;
2042 count++;
2048 /*****************************************************************************
2049 * bubbles_fall() makes removed bubbles fall from the screen.
2050 ******************************************************************************/
2051 static int bubbles_fall(struct game_context* bb) {
2052 int i, j;
2053 int count;
2054 int indent;
2055 int xofs, yofs;
2056 int buttonres;
2057 bool onscreen;
2058 long lasttick, currenttick;
2060 /* give all falling bubbles an x axis movement */
2061 for(i=0; i<BB_HEIGHT; i++) {
2062 for(j=0; j<BB_WIDTH; j++) {
2063 if(bb->playboard[i][j].delete) {
2064 bb->playboard[i][j].fallx = rb->rand()%25 - 12;
2065 bb->playboard[i][j].fallvel = rb->rand()%5 + 6;
2070 /* draw bubbles falling off the screen
2071 * follows y=x^2-8x scaled to bubble size
2073 lasttick = *rb->current_tick;
2075 for(count=1; ;count++) {
2076 onscreen = false;
2077 bubbles_drawboard(bb);
2079 for(i=0; i<BB_HEIGHT; i++) {
2080 for(j=0; j<BB_WIDTH; j++) {
2081 if(bb->playboard[i][j].delete) {
2082 indent = (i%2 ? ROW_INDENT : 0);
2083 xofs = ((bb->playboard[i][j].fallx*count)*BUBBLE_WIDTH)/48;
2084 yofs = ((count*count - bb->playboard[i][j].fallvel*count)*
2085 BUBBLE_HEIGHT)/20;
2087 /* draw bubble if it is still on the screen */
2088 if(YOFS+ROW_HEIGHT*i+bb->compress*ROW_HEIGHT+yofs
2089 <= LCD_HEIGHT) {
2090 onscreen = true;
2092 rb->lcd_bitmap_part(bubbles_emblem, 0,
2093 EMBLEM_HEIGHT*bb->playboard[i][j].type,
2094 STRIDE( SCREEN_MAIN,
2095 BMPWIDTH_bubbles_emblem,
2096 BMPHEIGHT_bubbles_emblem),
2097 XOFS+indent+BUBBLE_WIDTH*j+
2098 (BUBBLE_WIDTH-EMBLEM_WIDTH)/2+xofs,
2099 YOFS+ROW_HEIGHT*i+(BUBBLE_HEIGHT-EMBLEM_HEIGHT)/2+
2100 bb->compress*ROW_HEIGHT+yofs,
2101 EMBLEM_WIDTH, EMBLEM_HEIGHT);
2102 rb->lcd_set_drawmode(DRMODE_FG);
2103 rb->lcd_mono_bitmap(
2104 (const unsigned char *)bubbles_bubble,
2105 XOFS+indent+BUBBLE_WIDTH*j+xofs,
2106 YOFS+ROW_HEIGHT*i+bb->compress*ROW_HEIGHT+yofs,
2107 BUBBLE_WIDTH, BUBBLE_HEIGHT);
2108 rb->lcd_set_drawmode(DRMODE_SOLID);
2114 rb->lcd_update();
2116 /* break out if all bubbles are off the screen */
2117 if(!onscreen) break;
2119 /* handle button events */
2120 buttonres = bubbles_handlebuttons(bb, true, 0);
2121 if(buttonres != BB_NONE) return buttonres;
2123 /* framerate limiting */
2124 currenttick = *rb->current_tick;
2125 if(currenttick-lasttick < HZ/MAX_FPS) {
2126 rb->sleep((HZ/MAX_FPS)-(currenttick-lasttick));
2127 } else {
2128 rb->yield();
2130 lasttick = currenttick;
2133 return BB_NONE;
2136 /*****************************************************************************
2137 * bubbles_checklevel() checks the state of the playboard for a win or loss.
2138 ******************************************************************************/
2139 static int bubbles_checklevel(struct game_context* bb) {
2140 int i, j;
2141 int points;
2142 char str[13];
2144 bubbles_drawboard(bb);
2145 rb->lcd_update();
2147 /* check for bubbles below cut off point */
2148 for(i=0; i<=bb->compress; i++) {
2149 for(j=0; j<BB_WIDTH; j++) {
2150 if(bb->playboard[BB_HEIGHT-1-i][j].type >= 0) return BB_LOSE;
2154 /* check for bubbles above cut off point */
2155 for(i=0; i<BB_HEIGHT-1-bb->compress; i++) {
2156 for(j=0; j<BB_WIDTH; j++) {
2157 if(bb->playboard[i][j].type >= 0) return BB_NONE;
2161 /* level complete, record score */
2162 points = 100 - bb->elapsedlvl/100;
2163 if(points > 0) {
2164 bb->score += points;
2165 } else {
2166 points = 0;
2169 rb->snprintf(str, 12, "%d points", points);
2170 rb->splash(HZ, str);
2172 /* advance to the next level */
2173 if(!bubbles_nextlevel(bb)) {
2174 return BB_WIN;
2177 bubbles_drawboard(bb);
2178 rb->lcd_update();
2179 rb->snprintf(str, 12, "Level %d", bb->level);
2180 rb->splash(HZ, str);
2181 bubbles_drawboard(bb);
2182 rb->lcd_update();
2184 return BB_NONE;
2187 /*****************************************************************************
2188 * bubbles_recordscore() inserts a high score into the high scores list and
2189 * returns the high score position.
2190 ******************************************************************************/
2191 static void bubbles_recordscore(struct game_context* bb) {
2193 int position;
2195 position = highscore_update(bb->score, bb->level-1, "",
2196 highscores, NUM_SCORES);
2197 if (position != -1)
2199 if (position == 0)
2200 rb->splash(HZ*2, "New High Score");
2201 highscore_show(position, highscores, NUM_SCORES, true);
2205 /*****************************************************************************
2206 * bubbles_loaddata() loads highest level beaten.
2207 ******************************************************************************/
2208 static void bubbles_loaddata(void) {
2209 int fd;
2211 last_highlevel = highlevel = 0;
2212 /* open data file */
2213 fd = rb->open(DATA_FILE, O_RDONLY);
2214 if (fd < 0) return;
2216 /* read in saved game */
2217 if (rb->read(fd, &highlevel, sizeof(highlevel)) < (long)sizeof(highlevel))
2219 highlevel = 0;
2221 if (highlevel >= NUM_LEVELS)
2222 highlevel = NUM_LEVELS-1;
2223 last_highlevel = highlevel;
2225 rb->close(fd);
2228 /*****************************************************************************
2229 * bubbles_savedata() saves the current game state.
2230 ******************************************************************************/
2231 static void bubbles_savedata(void) {
2232 int fd;
2234 if (last_highlevel >= highlevel) /* no need to save */
2235 return;
2237 fd = rb->open(DATA_FILE, O_WRONLY|O_CREAT, 0666);
2238 if (fd < 0) return;
2240 rb->write(fd, &highlevel, sizeof(highlevel));
2242 rb->close(fd);
2245 /*****************************************************************************
2246 * bubbles_loadgame() loads the saved game and returns load success.
2247 ******************************************************************************/
2248 static bool bubbles_loadgame(struct game_context* bb) {
2249 int fd;
2251 bool ret = true;
2252 /* open game file */
2253 fd = rb->open(SAVE_FILE, O_RDONLY);
2254 if(fd < 0) return false;
2256 /* read in saved game */
2257 if(rb->read(fd, bb, sizeof(struct game_context))
2258 < (long)sizeof(struct game_context))
2260 ret = false;
2263 rb->close(fd);
2265 return ret;
2268 /*****************************************************************************
2269 * bubbles_savegame() saves the current game state.
2270 ******************************************************************************/
2271 static void bubbles_savegame(struct game_context* bb) {
2272 int fd;
2274 if (!resume) /* nothing to save */
2275 return;
2276 /* write out the game state to the save file */
2277 fd = rb->open(SAVE_FILE, O_WRONLY|O_CREAT, 0666);
2278 if (fd < 0)
2280 rb->splash(HZ/2, "Failed to save game");
2281 return;
2283 if (rb->write(fd, bb, sizeof(struct game_context)) <= 0)
2285 rb->splash(HZ/2, "Failed to save game");
2288 rb->close(fd);
2291 /*****************************************************************************
2292 * bubbles_setcolors() set the foreground and background colors.
2293 ******************************************************************************/
2294 static inline void bubbles_setcolors(void) {
2295 #ifdef HAVE_LCD_COLOR
2296 rb->lcd_set_background(LCD_RGBPACK(181,181,222));
2297 rb->lcd_set_foreground(LCD_BLACK);
2298 #endif
2301 /*****************************************************************************
2302 * bubbles_callback() is the default event handler callback which is called
2303 * on usb connect and shutdown.
2304 ******************************************************************************/
2305 static void bubbles_callback(void* param) {
2306 (void) param;
2307 highscore_save(SCORE_FILE, highscores, NUM_SCORES);
2310 /*****************************************************************************
2311 * bubbles_handlebuttons() handles button events during a game.
2312 ******************************************************************************/
2313 static int bubbles_handlebuttons(struct game_context* bb, bool animblock,
2314 int timeout) {
2315 int button;
2316 int buttonres;
2317 long start;
2318 const struct button_mapping *plugin_contexts[]
2319 = { pla_main_ctx,
2320 #ifdef HAVE_REMOTE_LCD
2321 pla_remote_ctx,
2322 #endif
2325 if (timeout < 0)
2326 timeout = 0;
2327 button = pluginlib_getaction(timeout,plugin_contexts,ARRAYLEN(plugin_contexts));
2328 #if defined(HAS_BUTTON_HOLD) && !defined(HAVE_REMOTE_LCD_AS_MAIN)
2329 /* FIXME: Should probably check remote hold here */
2330 if (rb->button_hold())
2331 button = BUBBLES_PAUSE;
2332 #endif
2334 switch(button){
2335 case BUBBLES_LEFT_REP:
2336 if(bb->angle > MIN_ANGLE) bb->angle -= ANGLE_STEP_REP;
2337 case BUBBLES_LEFT: /* change angle to the left */
2338 if(bb->angle > MIN_ANGLE) bb->angle -= ANGLE_STEP;
2339 break;
2341 case BUBBLES_RIGHT_REP:
2342 if(bb->angle < MAX_ANGLE) bb->angle += ANGLE_STEP_REP;
2343 case BUBBLES_RIGHT: /* change angle to the right */
2344 if(bb->angle < MAX_ANGLE) bb->angle += ANGLE_STEP;
2345 break;
2347 case BUBBLES_FIRE: /* fire the shot */
2348 case BUBBLES_FIRE_REPEAT:
2349 if(!animblock) {
2350 bb->elapsedlvl += bb->elapsedshot;
2351 bb->elapsedshot = 0;
2352 buttonres = bubbles_fire(bb);
2353 if(buttonres != BB_NONE) return buttonres;
2354 buttonres = bubbles_checklevel(bb);
2355 if(buttonres != BB_NONE) return buttonres;
2356 bb->startedshot = *rb->current_tick;
2358 break;
2360 case BUBBLES_PAUSE: /* pause the game */
2361 start = *rb->current_tick;
2362 rb->splash(0, "Paused");
2364 while(pluginlib_getaction(TIMEOUT_BLOCK,plugin_contexts,
2365 ARRAYLEN(plugin_contexts))
2366 != BUBBLES_PAUSE);
2367 bb->startedshot += *rb->current_tick-start;
2368 bubbles_drawboard(bb);
2369 rb->lcd_update();
2370 break;
2372 case BUBBLES_QUIT1:
2373 case BUBBLES_QUIT2: /* end the game */
2374 if(!animblock) {
2375 resume = true;
2376 return BB_END;
2378 break;
2380 case ACTION_UNKNOWN:
2381 case ACTION_NONE: /* no button pressed */
2382 break;
2384 default:
2385 if(rb->default_event_handler_ex(button, bubbles_callback,
2386 (void*) bb) == SYS_USB_CONNECTED)
2387 return BB_USB;
2388 break;
2391 return BB_NONE;
2394 static int bubbles_menu_cb(int action, const struct menu_item_ex *this_item)
2396 int i = ((intptr_t)this_item);
2397 if(action == ACTION_REQUEST_MENUITEM
2398 && !resume && (i==0))
2399 return ACTION_EXIT_MENUITEM;
2400 return action;
2403 /*****************************************************************************
2404 * bubbles_menu() is the initial menu at the start of the game.
2405 ******************************************************************************/
2406 static int bubbles_menu(struct game_context* bb) {
2407 static unsigned int startlevel = 0;
2408 int selected = 0;
2409 bool startgame = false;
2411 MENUITEM_STRINGLIST(menu,"Bubbles Menu",bubbles_menu_cb,
2412 "Resume Game", "Start New Game",
2413 "Level", "High Scores", "Playback Control",
2414 "Quit without Saving", "Quit");
2416 while(!startgame){
2417 switch (rb->do_menu(&menu, &selected, NULL, false))
2419 case 0: /* resume game */
2420 startgame = true;
2421 if(resume_file)
2422 rb->remove(SAVE_FILE);
2423 resume_file = false;
2424 break;
2425 case 1: /* new game */
2426 bb->level = startlevel;
2427 startgame = true;
2428 resume = false;
2429 resume_file = false;
2430 break;
2431 case 2: /* choose level */
2432 startlevel++;
2433 rb->set_int("Choose start level", "", UNIT_INT, &startlevel,
2434 NULL, 1, 1, highlevel+1, NULL);
2435 startlevel--;
2436 break;
2437 case 3: /* High scores */
2438 highscore_show(-1, highscores, NUM_SCORES, true);
2439 break;
2440 case 4: /* Playback Control */
2441 playback_control(NULL);
2442 break;
2443 case 5: /* quit but don't save */
2444 return BB_QUIT_WITHOUT_SAVING;
2445 case 6: /* save and quit */
2446 return BB_QUIT;
2447 case MENU_ATTACHED_USB:
2448 bubbles_callback(bb);
2449 return BB_USB;
2452 return 0;
2455 /*****************************************************************************
2456 * bubbles() is the main game subroutine, it returns the final game status.
2457 ******************************************************************************/
2458 static int bubbles(struct game_context* bb) {
2459 int buttonres;
2460 long timeout;
2462 /********************
2463 * menu *
2464 ********************/
2465 buttonres = bubbles_menu(bb);
2466 if(buttonres != 0)
2467 return buttonres;
2469 /********************
2470 * init *
2471 ********************/
2472 bubbles_init(bb);
2473 bubbles_drawboard(bb);
2474 rb->lcd_update();
2476 /**********************
2477 * play *
2478 **********************/
2479 bb->startedshot = *rb->current_tick;
2481 while(true) {
2482 /* refresh the board */
2483 bubbles_drawboard(bb);
2484 rb->lcd_update();
2486 /* manange idle framerate */
2487 bb->elapsedshot = *rb->current_tick-bb->startedshot;
2489 if(MAX_SHOTTIME-bb->elapsedshot < HZ/2) {
2490 timeout = MAX_SHOTTIME-bb->elapsedshot;
2491 } else {
2492 timeout = HZ/2;
2495 /* handle button events */
2496 buttonres = bubbles_handlebuttons(bb, false, timeout);
2497 if(buttonres != BB_NONE) return buttonres;
2499 /* handle timing */
2500 bb->elapsedshot = *rb->current_tick-bb->startedshot;
2502 if(bb->elapsedshot > MAX_SHOTTIME) {
2503 bb->elapsedlvl += bb->elapsedshot;
2504 bb->elapsedshot = 0;
2505 buttonres = bubbles_fire(bb);
2506 if(buttonres != BB_NONE) return buttonres;
2507 buttonres = bubbles_checklevel(bb);
2508 if(buttonres != BB_NONE) return buttonres;
2509 bb->startedshot = *rb->current_tick;
2514 /*****************************************************************************
2515 * plugin entry point.
2516 ******************************************************************************/
2517 enum plugin_status plugin_start(const void* parameter) {
2518 static struct game_context bb;
2519 bool exit = false;
2520 enum plugin_status ret = PLUGIN_OK;
2522 (void)parameter;
2524 /* load files */
2525 resume = bubbles_loadgame(&bb);
2526 resume_file = resume;
2527 bubbles_loaddata();
2528 highscore_load(SCORE_FILE, highscores, NUM_SCORES);
2529 rb->lcd_clear_display();
2531 /* start app */
2532 #if LCD_DEPTH > 1
2533 rb->lcd_set_backdrop(NULL);
2534 #endif
2535 rb->lcd_setfont(FONT_SYSFIXED);
2537 while(!exit) {
2538 switch(bubbles(&bb)){
2539 case BB_WIN:
2540 rb->splash(HZ*2, "You Win!");
2541 /* record high level */
2542 highlevel = NUM_LEVELS-1;
2543 /* record high score */
2544 bubbles_recordscore(&bb);
2545 break;
2547 case BB_LOSE:
2548 resume = false;
2549 rb->splash(HZ*2, "Game Over");
2550 /* record high score */
2551 bubbles_recordscore(&bb);
2552 /* fall through to BB_END */
2554 case BB_END:
2555 break;
2557 case BB_USB:
2558 ret = PLUGIN_USB_CONNECTED;
2559 exit = true;
2560 break;
2562 case BB_QUIT:
2563 rb->splash(HZ/3, "Saving game data ...");
2564 bubbles_savegame(&bb);
2565 bubbles_savedata();
2566 highscore_save(SCORE_FILE, highscores, NUM_SCORES);
2567 /* fall through */
2569 case BB_QUIT_WITHOUT_SAVING:
2570 exit = true;
2571 break;
2573 default:
2574 break;
2577 rb->lcd_setfont(FONT_UI);
2578 return ret;