Manual: Bookmarking update (FS#11227 by Magnus Holmgren)
[kugel-rb.git] / apps / plugins / bubbles.c
blob514621224a9314938c8480599adca2aac03c48f8
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2005 Adam Boot
12 * Color graphics from Frozen Bubble (http://www.frozen-bubble.org/)
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
22 ****************************************************************************/
24 #include "plugin.h"
26 #ifdef HAVE_LCD_BITMAP
28 #include "lib/xlcd.h"
29 #include "lib/pluginlib_actions.h"
30 #include "lib/fixedpoint.h"
31 #include "lib/playback_control.h"
32 #include "lib/highscore.h"
34 PLUGIN_HEADER
36 /* files */
37 #define SCORE_FILE PLUGIN_GAMES_DIR "/bubbles.score"
38 #define SAVE_FILE PLUGIN_GAMES_DIR "/bubbles.save"
39 #define DATA_FILE PLUGIN_GAMES_DIR "/bubbles.data"
41 /* final game return status */
42 enum {
43 BB_LOSE,
44 BB_QUIT_WITHOUT_SAVING,
45 BB_QUIT,
46 BB_USB,
47 BB_END,
48 BB_WIN,
49 BB_NONE,
52 /* play board dimension */
53 #define BB_HEIGHT 12
54 #define BB_WIDTH 8
55 #define BB_LEVEL_HEIGHT 10
57 /* various amounts */
58 #define NUM_SCORES 5
59 #define NUM_LEVELS 100
60 #define NUM_QUEUE 2
61 #define NUM_BUBBLES 8
62 #define MIN_ANGLE -76
63 #define MAX_ANGLE 76
64 #define NUM_COMPRESS 9
65 #define MAX_SHOTTIME 1000
67 /* keyboard layouts */
69 #if (CONFIG_KEYPAD != SANSA_E200_PAD) && \
70 (CONFIG_KEYPAD != SANSA_FUZE_PAD)
71 /* sansas use the wheel instead of left/right if available */
72 #define BUBBLES_LEFT PLA_LEFT
73 #define BUBBLES_LEFT_REP PLA_LEFT_REPEAT
74 #define BUBBLES_RIGHT PLA_RIGHT
75 #define BUBBLES_RIGHT_REP PLA_RIGHT_REPEAT
76 #define ANGLE_STEP 4
77 #define ANGLE_STEP_REP 4
78 #else
79 #define BUBBLES_LEFT PLA_UP
80 #define BUBBLES_LEFT_REP PLA_UP_REPEAT
81 #define BUBBLES_RIGHT PLA_DOWN
82 #define BUBBLES_RIGHT_REP PLA_DOWN_REPEAT
83 #define ANGLE_STEP 2
84 #define ANGLE_STEP_REP 4
85 #endif
87 #define BUBBLES_QUIT1 PLA_QUIT
88 #define BUBBLES_QUIT2 PLA_MENU
89 #define BUBBLES_PAUSE PLA_START
90 #define BUBBLES_FIRE PLA_FIRE
92 /* external bitmaps */
93 #ifdef HAVE_LCD_COLOR
94 #include "pluginbitmaps/bubbles_background.h"
95 #endif
96 #include "pluginbitmaps/bubbles_bubble.h"
97 #include "pluginbitmaps/bubbles_emblem.h"
99 #define BUBBLE_WIDTH BMPWIDTH_bubbles_bubble
100 #define BUBBLE_HEIGHT BMPHEIGHT_bubbles_bubble
101 #define EMBLEM_WIDTH BMPWIDTH_bubbles_emblem
102 #define EMBLEM_HEIGHT (BMPHEIGHT_bubbles_emblem/8)
104 /* bubbles will consume height of ROW_HEIGHT*(BB_HEIGHT-1)+BUBBLE_HEIGHT*3/2 */
105 /* 44x44 bubbles (m:robe 500) */
106 #if (LCD_WIDTH == 640) && (LCD_HEIGHT == 480)
107 #define XOFS 144
108 #define MAX_FPS 40
110 #elif (LCD_WIDTH == 480) && (LCD_HEIGHT == 640)
111 #define XOFS 128
112 #define MAX_FPS 40
114 /* 22x22 bubbles (iPod Video) */
115 #elif (LCD_HEIGHT == 240) && (LCD_WIDTH == 320)
116 #define XOFS 72
117 #define MAX_FPS 40
119 /* 22x22 bubbles (Gigabeat, Onda VX747) */
120 #elif ((LCD_HEIGHT == 320) || (LCD_HEIGHT == 400)) && (LCD_WIDTH == 240)
121 #define XOFS 64
122 #define MAX_FPS 30
124 /* 16x16 bubbles (H300, iPod Color, HDD6330) */
125 #elif (LCD_HEIGHT == 176) && (LCD_WIDTH == 220)
126 #define XOFS 46
127 #define MAX_FPS 30
129 /* 16x16 bubbles (Sansa E200) */
130 #elif (LCD_HEIGHT == 220) && (LCD_WIDTH == 176)
131 #define XOFS 24
132 #define MAX_FPS 30
133 #define YOFS 45
135 /* custom text positioning */
136 #define LEVEL_TXT_X 24
137 #define LEVEL_TXT_WIDTH 31
138 #define LEVEL_TXT_Y 5
139 #define SCORE_TXT_X 58
140 #define SCORE_TXT_WIDTH 31
141 #define SCORE_TXT_Y 5
142 #define NEXT_BB_X 112
143 #define NEXT_BB_WIDTH 31
144 #define NEXT_BB_Y 3
146 /* 12x12 bubbles (iPod Nano) */
147 #elif (LCD_HEIGHT == 132) && (LCD_WIDTH == 176)
148 #define XOFS 40
149 #define MAX_FPS 40
151 /* 12x12 bubbles (H100, H10, iAudio X5, HDD1630, iPod 3G, iPod 4G grayscale) */
152 #elif (LCD_HEIGHT == 128) && ((LCD_WIDTH == 160) || (LCD_WIDTH == 128))
153 #define XOFS 33
154 #define MAX_FPS 30
156 /* 12x12 bubbles (GoGear SA9200) */
157 #elif (LCD_HEIGHT == 160) && (LCD_WIDTH == 128)
158 #define XOFS 33
159 #define ROW_HEIGHT 10
160 #define ROW_INDENT 6
161 #define MAX_FPS 30
163 /* 10x10 bubbles (iPod Mini) */
164 #elif (LCD_HEIGHT == 110) && (LCD_WIDTH == 138)
165 #define XOFS 33
166 #define MAX_FPS 30
168 /* 9x9 bubbles (iAudio M3) */
169 #elif (LCD_HEIGHT == 96) && (LCD_WIDTH == 128)
170 #define XOFS 45
171 #define MAX_FPS 30
173 /* 8x8 bubbles (Sansa C200) */
174 #elif ((LCD_HEIGHT == 80) && (LCD_WIDTH == 132))
175 #define XOFS 45
176 #define ROW_HEIGHT 6
177 #define MAX_FPS 30
179 /* 7x7 bubbles (Sansa Clip/m200) */
180 #elif (LCD_HEIGHT == 64 && LCD_WIDTH == 128)
181 #define XOFS 33
182 #define ROW_HEIGHT 5
183 #define MAX_FPS 30
185 /* 8x7 bubbles (Archos recorder, Ondio) */
186 #elif (LCD_HEIGHT == 64) && (LCD_WIDTH == 112)
187 #define XOFS 33
188 #define ROW_HEIGHT 5
189 #define MAX_FPS 20
191 #else
192 #error BUBBLES: Unsupported LCD type
193 #endif
195 #if !defined(ROW_HEIGHT)
196 #define ROW_HEIGHT (BUBBLE_WIDTH-(BUBBLE_WIDTH-EMBLEM_WIDTH)/2)
197 #endif
199 #define ROW_INDENT (BUBBLE_WIDTH/2)
201 #define TEXT_LINES (LCD_HEIGHT/8)
203 #ifndef YOFS
204 #define YOFS 0
205 #endif
207 /* shot position */
208 #define SHOTX XOFS+ROW_INDENT+BUBBLE_WIDTH*3
209 #define SHOTY (YOFS+ROW_HEIGHT*(BB_HEIGHT-1)+BUBBLE_HEIGHT/2)
211 /* collision distance squared */
212 #define MIN_DISTANCE ((BUBBLE_WIDTH*8)/10)*((BUBBLE_HEIGHT*8)/10)
214 /* levels */
215 char level[NUM_LEVELS][BB_LEVEL_HEIGHT][BB_WIDTH] = {
216 {{ 6, 6, 4, 4, 2, 2, 3, 3},
217 { 6, 6, 4, 4, 2, 2, 3, -1},
218 { 2, 2, 3, 3, 6, 6, 4, 4},
219 { 2, 3, 3, 6, 6, 4, 4, -1},
220 {-1, -1, -1, -1, -1, -1, -1, -1},
221 {-1, -1, -1, -1, -1, -1, -1, -1},
222 {-1, -1, -1, -1, -1, -1, -1, -1},
223 {-1, -1, -1, -1, -1, -1, -1, -1},
224 {-1, -1, -1, -1, -1, -1, -1, -1},
225 {-1, -1, -1, -1, -1, -1, -1, -1}},
226 {{-1, 7, 7, 7, 7, 7, 7, -1},
227 {-1, 1, 1, 1, 1, 1, -1, -1},
228 {-1, -1, 2, 2, 2, 2, -1, -1},
229 {-1, -1, -1, 2, -1, -1, -1, -1},
230 {-1, -1, -1, 2, 2, -1, -1, -1},
231 {-1, -1, -1, 5, -1, -1, -1, -1},
232 {-1, -1, -1, 5, 5, -1, -1, -1},
233 {-1, -1, -1, -1, -1, -1, -1, -1},
234 {-1, -1, -1, -1, -1, -1, -1, -1},
235 {-1, -1, -1, -1, -1, -1, -1, -1}},
236 {{-1, -1, 7, -1, -1, 7, -1, -1},
237 {-1, -1, 7, 1, 7, -1, -1, -1},
238 {-1, -1, -1, 1, 2, -1, -1, -1},
239 {-1, -1, 1, 2, 1, -1, -1, -1},
240 {-1, -1, -1, 2, 5, -1, -1, -1},
241 {-1, -1, 3, 5, 3, -1, -1, -1},
242 {-1, -1, -1, 5, 3, -1, -1, -1},
243 {-1, -1, -1, 3, -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, 0, 0, -1, -1, -1},
247 {-1, -1, 5, 0, 1, -1, -1, -1},
248 {-1, -1, 3, 5, 1, 6, -1, -1},
249 {-1, 4, 3, -1, 6, 7, -1, -1},
250 {-1, 7, 4, -1, -1, 7, 4, -1},
251 { 6, 7, -1, -1, -1, 4, 3, -1},
252 { 1, 6, -1, -1, -1, -1, 3, 5},
253 { 1, -1, -1, -1, -1, -1, 5, -1},
254 {-1, -1, -1, -1, -1, -1, -1, -1},
255 {-1, -1, -1, -1, -1, -1, -1, -1}},
256 {{-1, -1, 0, 0, 0, 0, -1, -1},
257 {-1, 0, 1, 1, 1, 0, -1, -1},
258 {-1, 0, 1, 0, 0, 1, 0, -1},
259 {-1, 0, 1, 1, 1, 0, -1, -1},
260 {-1, -1, 0, 0, 0, 0, -1, -1},
261 {-1, -1, 7, -1, 7, -1, -1, -1},
262 {-1, -1, 7, 7, 7, 7, -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, 4, 4, 4, 6, 6, 6, -1},
267 { 4, -1, -1, -1, -1, -1, 6, -1},
268 {-1, 4, -1, -1, -1, -1, 6, -1},
269 { 4, 2, 3, 1, 2, 3, 6, -1},
270 {-1, 3, 1, 2, 3, 1, 2, -1},
271 {-1, -1, -1, -1, -1, -1, -1, -1},
272 {-1, -1, -1, -1, -1, -1, -1, -1},
273 {-1, -1, -1, -1, -1, -1, -1, -1},
274 {-1, -1, -1, -1, -1, -1, -1, -1},
275 {-1, -1, -1, -1, -1, -1, -1, -1}},
276 {{-1, 4, 4, 4, 6, 6, 6, -1},
277 { 4, -1, -1, -1, -1, -1, 6, -1},
278 {-1, 4, -1, -1, -1, -1, 6, -1},
279 { 4, 2, 3, 1, 2, 3, 6, -1},
280 {-1, 3, 1, 2, 3, 1, 2, -1},
281 {-1, 2, 3, 1, 2, 3, -1, -1},
282 {-1, -1, -1, -1, -1, -1, -1, -1},
283 {-1, -1, -1, -1, -1, -1, -1, -1},
284 {-1, -1, -1, -1, -1, -1, -1, -1},
285 {-1, -1, -1, -1, -1, -1, -1, -1}},
286 {{-1, 0, 0, -1, -1, 2, 2, -1},
287 {-1, 5, -1, -1, -1, 3, -1, -1},
288 {-1, 0, -1, -1, -1, 6, -1, -1},
289 {-1, 3, -1, -1, -1, 0, -1, -1},
290 {-1, 4, -1, -1, -1, 5, -1, -1},
291 {-1, 2, -1, -1, -1, 3, -1, -1},
292 {-1, 2, -1, -1, -1, 1, -1, -1},
293 {-1, 3, -1, -1, -1, 4, -1, -1},
294 {-1, -1, -1, -1, -1, -1, -1, -1},
295 {-1, -1, -1, -1, -1, -1, -1, -1}},
296 {{ 3, -1, -1, -1, -1, -1, -1, 3},
297 { 6, 3, 2, 4, 6, 3, 2, -1},
298 { 4, -1, -1, -1, -1, -1, -1, 4},
299 { 2, 4, 6, 3, 2, 4, 6, -1},
300 {-1, -1, -1, 6, -1, -1, -1, -1},
301 {-1, -1, -1, 3, -1, -1, -1, -1},
302 {-1, -1, -1, -1, -1, -1, -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, 2, -1, 1, -1, 1, -1, 2},
307 { 1, 2, -1, 2, 1, -1, 1, -1},
308 { 1, -1, 1, -1, 2, -1, 2, -1},
309 { 2, 1, -1, 1, 2, -1, 2, -1},
310 {-1, 2, -1, 2, -1, 2, -1, 2},
311 { 1, 2, -1, 2, 1, -1, 1, -1},
312 { 1, -1, 1, -1, 2, -1, 1, -1},
313 { 2, 2, -1, 1, 1, -1, 2, -1},
314 {-1, 2, -1, 1, -1, 1, -1, 1},
315 {-1, -1, -1, -1, -1, -1, -1, -1}},
316 {{-1, 7, 7, -1, -1, 5, 5, -1},
317 { 1, -1, -1, -1, -1, -1, 4, -1},
318 { 2, 1, -1, -1, -1, -1, 4, 3},
319 { 2, -1, -1, -1, -1, -1, 3, -1},
320 { 1, 2, -1, -1, -1, -1, 3, 4},
321 { 1, -1, -1, -1, -1, -1, 4, -1},
322 { 7, 1, -1, -1, -1, -1, 4, 5},
323 { 7, 7, -1, -1, -1, 5, 5, -1},
324 {-1, -1, -1, -1, -1, -1, -1, -1},
325 {-1, -1, -1, -1, -1, -1, -1, -1}},
326 {{ 7, 7, -1, -1, -1, -1, 5, 5},
327 { 1, 5, -1, -1, -1, 7, 4, -1},
328 { 2, 1, -1, -1, -1, -1, 4, 3},
329 { 2, -1, -1, -1, -1, -1, 3, -1},
330 { 1, 5, -1, -1, -1, -1, 7, 4},
331 { 1, -1, -1, -1, -1, -1, 4, -1},
332 { 7, 1, -1, -1, -1, -1, 4, 5},
333 { 7, 5, -1, -1, -1, 7, 5, -1},
334 {-1, -1, -1, -1, -1, -1, -1, -1},
335 {-1, -1, -1, -1, -1, -1, -1, -1}},
336 {{-1, -1, -1, 0, 0, -1, -1, -1},
337 {-1, -1, 5, 0, 1, -1, -1, -1},
338 {-1, -1, 3, 5, 1, 6, -1, -1},
339 {-1, 4, 3, 2, 6, 2, -1, -1},
340 {-1, 7, 4, 7, 2, 2, 4, -1},
341 { 6, 7, 7, 3, 3, 4, 3, -1},
342 { 1, 6, 1, 1, 1, 3, 3, 5},
343 { 1, 1, -1, -1, -1, -1, 5, -1},
344 {-1, -1, -1, -1, -1, -1, -1, -1},
345 {-1, -1, -1, -1, -1, -1, -1, -1}},
346 {{-1, -1, 0, -1, -1, 0, -1, -1},
347 {-1, 3, 3, -1, 3, 3, -1, -1},
348 {-1, 0, 2, 0, 0, 2, 0, -1},
349 {-1, 3, 3, -1, 3, 3, -1, -1},
350 {-1, -1, 0, -1, -1, 0, -1, -1},
351 {-1, -1, -1, -1, -1, -1, -1, -1},
352 {-1, -1, -1, -1, -1, -1, -1, -1},
353 {-1, -1, -1, -1, -1, -1, -1, -1},
354 {-1, -1, -1, -1, -1, -1, -1, -1},
355 {-1, -1, -1, -1, -1, -1, -1, -1}},
356 {{-1, -1, -1, 1, 1, -1, -1, -1},
357 {-1, -1, 2, 2, 2, -1, -1, -1},
358 {-1, -1, 3, 3, 3, 3, -1, -1},
359 {-1, 4, 4, 4, 4, 4, -1, -1},
360 {-1, 5, 5, 5, 5, 5, 5, -1},
361 {-1, -1, -1, 6, -1, -1, -1, -1},
362 {-1, -1, -1, 7, 7, -1, -1, -1},
363 {-1, -1, -1, 0, -1, -1, -1, -1},
364 {-1, -1, -1, -1, -1, -1, -1, -1},
365 {-1, -1, -1, -1, -1, -1, -1, -1}},
366 {{-1, -1, -1, 2, 5, -1, -1, -1},
367 {-1, 4, 3, -1, -1, -1, -1, -1},
368 { 6, 7, -1, 5, 2, -1, -1, -1},
369 {-1, -1, -1, -1, 3, 4, -1, -1},
370 {-1, -1, -1, 2, 5, -1, 7, 6},
371 {-1, 4, 3, -1, -1, -1, -1, -1},
372 { 6, 7, -1, 5, 2, -1, -1, -1},
373 {-1, -1, -1, -1, 3, 4, -1, -1},
374 {-1, -1, -1, -1, -1, -1, 7, 6},
375 {-1, -1, -1, -1, -1, -1, -1, -1}},
376 {{-1, -1, -1, 5, 5, -1, -1, -1},
377 {-1, -1, -1, 3, -1, -1, -1, -1},
378 {-1, -1, -1, 1, -1, -1, -1, -1},
379 {-1, -1, -1, 7, -1, -1, -1, -1},
380 {-1, -1, -1, 2, -1, -1, -1, -1},
381 {-1, -1, -1, 4, -1, -1, -1, -1},
382 {-1, -1, -1, 5, -1, -1, -1, -1},
383 {-1, -1, -1, 3, -1, -1, -1, -1},
384 {-1, -1, -1, -1, -1, -1, -1, -1},
385 {-1, -1, -1, -1, -1, -1, -1, -1}},
386 {{-1, -1, -1, 0, 1, -1, -1, -1},
387 {-1, -1, 0, 2, 7, 7, -1, -1},
388 {-1, -1, -1, 0, 1, 7, -1, -1},
389 {-1, 0, 0, 0, 0, -1, -1, -1},
390 {-1, 0, 0, 0, 1, 1, -1, -1},
391 { 0, 0, 0, 1, 1, 1, -1, -1},
392 {-1, 0, 0, 1, 1, 1, -1, -1},
393 {-1, 0, 0, 0, 7, 7, -1, -1},
394 {-1, -1, 7, 7, -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, -1, -1, -1, -1, -1, -1},
398 {-1, 2, 3, 4, 7, 6, 5, -1},
399 {-1, -1, -1, -1, -1, -1, 1, -1},
400 {-1, -1, -1, -1, -1, -1, 1, -1},
401 {-1, 2, 3, 4, 7, 6, -1, -1},
402 {-1, 1, -1, -1, -1, -1, -1, -1},
403 { 1, -1, -1, -1, -1, -1, -1, -1},
404 {-1, 2, 3, 4, 7, 6, 5, -1},
405 {-1, -1, -1, -1, -1, -1, -1, -1}},
406 {{-1, 6, -1, -1, -1, -1, -1, -1},
407 { 5, -1, -1, -1, -1, -1, -1, -1},
408 { 2, 3, 4, 7, 6, 5, 2, 3},
409 {-1, -1, -1, -1, -1, -1, 4, -1},
410 {-1, -1, -1, -1, -1, -1, 7, -1},
411 {-1, 4, 3, 2, 5, 6, -1, -1},
412 {-1, 7, -1, -1, -1, -1, -1, -1},
413 { 6, -1, -1, -1, -1, -1, -1, -1},
414 { 5, 2, 3, 4, 7, 6, 5, -1},
415 {-1, -1, -1, -1, -1, -1, -1, -1}},
416 {{ 3, 2, 1, 0, 0, 1, 2, 3},
417 { 3, 2, 1, 0, 1, 2, 3, -1},
418 { 4, 3, 2, 1, 1, 2, 3, 4},
419 { 4, 3, 2, 1, 2, 3, 4, -1},
420 { 5, 4, 3, 2, 2, 3, 4, 5},
421 { 5, 4, 3, 2, 3, 4, 5, -1},
422 { 6, 5, 4, 3, 3, 4, 5, 6},
423 { 6, 5, 4, 3, 4, 5, 6, -1},
424 { 7, 6, 5, 4, 4, 5, 6, 7},
425 {-1, -1, -1, -1, -1, -1, -1, -1}},
426 {{-1, -1, -1, 5, 5, -1, -1, -1},
427 {-1, -1, -1, 3, -1, -1, -1, -1},
428 {-1, -1, -1, 2, 4, -1, -1, -1},
429 {-1, -1, -1, 6, -1, -1, -1, -1},
430 {-1, -1, -1, 2, 4, -1, -1, -1},
431 {-1, 2, -1, 5, -1, 4, -1, -1},
432 { 1, 0, 1, 0, 1, 0, 1, 0},
433 { 3, -1, 3, -1, 2, -1, 6, -1},
434 {-1, -1, -1, -1, -1, -1, -1, -1},
435 {-1, -1, -1, -1, -1, -1, -1, -1}},
436 {{-1, -1, -1, -1, 1, -1, -1, -1},
437 { 7, 4, 3, 5, -1, -1, -1, -1},
438 { 6, -1, -1, 1, -1, -1, -1, -1},
439 {-1, -1, -1, 5, 3, 4, 7, -1},
440 { 6, -1, -1, -1, 1, -1, -1, 6},
441 { 7, 4, 3, 5, -1, -1, -1, -1},
442 {-1, -1, -1, 1, -1, -1, -1, 6},
443 {-1, -1, -1, 5, 3, 4, 7, -1},
444 {-1, -1, -1, -1, -1, -1, -1, -1},
445 {-1, -1, -1, -1, -1, -1, -1, -1}},
446 {{-1, -1, -1, -1, 7, 3, 6, -1},
447 {-1, -1, 3, 7, 3, 6, 3, -1},
448 {-1, -1, 5, 7, 3, 6, 3, -1},
449 {-1, 6, 7, 3, 6, 7, -1, -1},
450 {-1, 7, 7, 3, 6, 1, -1, -1},
451 { 3, 7, 3, 6, 3, -1, -1, -1},
452 { 5, 6, 2, 7, 1, -1, -1, -1},
453 {-1, -1, -1, -1, -1, -1, -1, -1},
454 {-1, -1, -1, -1, -1, -1, -1, -1},
455 {-1, -1, -1, -1, -1, -1, -1, -1}},
456 {{ 5, -1, -1, -1, -1, -1, -1, 5},
457 { 5, -1, 6, 6, 6, -1, 5, -1},
458 {-1, 5, 4, -1, -1, 4, 5, -1},
459 {-1, 3, -1, -1, -1, 3, -1, -1},
460 {-1, 6, 0, -1, -1, 0, 6, -1},
461 {-1, 3, -1, -1, -1, 3, -1, -1},
462 {-1, -1, 4, -1, -1, 4, -1, -1},
463 {-1, -1, 6, 6, 6, -1, -1, -1},
464 {-1, -1, -1, -1, -1, -1, -1, -1},
465 {-1, -1, -1, -1, -1, -1, -1, -1}},
466 {{-1, 7, 0, -1, -1, 0, 7, -1},
467 { 7, -1, 0, -1, 0, -1, 7, -1},
468 { 7, 1, -1, 0, 0, -1, 1, 7},
469 { 7, 1, 2, 0, 2, 1, 7, -1},
470 { 7, 6, 3, 2, 2, 3, 6, 7},
471 { 7, -1, 3, 2, 3, -1, 7, -1},
472 {-1, 7, 7, 3, 3, 7, 7, -1},
473 {-1, -1, -1, 3, -1, -1, -1, -1},
474 {-1, -1, -1, -1, -1, -1, -1, -1},
475 {-1, -1, -1, -1, -1, -1, -1, -1}},
476 {{-1, 3, -1, 1, -1, 7, -1, 6},
477 { 5, -1, 7, -1, 7, -1, 6, -1},
478 { 6, -1, 0, -1, 5, -1, 3, -1},
479 {-1, 2, -1, 1, -1, 5, -1, -1},
480 {-1, 4, -1, 3, -1, 4, -1, -1},
481 { 2, -1, 3, -1, 2, -1, -1, -1},
482 {-1, -1, 4, -1, 6, -1, -1, -1},
483 {-1, -1, -1, 5, -1, -1, -1, -1},
484 {-1, -1, -1, -1, -1, -1, -1, -1},
485 {-1, -1, -1, -1, -1, -1, -1, -1}},
486 {{-1, -1, -1, -1, 1, -1, -1, -1},
487 {-1, -1, -1, -1, 3, -1, -1, -1},
488 { 6, 1, 3, 1, 2, 1, 4, 1},
489 {-1, -1, -1, -1, 6, -1, -1, -1},
490 {-1, -1, -1, 4, 1, -1, -1, -1},
491 {-1, -1, 1, -1, 3, -1, -1, -1},
492 {-1, -1, -1, 2, 1, -1, -1, -1},
493 {-1, -1, -1, -1, 4, -1, -1, -1},
494 {-1, -1, -1, 6, 1, -1, -1, -1},
495 {-1, -1, -1, 6, -1, -1, -1, -1}},
496 {{-1, -1, -1, 5, 4, -1, -1, -1},
497 {-1, -1, 4, 1, 0, -1, -1, -1},
498 {-1, -1, -1, 2, 3, -1, -1, -1},
499 {-1, 1, 4, -1, 2, 2, -1, -1},
500 {-1, 3, 1, 2, 5, 1, 4, -1},
501 {-1, 4, 2, -1, 0, 4, -1, -1},
502 {-1, -1, -1, -1, -1, -1, -1, -1},
503 {-1, -1, -1, -1, -1, -1, -1, -1},
504 {-1, -1, -1, -1, -1, -1, -1, -1},
505 {-1, -1, -1, -1, -1, -1, -1, -1}},
506 {{-1, -1, -1, -1, 1, -1, -1, -1},
507 {-1, -1, -1, 1, -1, -1, -1, -1},
508 {-1, 2, -1, -1, 1, -1, 5, -1},
509 { 5, -1, -1, 1, -1, -1, 0, -1},
510 {-1, 6, -1, -1, 1, -1, 4, -1},
511 {-1, 0, -1, 1, -1, 5, -1, -1},
512 {-1, -1, 5, 5, 0, 1, -1, -1},
513 {-1, -1, -1, -1, -1, -1, -1, -1},
514 {-1, -1, -1, -1, -1, -1, -1, -1},
515 {-1, -1, -1, -1, -1, -1, -1, -1}},
516 {{-1, -1, -1, 6, 3, -1, -1, -1},
517 {-1, -1, 3, 2, 6, -1, -1, -1},
518 {-1, -1, 2, 6, 3, 2, -1, -1},
519 {-1, 6, 3, 2, 6, 3, -1, -1},
520 {-1, 3, 2, 6, 3, 2, 6, -1},
521 { 2, 6, 3, 2, 6, 3, 2, -1},
522 { 6, 3, 2, 6, 3, 2, 6, 3},
523 {-1, -1, -1, -1, -1, -1, -1, -1},
524 {-1, -1, -1, -1, -1, -1, -1, -1},
525 {-1, -1, -1, -1, -1, -1, -1, -1}},
526 {{ 6, 6, 6, 6, 6, 6, 6, 6},
527 { 4, -1, -1, -1, -1, -1, -1, -1},
528 {-1, 3, 2, 5, 7, 6, 4, 3},
529 {-1, 5, -1, -1, -1, -1, -1, -1},
530 {-1, -1, 7, 6, 4, 3, 2, 5},
531 {-1, -1, 4, -1, -1, -1, -1, -1},
532 {-1, -1, -1, 3, 2, 5, 7, 6},
533 {-1, -1, -1, -1, -1, -1, -1, -1},
534 {-1, -1, -1, -1, -1, -1, -1, -1},
535 {-1, -1, -1, -1, -1, -1, -1, -1}},
536 {{ 1, -1, 7, -1, -1, 6, -1, 2},
537 { 6, -1, 1, -1, 6, 1, 3, -1},
538 {-1, 4, -1, 7, 2, -1, 7, -1},
539 { 2, 7, -1, -1, -1, 4, -1, -1},
540 { 6, -1, 3, 5, 0, 2, -1, 7},
541 { 1, -1, -1, -1, -1, -1, 1, -1},
542 {-1, 1, 4, 5, 7, 5, 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 {{ 6, 6, 6, -1, -1, 6, 6, 6},
547 {-1, -1, 6, -1, 6, -1, -1, -1},
548 {-1, -1, 2, 3, 3, 2, -1, -1},
549 {-1, 3, -1, 5, -1, 3, -1, -1},
550 {-1, -1, 5, 3, 3, 5, -1, -1},
551 {-1, -1, 6, 1, 6, -1, -1, -1},
552 {-1, 4, 2, -1, -1, 2, 4, -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, 5, 5, -1, -1, -1},
557 {-1, -1, 5, -1, -1, -1, -1, -1},
558 {-1, 3, 4, 6, 6, -1, -1, 5},
559 { 3, 3, 4, 6, 5, -1, 5, -1},
560 { 3, 2, 3, 6, 6, 5, 5, -1},
561 { 3, 3, 4, 6, 5, -1, 5, -1},
562 {-1, 3, 4, 6, 6, -1, -1, 5},
563 {-1, -1, 5, -1, -1, -1, -1, -1},
564 {-1, -1, -1, 5, 5, -1, -1, -1},
565 {-1, -1, -1, -1, -1, -1, -1, -1}},
566 {{ 1, -1, -1, -1, -1, -1, -1, 1},
567 { 1, -1, 2, 2, 2, -1, 1, -1},
568 {-1, 1, 2, 3, 3, 2, 1, -1},
569 { 6, 2, 3, -1, 3, 2, 6, -1},
570 { 6, 2, 3, -1, -1, 3, 2, 6},
571 { 6, 2, 3, -1, 3, 2, 6, -1},
572 { 3, 3, 3, 7, 7, 3, 3, 3},
573 { 0, 5, 0, 2, 0, 5, 0, -1},
574 {-1, -1, -1, -1, -1, -1, -1, -1},
575 {-1, -1, -1, -1, -1, -1, -1, -1}},
576 {{-1, -1, 7, 7, 7, -1, -1, -1},
577 {-1, 7, 2, 2, 7, -1, -1, -1},
578 {-1, 7, 5, 5, 5, 7, -1, -1},
579 { 7, 7, 7, 7, 7, 7, -1, -1},
580 {-1, -1, 6, -1, 6, -1, -1, -1},
581 {-1, 6, -1, -1, 6, -1, -1, -1},
582 {-1, 6, 4, 4, -1, 6, 4, 4},
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 {{-1, 3, 3, -1, 3, 3, 3, -1},
587 { 3, 7, 5, 4, 6, 5, 3, -1},
588 { 1, 3, 3, 3, -1, 3, 3, 1},
589 { 2, 1, 2, 1, 2, 1, 2, -1},
590 { 1, 3, 3, -1, 3, 3, 3, 1},
591 { 3, 5, 6, 4, 5, 7, 3, -1},
592 { 2, 3, 3, 3, -1, 3, 3, 2},
593 { 1, 1, 2, 2, 2, 1, 1, -1},
594 {-1, -1, -1, -1, -1, -1, -1, -1},
595 {-1, -1, -1, -1, -1, -1, -1, -1}},
596 {{-1, 6, 5, -1, -1, -1, -1, -1},
597 { 3, 1, 3, -1, -1, -1, -1, -1},
598 {-1, 5, 6, -1, -1, -1, -1, -1},
599 {-1, -1, 5, 3, -1, -1, -1, -1},
600 {-1, -1, 6, 1, 6, -1, -1, -1},
601 {-1, -1, 3, 5, -1, -1, -1, -1},
602 {-1, -1, -1, -1, 3, 6, -1, -1},
603 {-1, -1, -1, 5, 6, 5, -1, -1},
604 {-1, -1, -1, -1, 6, 3, -1, -1},
605 {-1, -1, -1, -1, -1, -1, -1, -1}},
606 {{ 6, 3, 7, 4, 5, 1, 6, 3},
607 { 5, 1, 6, 3, 7, 4, 5, -1},
608 { 6, 3, 7, 4, 5, 1, 6, 3},
609 {-1, -1, -1, -1, -1, -1, -1, -1},
610 {-1, -1, -1, -1, -1, -1, -1, -1},
611 {-1, -1, -1, -1, -1, -1, -1, -1},
612 {-1, -1, -1, -1, -1, -1, -1, -1},
613 {-1, -1, -1, -1, -1, -1, -1, -1},
614 {-1, -1, -1, -1, -1, -1, -1, -1},
615 {-1, -1, -1, -1, -1, -1, -1, -1}},
616 {{-1, -1, -1, -1, -1, -1, 4, 4},
617 {-1, -1, 7, 7, 7, 4, 4, -1},
618 {-1, -1, -1, -1, -1, -1, 4, 4},
619 {-1, 1, -1, -1, -1, 7, -1, -1},
620 {-1, 1, 1, -1, -1, 7, -1, -1},
621 { 3, 3, 3, -1, 7, -1, -1, -1},
622 { 3, -1, 2, 3, 3, 3, -1, 3},
623 {-1, 2, -1, 3, -1, 3, 3, -1},
624 {-1, 2, -1, -1, -1, -1, -1, -1},
625 {-1, -1, -1, -1, -1, -1, -1, -1}},
626 {{-1, -1, 4, -1, -1, -1, -1, -1},
627 {-1, 7, 4, -1, -1, -1, -1, -1},
628 {-1, -1, 7, 4, -1, -1, -1, -1},
629 {-1, 4, 7, 4, -1, -1, -1, -1},
630 { 1, 1, 1, 1, 1, 1, 1, -1},
631 { 1, 2, 1, 2, 1, 1, -1, -1},
632 { 2, 2, 2, 2, 2, 2, 2, 2},
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 {{ 0, -1, -1, -1, -1, -1, -1, 6},
637 { 6, 1, 4, 3, 7, 5, 0, -1},
638 { 0, -1, -1, -1, -1, -1, -1, 6},
639 { 6, 1, 4, 3, 7, 5, 0, -1},
640 { 0, -1, -1, -1, -1, -1, -1, 6},
641 { 6, 1, 4, 3, 7, 5, 0, -1},
642 {-1, -1, -1, -1, -1, -1, -1, -1},
643 {-1, -1, -1, -1, -1, -1, -1, -1},
644 {-1, -1, -1, -1, -1, -1, -1, -1},
645 {-1, -1, -1, -1, -1, -1, -1, -1}},
646 {{ 3, 3, 4, 6, 6, 4, 3, 3},
647 { 0, 3, 4, 6, 4, 3, 1, -1},
648 { 5, 1, 3, 4, 4, 3, 0, 1},
649 { 0, 1, 3, 4, 3, 1, 0, -1},
650 { 2, 1, 6, 3, 3, 0, 0, 1},
651 { 0, 3, 4, 3, 6, 1, 5, -1},
652 { 6, 1, 2, 6, 4, 0, 0, 2},
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 {{ 6, 6, -1, -1, -1, -1, 4, 4},
657 { 4, 0, -1, -1, -1, 3, 6, -1},
658 { 0, 6, -1, -1, -1, -1, 4, 2},
659 { 7, -1, -1, -1, -1, -1, 7, -1},
660 { 4, 4, -1, -1, -1, -1, 5, 6},
661 { 6, 4, 7, 7, 5, 6, 4, -1},
662 {-1, 7, 6, 4, 6, 4, 7, -1},
663 {-1, 0, -1, 7, -1, 7, -1, -1},
664 {-1, -1, -1, -1, -1, -1, -1, -1},
665 {-1, -1, -1, -1, -1, -1, -1, -1}},
666 {{-1, 5, -1, -1, -1, -1, 4, -1},
667 {-1, 5, -1, -1, -1, 4, -1, -1},
668 {-1, -1, 5, 6, 6, 4, -1, -1},
669 {-1, -1, 2, -1, 2, -1, -1, -1},
670 { 0, 0, 6, -1, -1, 6, 1, 1},
671 {-1, -1, 2, -1, 2, -1, -1, -1},
672 {-1, -1, 7, 6, 6, 3, -1, -1},
673 {-1, 7, -1, -1, -1, 3, -1, -1},
674 {-1, 7, -1, -1, -1, -1, 3, -1},
675 {-1, -1, -1, -1, -1, -1, -1, -1}},
676 {{-1, 6, -1, -1, -1, -1, 2, -1},
677 { 1, 7, 1, 1, 1, 3, 1, -1},
678 {-1, -1, 4, 1, 1, 4, -1, -1},
679 {-1, 1, 3, 1, 7, 1, -1, -1},
680 {-1, -1, -1, 2, 6, -1, -1, -1},
681 {-1, -1, 1, 5, 1, -1, -1, -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 {{ 7, 7, 7, 7, 7, 7, 7, 7},
687 { 7, -1, -1, -1, -1, -1, 7, -1},
688 { 7, -1, -1, 2, 0, 5, 2, 2},
689 { 7, -1, -1, -1, 0, 3, 6, -1},
690 { 7, -1, -1, -1, -1, -1, 4, 0},
691 { 5, 5, -1, -1, -1, -1, -1, -1},
692 { 4, 3, 6, 2, -1, -1, -1, -1},
693 { 0, 2, 0, 4, -1, -1, -1, -1},
694 {-1, -1, -1, -1, -1, -1, -1, -1},
695 {-1, -1, -1, -1, -1, -1, -1, -1}},
696 {{-1, -1, 1, -1, -1, 1, -1, -1},
697 {-1, 4, -1, -1, 5, -1, -1, -1},
698 {-1, 7, -1, -1, 1, 1, 1, -1},
699 { 6, -1, -1, -1, -1, 7, -1, -1},
700 { 1, 1, 1, 1, -1, 4, -1, -1},
701 {-1, -1, 5, -1, -1, -1, -1, -1},
702 {-1, -1, 0, -1, -1, -1, -1, -1},
703 {-1, 3, -1, -1, -1, -1, -1, -1},
704 {-1, 1, -1, -1, -1, -1, -1, -1},
705 {-1, -1, -1, -1, -1, -1, -1, -1}},
706 {{-1, 7, 7, -1, -1, 7, 7, -1},
707 { 6, -1, 4, -1, 4, -1, 6, -1},
708 { 5, -1, -1, 3, 3, -1, -1, 5},
709 { 6, -1, -1, -1, -1, -1, 6, -1},
710 {-1, 7, -1, -1, -1, -1, 7, -1},
711 {-1, 4, -1, -1, -1, 4, -1, -1},
712 {-1, -1, 3, -1, -1, 3, -1, -1},
713 {-1, -1, 2, -1, 2, -1, -1, -1},
714 {-1, -1, -1, 5, 5, -1, -1, -1},
715 {-1, -1, -1, -1, -1, -1, -1, -1}},
716 {{-1, 0, 0, -1, -1, 0, 0, -1},
717 { 7, 4, 6, 6, 6, 4, 3, -1},
718 { 5, 6, 6, 6, 2, 6, 6, 3},
719 { 7, 4, 6, 6, 6, 4, 3, -1},
720 {-1, 0, 0, -1, -1, 0, 0, -1},
721 {-1, -1, -1, -1, -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 {{-1, -1, -1, -1, -1, 7, 7, 7},
727 {-1, -1, -1, -1, 2, 7, 7, -1},
728 {-1, 0, 7, 7, 7, -1, 7, 7},
729 { 6, 7, 7, 7, -1, -1, -1, -1},
730 { 6, -1, -1, -1, 7, 7, 7, 7},
731 { 6, -1, -1, -1, -1, -1, -1, -1},
732 { 4, 2, 2, 2, 4, -1, 3, -1},
733 { 4, 4, 4, 4, 3, 3, 3, -1},
734 {-1, -1, -1, -1, -1, -1, -1, -1},
735 {-1, -1, -1, -1, -1, -1, -1, -1}},
736 {{ 4, -1, -1, 7, -1, 6, -1, 7},
737 { 7, 6, 7, -1, -1, 7, 4, -1},
738 {-1, -1, 7, -1, -1, 7, -1, -1},
739 {-1, 0, 0, 0, 0, 0, 3, -1},
740 {-1, -1, 0, 2, 2, 0, 6, 4},
741 {-1, -1, 0, 0, 0, 1, 3, -1},
742 {-1, -1, -1, 0, 0, -1, 3, 4},
743 {-1, -1, -1, 6, -1, 5, 6, -1},
744 {-1, -1, -1, -1, -1, -1, 1, 0},
745 {-1, -1, -1, -1, -1, -1, -1, -1}},
746 {{-1, 5, -1, -1, -1, -1, 5, -1},
747 { 0, -1, -1, 0, -1, -1, 0, -1},
748 { 0, 0, 0, 2, 2, 0, 0, 0},
749 { 0, -1, -1, 0, -1, -1, 0, -1},
750 {-1, 7, -1, 3, -1, -1, 7, -1},
751 {-1, -1, 3, 6, -1, -1, -1, -1},
752 {-1, -1, -1, 6, -1, -1, -1, -1},
753 {-1, 3, 6, -1, -1, -1, -1, -1},
754 {-1, 3, -1, -1, -1, -1, -1, -1},
755 {-1, -1, -1, -1, -1, -1, -1, -1}},
756 {{-1, -1, -1, 6, 5, -1, -1, -1},
757 {-1, -1, 2, 6, 3, -1, -1, -1},
758 {-1, -1, 5, 4, 7, 1, -1, -1},
759 {-1, 6, 2, 2, 3, 4, -1, -1},
760 {-1, -1, 3, 7, 3, 6, -1, -1},
761 {-1, -1, 1, 3, 2, -1, -1, -1},
762 {-1, -1, -1, 4, 5, -1, -1, -1},
763 {-1, -1, -1, 4, -1, -1, -1, -1},
764 {-1, -1, -1, -1, -1, -1, -1, -1},
765 {-1, -1, -1, -1, -1, -1, -1, -1}},
766 {{ 7, 7, -1, 2, 2, -1, 6, 6},
767 { 6, -1, -1, 6, -1, -1, 3, -1},
768 { 2, -1, -1, 1, -1, -1, 2, -1},
769 { 5, -1, -1, 3, -1, -1, 2, -1},
770 { 1, -1, -1, 2, -1, -1, 1, -1},
771 { 5, -1, -1, 2, -1, -1, 2, -1},
772 { 6, -1, -1, 1, -1, -1, 7, -1},
773 { 5, -1, -1, 5, -1, -1, 4, -1},
774 {-1, -1, -1, -1, -1, -1, -1, -1},
775 {-1, -1, -1, -1, -1, -1, -1, -1}},
776 {{-1, -1, -1, 6, 6, -1, -1, -1},
777 {-1, 0, 4, 4, 4, 0, -1, -1},
778 {-1, -1, -1, 6, 6, -1, -1, -1},
779 {-1, -1, 2, 7, 2, -1, -1, -1},
780 {-1, -1, -1, 6, 6, -1, -1, -1},
781 {-1, 0, 5, 5, 5, 0, -1, -1},
782 {-1, -1, -1, 3, 3, -1, -1, -1},
783 {-1, -1, -1, -1, -1, -1, -1, -1},
784 {-1, -1, -1, -1, -1, -1, -1, -1},
785 {-1, -1, -1, -1, -1, -1, -1, -1}},
786 {{-1, -1, 4, 1, 3, -1, -1, -1},
787 {-1, 1, -1, -1, 1, -1, -1, -1},
788 {-1, -1, 4, 1, 3, 4, 1, -1},
789 {-1, 1, 3, 4, -1, -1, 4, -1},
790 {-1, 3, -1, -1, 3, 4, 1, -1},
791 {-1, 1, 3, 4, 1, 3, -1, -1},
792 {-1, -1, 4, 1, -1, -1, -1, -1},
793 {-1, -1, -1, -1, -1, -1, -1, -1},
794 {-1, -1, -1, -1, -1, -1, -1, -1},
795 {-1, -1, -1, -1, -1, -1, -1, -1}},
796 {{-1, 6, 4, -1, 3, 2, 5, -1},
797 { 0, -1, -1, -1, -1, -1, 1, -1},
798 {-1, 2, 3, 5, -1, 4, 6, -1},
799 { 0, -1, -1, -1, -1, -1, 1, -1},
800 {-1, 4, 6, -1, 2, 5, 3, -1},
801 { 0, -1, -1, -1, -1, -1, 1, -1},
802 {-1, 5, 2, 3, -1, 4, 6, -1},
803 {-1, -1, -1, -1, -1, -1, -1, -1},
804 {-1, -1, -1, -1, -1, -1, -1, -1},
805 {-1, -1, -1, -1, -1, -1, -1, -1}},
806 {{-1, -1, -1, 6, 6, -1, -1, -1},
807 {-1, -1, 7, 6, 4, -1, -1, -1},
808 {-1, 2, 1, 7, 4, 1, 3, -1},
809 { 2, 1, 1, 1, 1, 1, 3, -1},
810 {-1, 2, 2, 2, 3, 3, 3, -1},
811 {-1, -1, -1, 5, -1, -1, -1, -1},
812 {-1, -1, -1, 2, 3, -1, -1, -1},
813 {-1, -1, -1, 5, -1, -1, -1, -1},
814 {-1, -1, 2, 2, 3, 3, -1, -1},
815 {-1, -1, -1, -1, -1, -1, -1, -1}},
816 {{ 4, -1, 5, -1, -1, 3, -1, 6},
817 { 2, -1, 3, -1, 2, -1, 4, -1},
818 { 4, -1, -1, 1, 0, -1, -1, 6},
819 { 6, -1, 2, 3, 5, -1, 4, -1},
820 { 4, -1, -1, 0, 1, -1, -1, 6},
821 { 2, -1, 5, -1, 3, -1, 4, -1},
822 { 4, -1, 3, -1, -1, 2, -1, 6},
823 { 6, -1, -1, -1, -1, -1, 4, -1},
824 {-1, -1, -1, -1, -1, -1, -1, -1},
825 {-1, -1, -1, -1, -1, -1, -1, -1}},
826 {{ 2, 6, 0, 5, 5, 1, 3, 4},
827 { 1, -1, -1, 2, -1, -1, 0, -1},
828 { 4, -1, -1, 3, 6, -1, -1, 2},
829 {-1, -1, -1, 0, -1, -1, -1, -1},
830 {-1, -1, -1, 1, 4, -1, -1, -1},
831 {-1, -1, -1, 2, -1, -1, -1, -1},
832 {-1, -1, -1, 6, 3, -1, -1, -1},
833 {-1, -1, -1, 5, -1, -1, -1, -1},
834 {-1, -1, -1, 4, 1, -1, -1, -1},
835 {-1, -1, -1, -1, -1, -1, -1, -1}},
836 {{-1, -1, -1, -1, 5, 1, 1, 3},
837 { 0, 5, 1, 0, 5, 3, 3, -1},
838 { 5, 1, 0, 5, 1, 0, 5, 1},
839 { 0, 5, 1, 0, 5, 1, 6, -1},
840 {-1, -1, -1, -1, 1, 6, 5, 1},
841 {-1, -1, -1, -1, 5, 1, 6, -1},
842 {-1, -1, -1, -1, 1, 0, 5, 1},
843 {-1, -1, -1, -1, 5, 1, 0, -1},
844 {-1, -1, -1, -1, -1, -1, -1, -1},
845 {-1, -1, -1, -1, -1, -1, -1, -1}},
846 {{-1, 0, 7, 3, -1, -1, 2, 2},
847 {-1, 0, 7, 3, -1, -1, 2, -1},
848 {-1, 0, 7, 3, -1, -1, 2, 2},
849 {-1, 0, 7, 3, -1, 3, 1, -1},
850 {-1, 0, 7, 3, -1, 6, 4, 5},
851 {-1, 0, 7, 3, -1, 7, 0, -1},
852 {-1, 0, 7, 3, -1, 2, 3, 4},
853 {-1, 0, 7, 3, -1, 5, 6, -1},
854 {-1, -1, -1, -1, -1, 7, 0, 1},
855 {-1, -1, -1, -1, -1, -1, -1, -1}},
856 {{-1, -1, -1, 7, 7, 7, 7, -1},
857 { 3, 4, 5, -1, -1, -1, 7, -1},
858 { 2, -1, -1, -1, -1, -1, -1, 3},
859 { 7, -1, -1, -1, -1, -1, 4, -1},
860 { 7, -1, -1, -1, 3, 4, 5, 6},
861 { 7, -1, -1, 2, 0, 1, 2, -1},
862 { 6, -1, -1, -1, 3, 4, 5, 6},
863 { 0, 1, -1, -1, -1, -1, -1, -1},
864 { 2, 3, 4, -1, -1, -1, -1, -1},
865 { 5, 6, 0, -1, -1, -1, -1, -1}},
866 {{-1, 7, -1, -1, -1, -1, 2, -1},
867 { 1, 1, -1, -1, -1, 3, 3, -1},
868 {-1, 2, -1, -1, -1, -1, 4, -1},
869 { 3, 3, -1, -1, -1, 5, 5, -1},
870 {-1, 4, -1, -1, -1, -1, 6, -1},
871 { 5, 5, -1, -1, -1, 1, 1, -1},
872 {-1, 6, -1, -1, -1, -1, 7, -1},
873 {-1, -1, -1, -1, -1, -1, -1, -1},
874 {-1, -1, -1, -1, -1, -1, -1, -1},
875 {-1, -1, -1, -1, -1, -1, -1, -1}},
876 {{-1, 4, -1, -1, -1, -1, 4, -1},
877 { 2, -1, -1, 1, -1, -1, 2, -1},
878 { 5, -1, -1, 0, 0, -1, -1, 5},
879 { 5, -1, -1, 1, -1, -1, 6, -1},
880 {-1, 4, 2, 7, 7, 5, 4, -1},
881 {-1, -1, -1, 6, -1, -1, -1, -1},
882 {-1, -1, -1, 3, 3, -1, -1, -1},
883 {-1, -1, -1, 7, -1, -1, -1, -1},
884 {-1, -1, -1, -1, -1, -1, -1, -1},
885 {-1, -1, -1, -1, -1, -1, -1, -1}},
886 {{-1, 1, -1, -1, 2, 3, 4, -1},
887 { 2, -1, -1, 3, 0, 4, -1, -1},
888 { 4, -1, -1, 2, 3, 1, -1, -1},
889 { 3, -1, 4, 3, 0, -1, -1, -1},
890 { 4, -1, -1, 2, 5, 1, -1, -1},
891 { 3, -1, 4, 5, 0, 4, -1, -1},
892 {-1, -1, -1, -1, -1, -1, -1, -1},
893 {-1, -1, -1, -1, -1, -1, -1, -1},
894 {-1, -1, -1, -1, -1, -1, -1, -1},
895 {-1, -1, -1, -1, -1, -1, -1, -1}},
896 {{ 2, -1, -1, 1, 1, -1, -1, 2},
897 { 2, -1, 3, 3, 3, -1, 2, -1},
898 {-1, 2, -1, 4, 4, -1, 2, -1},
899 {-1, 7, 7, 0, 7, 7, -1, -1},
900 {-1, -1, -1, 4, 4, -1, -1, -1},
901 {-1, -1, 5, 7, 5, -1, -1, -1},
902 { 6, 3, 2, 6, 4, 2, 3, 6},
903 { 5, -1, -1, -1, -1, -1, 1, -1},
904 {-1, -1, -1, -1, -1, -1, -1, -1},
905 {-1, -1, -1, -1, -1, -1, -1, -1}},
906 {{ 4, 2, 3, 5, 7, 1, 3, 6},
907 { 1, -1, -1, 1, -1, -1, 1, -1},
908 { 3, 0, 1, 3, 2, 4, 3, 5},
909 { 4, -1, -1, 4, -1, -1, 4, -1},
910 {-1, 5, -1, -1, 5, -1, -1, 5},
911 { 0, 3, 2, 0, 4, 5, 0, -1},
912 {-1, 6, -1, -1, 6, -1, -1, 6},
913 { 7, -1, -1, 7, -1, -1, 7, -1},
914 {-1, -1, -1, -1, -1, -1, -1, -1},
915 {-1, -1, -1, -1, -1, -1, -1, -1}},
916 {{-1, 5, 4, -1, 1, 1, -1, -1},
917 { 5, -1, 4, 1, -1, 1, -1, -1},
918 { 0, -1, -1, -1, -1, -1, 0, -1},
919 { 0, 6, 4, -1, -1, 4, 2, -1},
920 {-1, 4, 3, 5, 2, 6, 3, 6},
921 {-1, 2, 6, -1, -1, 5, 4, -1},
922 {-1, -1, -1, -1, -1, -1, -1, -1},
923 {-1, -1, -1, -1, -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, 6, 6, -1, -1, -1},
927 {-1, -1, 5, 5, 4, -1, -1, -1},
928 {-1, -1, 1, 6, 6, 4, -1, -1},
929 {-1, 1, 7, 2, 5, 3, -1, -1},
930 {-1, 2, 7, 2, 1, 5, 3, -1},
931 { 2, 1, 3, 1, 4, 2, 7, -1},
932 {-1, 3, 1, 3, 4, 2, 7, -1},
933 {-1, 3, 5, 5, 6, 6, -1, -1},
934 {-1, -1, -1, -1, -1, -1, -1, -1},
935 {-1, -1, -1, -1, -1, -1, -1, -1}},
936 {{-1, -1, 7, 3, -1, -1, -1, -1},
937 {-1, 1, 7, 6, -1, -1, -1, -1},
938 {-1, 3, 7, 5, 1, 5, -1, -1},
939 { 7, 7, 0, 2, 4, 0, 4, -1},
940 { 7, 1, 4, 6, 5, 6, 5, 7},
941 { 1, 7, 7, 1, 7, 7, 1, -1},
942 {-1, -1, -1, -1, -1, -1, -1, -1},
943 {-1, -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 {{-1, -1, 1, -1, -1, 1, -1, -1},
947 {-1, 5, 6, 1, 5, 6, -1, -1},
948 {-1, 1, 1, 2, 2, 1, 1, -1},
949 { 4, 7, 1, 0, 1, 7, 4, -1},
950 {-1, 3, 7, 5, 7, 5, 3, -1},
951 {-1, 1, 1, 1, 1, 1, -1, -1},
952 {-1, -1, -1, -1, -1, -1, -1, -1},
953 {-1, -1, -1, -1, -1, -1, -1, -1},
954 {-1, -1, -1, -1, -1, -1, -1, -1},
955 {-1, -1, -1, -1, -1, -1, -1, -1}},
956 {{ 4, -1, -1, -1, 5, -1, -1, 4},
957 { 6, 6, 7, 6, -1, 4, 5, -1},
958 { 4, 2, 7, 5, 2, 2, 6, 4},
959 {-1, -1, 4, 1, -1, 5, 2, -1},
960 {-1, 5, 2, 7, 7, -1, 7, 4},
961 { 4, 6, 5, 4, -1, 4, 2, -1},
962 {-1, -1, -1, 4, -1, 4, 1, -1},
963 { 0, 0, 0, 5, -1, -1, -1, -1},
964 {-1, -1, -1, -1, 0, 0, 0, 0},
965 {-1, -1, -1, -1, -1, -1, -1, -1}},
966 {{ 1, -1, -1, -1, 0, 0, -1, -1},
967 { 2, -1, -1, 0, 1, 0, -1, -1},
968 { 3, -1, -1, 0, 2, 2, 0, -1},
969 { 4, -1, 0, 1, 1, 1, 0, -1},
970 { 5, -1, -1, 0, 4, 4, 0, -1},
971 { 6, -1, -1, 4, 4, 4, -1, -1},
972 { 7, -1, -1, -1, 4, 4, -1, -1},
973 {-1, -1, -1, 0, 1, 0, -1, -1},
974 {-1, -1, -1, 0, 1, 1, 0, -1},
975 {-1, -1, -1, -1, -1, -1, -1, -1}},
976 {{-1, -1, 3, -1, -1, 1, 7, -1},
977 {-1, 7, 4, -1, -1, 4, 3, -1},
978 { 1, -1, -1, 0, 2, 0, -1, -1},
979 { 5, 4, -1, 3, -1, -1, -1, -1},
980 { 4, -1, 3, 6, 1, 1, 6, -1},
981 {-1, 1, -1, -1, 4, -1, 1, -1},
982 {-1, 7, 5, -1, -1, -1, 3, -1},
983 {-1, -1, 3, -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 { 2, -1, -1, -1, 2, -1, -1, -1},
988 {-1, 3, -1, -1, 3, 3, -1, -1},
989 {-1, 4, -1, 4, -1, 4, -1, -1},
990 {-1, 5, -1, -1, 5, 5, -1, -1},
991 { 6, -1, -1, 7, 1, 7, -1, -1},
992 { 7, -1, -1, -1, 6, 6, -1, -1},
993 {-1, -1, -1, -1, -1, -1, -1, -1},
994 {-1, -1, -1, -1, -1, -1, -1, -1},
995 {-1, -1, -1, -1, -1, -1, -1, -1}},
996 {{ 2, -1, -1, 6, -1, 2, 5, 1},
997 { 5, -1, 4, -1, 4, -1, 4, -1},
998 { 6, -1, -1, 3, -1, -1, -1, 3},
999 { 4, 2, 0, -1, -1, -1, 5, -1},
1000 {-1, -1, -1, 6, -1, 3, 6, -1},
1001 {-1, -1, 5, -1, 5, -1, -1, -1},
1002 {-1, -1, -1, 3, -1, 4, 2, 5},
1003 {-1, -1, -1, -1, -1, -1, -1, -1},
1004 {-1, -1, -1, -1, -1, -1, -1, -1},
1005 {-1, -1, -1, -1, -1, -1, -1, -1}},
1006 {{ 6, -1, -1, -1, 4, -1, -1, 3},
1007 { 0, 3, -1, -1, 6, -1, 0, -1},
1008 {-1, -1, 7, -1, 1, -1, 3, -1},
1009 { 7, -1, 4, 7, -1, 2, -1, -1},
1010 { 5, 2, 3, 2, 1, 6, -1, 3},
1011 {-1, -1, 0, 4, 3, 5, 4, -1},
1012 {-1, 7, 6, -1, -1, 0, -1, -1},
1013 { 4, 3, -1, -1, -1, 4, 2, -1},
1014 { 0, -1, -1, -1, -1, -1, 6, -1},
1015 {-1, -1, -1, -1, -1, -1, -1, -1}},
1016 {{ 6, 1, 2, 5, 1, 6, 3, 0},
1017 {-1, -1, -1, -1, -1, -1, 4, -1},
1018 { 0, 5, 2, 7, 1, 6, 2, -1},
1019 { 3, -1, -1, -1, -1, -1, -1, -1},
1020 { 6, 7, 6, 4, 0, 5, 2, 6},
1021 {-1, -1, -1, -1, -1, -1, 1, -1},
1022 { 6, 1, 4, 0, 6, 2, 3, -1},
1023 { 0, -1, -1, -1, -1, -1, -1, -1},
1024 {-1, 0, 4, 5, 3, 7, 6, 0},
1025 {-1, -1, -1, -1, -1, -1, -1, -1}},
1026 {{-1, -1, -1, 0, 1, -1, -1, -1},
1027 {-1, -1, 0, 7, 0, -1, -1, -1},
1028 {-1, -1, 1, 2, 2, 0, -1, -1},
1029 {-1, 0, 7, 0, 7, 0, -1, -1},
1030 {-1, 6, -1, 7, 7, -1, 6, -1},
1031 { 4, 1, 6, 6, 6, 4, 1, -1},
1032 {-1, 5, -1, 7, 7, -1, 5, -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 {{-1, -1, -1, 5, 6, -1, -1, -1},
1037 {-1, -1, 3, 3, 3, -1, -1, -1},
1038 {-1, -1, 7, 5, 3, 7, -1, -1},
1039 {-1, 3, -1, 6, -1, 3, -1, -1},
1040 { 2, -1, -1, 3, 7, -1, -1, 1},
1041 { 2, 2, -1, 3, -1, 1, 1, -1},
1042 {-1, 0, 2, 5, 6, 1, 0, -1},
1043 {-1, -1, -1, 3, -1, -1, -1, -1},
1044 {-1, -1, -1, 3, 7, -1, -1, -1},
1045 {-1, -1, -1, -1, -1, -1, -1, -1}},
1046 {{-1, 6, -1, -1, -1, -1, 2, -1},
1047 {-1, 2, 6, 0, 6, 0, -1, -1},
1048 {-1, 0, -1, -1, -1, -1, -1, -1},
1049 { 6, -1, -1, -1, -1, -1, -1, -1},
1050 {-1, 3, 3, 2, 0, 6, 0, 0},
1051 {-1, 6, -1, -1, -1, -1, 0, -1},
1052 {-1, -1, -1, 6, 0, 2, 6, -1},
1053 {-1, 2, 0, -1, -1, -1, -1, -1},
1054 {-1, -1, -1, -1, -1, -1, -1, -1},
1055 {-1, -1, -1, -1, -1, -1, -1, -1}},
1056 {{ 0, 7, -1, -1, -1, -1, -1, -1},
1057 { 1, 5, -1, -1, -1, -1, -1, -1},
1058 { 7, 2, 5, -1, -1, -1, -1, -1},
1059 { 6, 3, 4, -1, -1, -1, -1, -1},
1060 { 5, 5, 4, 4, -1, -1, -1, -1},
1061 { 3, 3, 5, 3, -1, -1, -1, -1},
1062 { 1, 2, 2, 5, 3, -1, -1, -1},
1063 { 1, 0, 0, 7, 6, -1, -1, -1},
1064 { 3, 3, 5, 5, 7, 6, -1, -1},
1065 {-1, -1, -1, -1, -1, -1, -1, -1}},
1066 {{-1, -1, 2, 6, 6, 2, -1, -1},
1067 {-1, 2, 1, 1, 0, 2, -1, -1},
1068 {-1, 2, 3, 2, 2, 0, 2, -1},
1069 { 2, 3, 2, 5, 2, 7, 2, -1},
1070 { 2, 4, 2, 5, 2, 7, 2, 0},
1071 { 2, 4, 2, 6, 6, 2, 0, -1},
1072 {-1, 2, 5, 2, 2, 2, 7, 2},
1073 {-1, 2, 5, 6, 6, 7, 2, -1},
1074 {-1, -1, 2, 2, 2, 2, 2, -1},
1075 {-1, -1, -1, -1, -1, -1, -1, -1}},
1076 {{-1, -1, 0, -1, -1, 0, -1, -1},
1077 { 1, 0, 0, 1, 0, 0, 1, -1},
1078 { 1, 7, 7, 5, 5, 7, 7, 1},
1079 { 3, 2, -1, 2, -1, 2, 3, -1},
1080 { 3, 7, -1, 6, 6, -1, 7, 3},
1081 { 7, -1, -1, 6, -1, -1, 7, -1},
1082 { 4, 4, 5, -1, -1, 5, 4, 4},
1083 {-1, -1, -1, -1, -1, -1, -1, -1},
1084 {-1, -1, -1, -1, -1, -1, -1, -1},
1085 {-1, -1, -1, -1, -1, -1, -1, -1}},
1086 {{-1, 6, 3, -1, -1, 3, 6, -1},
1087 { 6, -1, 2, -1, 2, -1, 6, -1},
1088 { 2, -1, 0, 1, 1, 0, -1, 2},
1089 { 5, 0, -1, 7, -1, 0, 5, -1},
1090 {-1, 5, -1, 6, 6, -1, 5, -1},
1091 { 7, 1, 4, -1, 4, 1, 7, -1},
1092 { 7, -1, 4, -1, -1, 4, -1, 7},
1093 { 2, 0, -1, -1, -1, 0, 2, -1},
1094 {-1, 2, -1, -1, -1, -1, 2, -1},
1095 {-1, -1, -1, -1, -1, -1, -1, -1}},
1096 {{ 6, 1, -1, -1, -1, -1, 4, 0},
1097 { 2, 7, 5, 5, 5, 7, 3, -1},
1098 { 6, 1, -1, -1, -1, -1, 4, 0},
1099 { 2, 5, 7, 7, 7, 5, 3, -1},
1100 { 6, 1, -1, -1, -1, -1, 4, 0},
1101 { 2, 0, 6, 6, 6, 0, 3, -1},
1102 { 6, 1, -1, -1, -1, -1, 4, 0},
1103 {-1, -1, -1, -1, -1, -1, -1, -1},
1104 {-1, -1, -1, -1, -1, -1, -1, -1},
1105 {-1, -1, -1, -1, -1, -1, -1, -1}},
1106 {{ 5, -1, -1, 1, 1, -1, -1, 5},
1107 { 5, -1, 4, -1, 4, -1, 5, -1},
1108 {-1, 2, 4, -1, -1, 4, 2, -1},
1109 { 7, 2, -1, -1, -1, 2, 7, -1},
1110 { 0, -1, 0, 4, 4, 0, -1, 0},
1111 { 7, 2, -1, -1, -1, 2, 7, -1},
1112 {-1, 2, 3, -1, -1, 3, 2, -1},
1113 { 5, -1, 3, -1, 3, -1, 5, -1},
1114 { 5, -1, -1, 6, 6, -1, -1, 5},
1115 {-1, -1, -1, -1, -1, -1, -1, -1}},
1116 {{ 2, 2, -1, -1, -1, -1, 5, 5},
1117 { 5, -1, -1, -1, -1, -1, 2, -1},
1118 { 5, -1, -1, -1, -1, -1, -1, 2},
1119 { 1, -1, 1, 5, 1, -1, 3, -1},
1120 { 5, 2, 5, 3, 1, 2, 5, 2},
1121 { 2, 0, 5, -1, 2, 0, 5, -1},
1122 {-1, 3, 7, -1, -1, 3, 7, -1},
1123 {-1, -1, 2, 0, 5, -1, -1, -1},
1124 {-1, -1, -1, -1, -1, -1, -1, -1},
1125 {-1, -1, -1, -1, -1, -1, -1, -1}},
1126 {{ 0, 6, 5, 2, 3, 4, 1, 7},
1127 {-1, -1, -1, -1, 1, -1, -1, -1},
1128 {-1, -1, -1, 1, 1, -1, -1, -1},
1129 {-1, -1, 1, -1, -1, -1, -1, -1},
1130 { 7, 1, 4, 3, 2, 5, 6, 0},
1131 {-1, -1, -1, -1, 1, -1, -1, -1},
1132 {-1, -1, -1, 1, 1, -1, -1, -1},
1133 {-1, -1, 1, -1, -1, -1, -1, -1},
1134 { 0, 6, 5, 2, 3, 4, 1, 7},
1135 {-1, -1, -1, -1, -1, -1, -1, -1}},
1136 {{-1, -1, 1, -1, -1, 1, -1, -1},
1137 {-1, 2, 4, -1, 2, 4, -1, -1},
1138 {-1, 2, 3, 6, 5, 3, 2, -1},
1139 {-1, 6, 5, -1, 6, 5, -1, -1},
1140 {-1, -1, -1, 7, 7, -1, -1, -1},
1141 {-1, -1, -1, 7, -1, -1, -1, -1},
1142 { 1, -1, -1, 7, 7, -1, -1, 3},
1143 { 2, -1, -1, 7, -1, -1, 2, -1},
1144 {-1, 3, 4, 5, 6, 4, 1, -1},
1145 {-1, -1, -1, -1, -1, -1, -1, -1}},
1146 {{ 1, -1, -1, 2, 2, -1, -1, 2},
1147 { 1, 3, 7, 3, 7, 4, 2, -1},
1148 {-1, 1, 6, -1, -1, 6, 2, -1},
1149 { 6, -1, 7, 3, 7, -1, 6, -1},
1150 {-1, 4, 2, -1, -1, 1, 3, -1},
1151 {-1, -1, 2, 6, 1, -1, -1, -1},
1152 {-1, 4, 3, 3, 4, 4, 3, -1},
1153 {-1, -1, -1, -1, -1, -1, -1, -1},
1154 {-1, -1, -1, -1, -1, -1, -1, -1},
1155 {-1, -1, -1, -1, -1, -1, -1, -1}},
1156 {{-1, -1, -1, 5, 6, -1, -1, -1},
1157 {-1, -1, -1, 3, -1, -1, -1, -1},
1158 {-1, -1, -1, 1, 2, -1, -1, -1},
1159 {-1, -1, -1, 4, -1, -1, -1, -1},
1160 {-1, -1, -1, 5, 7, -1, -1, -1},
1161 {-1, -1, -1, 2, -1, -1, -1, -1},
1162 { 6, 5, 4, 3, 2, 1, 7, 5},
1163 {-1, -1, -1, -1, -1, -1, -1, -1},
1164 {-1, -1, -1, -1, -1, -1, -1, -1},
1165 {-1, -1, -1, -1, -1, -1, -1, -1}},
1166 {{-1, 0, -1, 1, -1, 2, -1, -1},
1167 {-1, 4, -1, 5, -1, 6, -1, -1},
1168 {-1, 7, -1, 0, -1, 2, -1, -1},
1169 {-1, 6, -1, 3, -1, 6, -1, -1},
1170 {-1, 1, -1, 1, -1, 2, -1, -1},
1171 {-1, 3, -1, 5, -1, 0, -1, -1},
1172 {-1, 2, -1, 4, -1, 6, -1, -1},
1173 {-1, 3, -1, 6, -1, 7, -1, -1},
1174 {-1, -1, -1, -1, -1, -1, -1, -1},
1175 {-1, -1, -1, -1, -1, -1, -1, -1}},
1176 {{ 1, 1, 2, 2, 3, 3, 4, 4},
1177 { 5, 5, 6, 7, 6, 5, 5, -1},
1178 { 6, 4, 3, 3, 2, 2, 1, 6},
1179 { 4, 6, 5, 7, 6, 3, 1, -1},
1180 {-1, -1, -1, -1, -1, -1, -1, -1},
1181 {-1, -1, -1, -1, -1, -1, -1, -1},
1182 {-1, -1, -1, -1, -1, -1, -1, -1},
1183 {-1, -1, -1, -1, -1, -1, -1, -1},
1184 {-1, -1, -1, -1, -1, -1, -1, -1},
1185 {-1, -1, -1, -1, -1, -1, -1, -1}},
1186 {{ 7, 4, -1, 1, 2, -1, 4, 7},
1187 { 5, 5, -1, 2, -1, 4, 4, -1},
1188 {-1, 5, -1, 7, 7, -1, 4, -1},
1189 { 1, 0, 6, 7, 6, 0, 2, -1},
1190 {-1, 2, -1, 5, 3, -1, 1, -1},
1191 { 1, 1, -1, -1, -1, 2, 2, -1},
1192 { 6, 1, 4, -1, -1, 4, 2, 6},
1193 { 5, 3, -1, -1, -1, 3, 5, -1},
1194 {-1, -1, -1, -1, -1, -1, -1, -1},
1195 {-1, -1, -1, -1, -1, -1, -1, -1}},
1196 {{ 1, 5, 1, 0, 0, 1, 5, 1},
1197 { 1, 2, 5, -1, 5, 2, 1, -1},
1198 { 3, 6, 1, 2, 2, 1, 6, 3},
1199 { 4, 3, 4, -1, 4, 3, 4, -1},
1200 { 3, 4, 6, 5, 5, 6, 4, 3},
1201 { 0, 2, 3, -1, 3, 2, 0, -1},
1202 { 2, 3, 1, 5, 5, 1, 3, 2},
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 {{ 3, 0, 2, 7, 5, 7, 6, 5},
1207 { 6, -1, 1, -1, 2, -1, 1, -1},
1208 {-1, 6, 4, 0, 3, 4, 5, -1},
1209 {-1, 5, -1, 1, -1, 4, -1, -1},
1210 {-1, 7, 3, 5, 6, 5, 3, -1},
1211 { 1, -1, 2, -1, 4, -1, 2, -1},
1212 { 6, 4, 4, 6, 6, 5, 5, 1},
1213 {-1, -1, -1, -1, -1, -1, -1, -1},
1214 {-1, -1, -1, -1, -1, -1, -1, -1},
1215 {-1, -1, -1, -1, -1, -1, -1, -1}}
1218 /* the tile struct
1219 * type is the bubble number 0-7
1220 * fallx is the x axis movement for the falling bubble
1221 * fallvel is the initial upward velocity for the falling bubble
1222 * ingroup denotes a bubble that is part of a group to be removed
1223 * anchored denotes a bubble that is anchored to the ceiling
1225 struct tile {
1226 int type;
1227 int fallx;
1228 int fallvel;
1229 bool ingroup;
1230 bool anchored;
1231 bool delete;
1234 /* the game context struct
1235 * score is the current score
1236 * level is the current level
1237 * angle is the current cannon direction
1238 * shots is the number of shots fired since last compression
1239 * compress is the height of the compressor
1240 * onboardcnt is the number of unique bubbles on the playing board
1241 * onboard is the unique bubbles on the playing board
1242 * nextinq is the pointer to the next bubble in the firing queue
1243 * queue is the circular buffer of bubbles to be fired
1244 * elapsedlvl is level elapsed time in 1/100s of seconds
1245 * elapsedshot is the shot elapsed time in 1/100s of seconds
1246 * startedshot is when the current shot began
1247 * playboard is the game playing board
1249 struct game_context {
1250 unsigned int score;
1251 unsigned int level;
1252 int angle;
1253 int shots;
1254 int compress;
1255 int onboardcnt;
1256 int onboard[NUM_BUBBLES];
1257 int nextinq;
1258 int queue[NUM_QUEUE];
1259 long elapsedlvl;
1260 long elapsedshot;
1261 long startedshot;
1262 struct tile playboard[BB_HEIGHT][BB_WIDTH];
1265 static struct highscore highscores[NUM_SCORES];
1267 /* used to denote available resume info */
1268 static bool resume = false;
1269 static bool resume_file = false;
1270 static unsigned int highlevel = 0; /* the highest level beaten */
1271 static unsigned int last_highlevel = 0;
1273 static void bubbles_init(struct game_context* bb);
1274 static bool bubbles_nextlevel(struct game_context* bb);
1275 static void bubbles_getonboard(struct game_context* bb);
1276 static void bubbles_drawboard(struct game_context* bb);
1277 static int bubbles_fire(struct game_context* bb);
1278 static bool bubbles_collision(struct game_context* bb, int y, int x,
1279 int nearrow, int nearcol);
1280 static bool bubbles_ingroup(struct game_context* bb, int row, int col);
1281 static int bubbles_searchgroup(struct game_context* bb, int row, int col);
1282 static int bubbles_remove(struct game_context* bb);
1283 static void bubbles_anchored(struct game_context* bb, int row, int col);
1284 static int bubbles_fall(struct game_context* bb);
1285 static int bubbles_checklevel(struct game_context* bb);
1286 static void bubbles_recordscore(struct game_context* bb);
1287 static bool bubbles_loadgame(struct game_context* bb);
1288 static void bubbles_savegame(struct game_context* bb);
1289 static inline void bubbles_setcolors(void);
1290 static void bubbles_callback(void* param);
1291 static int bubbles_handlebuttons(struct game_context* bb, bool animblock,
1292 int timeout);
1293 static int bubbles(struct game_context* bb);
1295 /*****************************************************************************
1296 * bubbles_init() initializes bubbles data structures.
1297 ******************************************************************************/
1298 static void bubbles_init(struct game_context* bb) {
1299 bubbles_setcolors();
1300 /* seed the rand generator */
1301 rb->srand(*rb->current_tick);
1303 /* check for resumed game */
1304 if (resume)
1306 resume = false;
1307 return;
1310 bb->score = 0;
1311 bubbles_nextlevel(bb);
1314 /*****************************************************************************
1315 * bubbles_nextlevel() sets up the game for the next level, returns false if
1316 * there are no more levels.
1317 ******************************************************************************/
1318 static bool bubbles_nextlevel(struct game_context* bb) {
1319 int i, j, pos;
1321 bb->level++;
1323 /* check if there are no more levels */
1324 if(bb->level > NUM_LEVELS) return false;
1326 /* save highest level */
1327 if (bb->level-1 > highlevel)
1328 highlevel = bb->level-1;
1330 /* set up the play board */
1331 rb->memset(bb->playboard, 0, sizeof(bb->playboard));
1332 for(i=0; i<BB_LEVEL_HEIGHT; i++) {
1333 for(j=0; j<BB_WIDTH; j++) {
1334 pos = (int)level[bb->level-1][i][j];
1335 if(pos >=0 && pos < NUM_BUBBLES) {
1336 bb->playboard[i][j].type = pos;
1337 } else {
1338 bb->playboard[i][j].type = -1;
1342 for(i=BB_LEVEL_HEIGHT; i<BB_HEIGHT; i++) {
1343 for(j=0; j<BB_WIDTH; j++) {
1344 bb->playboard[i][j].type = -1;
1348 /* fill first bubbles in shot queue */
1349 bubbles_getonboard(bb);
1350 for(i=0; i<NUM_QUEUE; i++) {
1351 bb->queue[i] = bb->onboard[rb->rand()%bb->onboardcnt];
1354 bb->angle = 0;
1355 bb->shots = 0;
1356 bb->compress = 0;
1357 bb->nextinq = 0;
1358 bb->elapsedlvl = 0;
1359 bb->elapsedshot = 0;
1361 return true;
1364 /*****************************************************************************
1365 * bubbles_getonboard() determines which bubble types are on the play board.
1366 ******************************************************************************/
1367 static void bubbles_getonboard(struct game_context* bb) {
1368 int i, j, k;
1369 bool found;
1371 bb->onboardcnt = 0;
1372 rb->memset(bb->onboard, -1, sizeof(bb->onboard));
1374 for(i=0; i<BB_HEIGHT; i++) {
1375 for(j=0; j<BB_WIDTH; j++) {
1376 if(bb->playboard[i][j].type >= 0) {
1377 found = false;
1379 for(k=0; k<bb->onboardcnt; k++) {
1380 if(bb->playboard[i][j].type == bb->onboard[k]) {
1381 found = true;
1382 break;
1386 if(!found) {
1387 bb->onboard[bb->onboardcnt] = bb->playboard[i][j].type;
1388 bb->onboardcnt++;
1391 if(bb->onboardcnt == NUM_BUBBLES) return;
1397 /*****************************************************************************
1398 * bubbles_drawboard() draws the game board to the buffer but does not update
1399 * the lcd.
1400 ******************************************************************************/
1401 static void bubbles_drawboard(struct game_context* bb) {
1402 int i, j;
1403 int w1, w2, h;
1404 int colmax, indent;
1405 int tipx, tipy;
1406 bool evenline = false;
1407 char *level = "Level";
1408 char *score = "Score";
1409 char *next = "Next";
1410 char *hurry = "HURRY!";
1411 char str[11];
1413 /* clear screen */
1414 rb->lcd_clear_display();
1415 int font = rb->screens[SCREEN_MAIN]->getfont();
1416 h = rb->font_get(font)->height + 1;
1417 /* draw background */
1418 #ifdef HAVE_LCD_COLOR
1419 rb->lcd_bitmap(bubbles_background, 0, 0, LCD_WIDTH, LCD_HEIGHT);
1420 #endif
1422 /* display play board */
1423 for(i=0; i<BB_HEIGHT; i++) {
1424 colmax = BB_WIDTH;
1425 if(evenline) {
1426 colmax--;
1427 indent = ROW_INDENT;
1428 } else {
1429 indent = 0;
1431 evenline = !evenline;
1433 for(j=0; j<colmax; j++) {
1434 if(bb->playboard[i][j].type >= 0 && !bb->playboard[i][j].delete) {
1435 rb->lcd_bitmap_part(bubbles_emblem,
1436 0, EMBLEM_HEIGHT*bb->playboard[i][j].type,
1437 STRIDE( SCREEN_MAIN,
1438 BMPWIDTH_bubbles_emblem, BMPHEIGHT_bubbles_emblem),
1439 XOFS+indent+BUBBLE_WIDTH*j+(BUBBLE_WIDTH-EMBLEM_WIDTH)/2,
1440 YOFS+ROW_HEIGHT*i+(BUBBLE_HEIGHT-EMBLEM_HEIGHT)/2+bb->compress*ROW_HEIGHT,
1441 EMBLEM_WIDTH, EMBLEM_HEIGHT);
1442 rb->lcd_set_drawmode(DRMODE_FG);
1443 rb->lcd_mono_bitmap((const unsigned char *)bubbles_bubble,
1444 XOFS+indent+BUBBLE_WIDTH*j,
1445 YOFS+ROW_HEIGHT*i+bb->compress*ROW_HEIGHT,
1446 BUBBLE_WIDTH, BUBBLE_HEIGHT);
1447 rb->lcd_set_drawmode(DRMODE_SOLID);
1452 /* display bubble to be shot */
1453 rb->lcd_bitmap_part(bubbles_emblem,
1454 0, EMBLEM_HEIGHT*bb->queue[bb->nextinq],
1455 STRIDE( SCREEN_MAIN,
1456 BMPWIDTH_bubbles_emblem, BMPHEIGHT_bubbles_emblem),
1457 SHOTX+(BUBBLE_WIDTH-EMBLEM_WIDTH)/2,
1458 SHOTY+(BUBBLE_HEIGHT-EMBLEM_HEIGHT)/2,
1459 EMBLEM_WIDTH, EMBLEM_HEIGHT);
1460 rb->lcd_set_drawmode(DRMODE_FG);
1461 rb->lcd_mono_bitmap((const unsigned char *)bubbles_bubble,
1462 SHOTX, SHOTY,
1463 BUBBLE_WIDTH, BUBBLE_HEIGHT);
1464 rb->lcd_set_drawmode(DRMODE_SOLID);
1466 /* display next bubble to be shot */
1467 #ifndef NEXT_BB_X
1468 rb->lcd_bitmap_part(bubbles_emblem,
1469 0, EMBLEM_HEIGHT*bb->queue[(bb->nextinq+1)%NUM_QUEUE],
1470 STRIDE( SCREEN_MAIN,
1471 BMPWIDTH_bubbles_emblem, BMPHEIGHT_bubbles_emblem),
1472 XOFS/2-BUBBLE_WIDTH/2+(BUBBLE_WIDTH-EMBLEM_WIDTH)/2,
1473 SHOTY+(BUBBLE_HEIGHT-EMBLEM_HEIGHT)/2,
1474 EMBLEM_WIDTH, EMBLEM_HEIGHT);
1475 rb->lcd_set_drawmode(DRMODE_FG);
1476 rb->lcd_mono_bitmap((const unsigned char *)bubbles_bubble,
1477 XOFS/2-BUBBLE_WIDTH/2, SHOTY,
1478 BUBBLE_WIDTH, BUBBLE_HEIGHT);
1479 rb->lcd_set_drawmode(DRMODE_SOLID);
1480 #else
1481 rb->lcd_bitmap_part(bubbles_emblem,
1482 0, EMBLEM_HEIGHT*bb->queue[(bb->nextinq+1)%NUM_QUEUE],
1483 STRIDE( SCREEN_MAIN,
1484 BMPWIDTH_bubbles_emblem, BMPHEIGHT_bubbles_emblem),
1485 NEXT_BB_X + NEXT_BB_WIDTH/2-BUBBLE_WIDTH/2+(BUBBLE_WIDTH-EMBLEM_WIDTH)/2,
1486 NEXT_BB_Y + (BUBBLE_HEIGHT-EMBLEM_HEIGHT)/2 + h,
1487 EMBLEM_WIDTH, EMBLEM_HEIGHT);
1488 rb->lcd_set_drawmode(DRMODE_FG);
1489 rb->lcd_mono_bitmap((const unsigned char *)bubbles_bubble,
1490 NEXT_BB_X + NEXT_BB_WIDTH/2-BUBBLE_WIDTH/2, NEXT_BB_Y + h,
1491 BUBBLE_WIDTH, BUBBLE_HEIGHT);
1492 rb->lcd_set_drawmode(DRMODE_SOLID);
1493 #endif
1495 /* draw bounding lines */
1496 #ifndef HAVE_LCD_COLOR
1497 rb->lcd_vline(XOFS-1, 0, LCD_HEIGHT);
1498 rb->lcd_vline(XOFS+BUBBLE_WIDTH*BB_WIDTH, 0, LCD_HEIGHT);
1499 #endif
1500 rb->lcd_hline(XOFS, XOFS+BUBBLE_WIDTH*BB_WIDTH-1, YOFS+bb->compress*ROW_HEIGHT-1);
1501 rb->lcd_hline(XOFS, XOFS+BUBBLE_WIDTH*BB_WIDTH-1,
1502 YOFS+ROW_HEIGHT*(BB_HEIGHT-2)+BUBBLE_HEIGHT);
1504 /* draw arrow */
1505 tipx = SHOTX+BUBBLE_WIDTH/2+(((fp14_sin(bb->angle)>>4)*BUBBLE_WIDTH*3/2)>>10);
1506 tipy = SHOTY+BUBBLE_HEIGHT/2-(((fp14_cos(bb->angle)>>4)*BUBBLE_HEIGHT*3/2)>>10);
1508 rb->lcd_drawline(SHOTX+BUBBLE_WIDTH/2+(((fp14_sin(bb->angle)>>4)*BUBBLE_WIDTH/2)>>10),
1509 SHOTY+BUBBLE_HEIGHT/2-(((fp14_cos(bb->angle)>>4)*BUBBLE_HEIGHT/2)>>10),
1510 tipx, tipy);
1511 xlcd_filltriangle(tipx, tipy,
1512 tipx+(((fp14_sin(bb->angle-135)>>4)*BUBBLE_WIDTH/3)>>10),
1513 tipy-(((fp14_cos(bb->angle-135)>>4)*BUBBLE_HEIGHT/3)>>10),
1514 tipx+(((fp14_sin(bb->angle+135)>>4)*BUBBLE_WIDTH/3)>>10),
1515 tipy-(((fp14_cos(bb->angle+135)>>4)*BUBBLE_HEIGHT/3)>>10));
1517 /* draw text */
1518 rb->snprintf(str, 4, "%d", bb->level);
1519 rb->lcd_getstringsize(level, &w1, NULL);
1520 rb->lcd_getstringsize(str, &w2, NULL);
1521 #ifndef LEVEL_TXT_X
1522 rb->lcd_putsxy(XOFS/2-w1/2, 2, level);
1523 rb->lcd_putsxy(XOFS/2-w2/2, 2+h, str);
1524 #else
1525 rb->lcd_putsxy(LEVEL_TXT_X+(LEVEL_TXT_WIDTH/2-w1/2), LEVEL_TXT_Y, level);
1526 rb->lcd_putsxy(LEVEL_TXT_X+(LEVEL_TXT_WIDTH/2-w2/2), LEVEL_TXT_Y+h, str);
1527 #endif
1529 rb->snprintf(str, 10, "%d", bb->score);
1530 rb->lcd_getstringsize(score, &w1,NULL);
1531 rb->lcd_getstringsize(str, &w2, NULL);
1532 #ifndef SCORE_TXT_X
1533 rb->lcd_putsxy(XOFS/2-w1/2, 29, score);
1534 rb->lcd_putsxy(XOFS/2-w2/2, 29+h, str);
1535 #else
1536 rb->lcd_putsxy(SCORE_TXT_X+(SCORE_TXT_WIDTH/2-w1/2), SCORE_TXT_Y, score);
1537 rb->lcd_putsxy(SCORE_TXT_X+(SCORE_TXT_WIDTH/2-w2/2), SCORE_TXT_Y+h, str);
1538 #endif
1540 rb->lcd_getstringsize(next, &w1, NULL);
1541 #ifndef NEXT_BB_X
1542 rb->lcd_putsxy(XOFS/2-w1/2, SHOTY-h, next);
1543 #else
1544 rb->lcd_putsxy(NEXT_BB_X+(NEXT_BB_WIDTH/2-w1/2), NEXT_BB_Y, next);
1545 #endif
1548 if(bb->elapsedshot >= (MAX_SHOTTIME*7)/10) {
1549 rb->lcd_getstringsize(hurry, &w1, &h);
1550 rb->lcd_putsxy(LCD_WIDTH/2-w1/2, LCD_HEIGHT/2-h/2, hurry);
1554 /*****************************************************************************
1555 * bubbles_fire() fires the current bubble, reloads the cannon, attaches
1556 * bubble to playboard, removes appropriate bubbles, and advances the
1557 * the compressor.
1558 ******************************************************************************/
1559 static int bubbles_fire(struct game_context* bb) {
1560 int bubblecur;
1561 long shotxinc, shotyinc;
1562 long shotxofs, shotyofs;
1563 int shotxdirec = 1;
1564 long tempxofs, tempyofs;
1565 int nearrow, nearcol;
1566 int lastrow = BB_HEIGHT-1;
1567 int lastcol = (BB_WIDTH-1)/2;
1568 int buttonres;
1569 long lasttick, currenttick;
1571 /* get current bubble */
1572 bubblecur = bb->queue[bb->nextinq];
1573 shotxinc = ((fp14_sin(bb->angle)>>4)*BUBBLE_WIDTH)/3;
1574 shotyinc = ((-1*(fp14_cos(bb->angle)>>4))*BUBBLE_HEIGHT)/3;
1575 shotxofs = shotyofs = 0;
1577 /* advance the queue */
1578 bb->queue[bb->nextinq] = bb->onboard[rb->rand()%bb->onboardcnt];
1579 bb->nextinq = (bb->nextinq+1)%NUM_QUEUE;
1580 bubbles_drawboard(bb);
1581 rb->lcd_update_rect(0, 0, XOFS, LCD_HEIGHT);
1583 /* move the bubble across the play board */
1584 lasttick = *rb->current_tick;
1586 while(true) {
1587 /* move the bubble one step */
1588 shotyofs += shotyinc;
1589 shotxofs += shotxinc*shotxdirec;
1591 /* check for bounce off sides */
1592 if(SHOTX+(shotxofs>>10) < XOFS) {
1593 shotxofs += 2*((XOFS<<10)-(((SHOTX)<<10)+shotxofs));
1594 shotxdirec *= -1;
1595 } else if(SHOTX+(shotxofs>>10) > XOFS+(BB_WIDTH-1)*BUBBLE_WIDTH) {
1596 shotxofs -= 2*((((SHOTX)<<10)+shotxofs)-
1597 ((XOFS<<10)+(((BB_WIDTH-1)*BUBBLE_WIDTH)<<10)));
1598 shotxdirec *= -1;
1601 tempxofs = shotxofs>>10;
1602 tempyofs = shotyofs>>10;
1604 /* display shot */
1605 bubbles_drawboard(bb);
1606 rb->lcd_bitmap_part(bubbles_emblem, 0, EMBLEM_HEIGHT*bubblecur,
1607 STRIDE( SCREEN_MAIN,
1608 BMPWIDTH_bubbles_emblem,
1609 BMPHEIGHT_bubbles_emblem),
1610 SHOTX+tempxofs+(BUBBLE_WIDTH-EMBLEM_WIDTH)/2,
1611 SHOTY+tempyofs+(BUBBLE_HEIGHT-EMBLEM_HEIGHT)/2,
1612 EMBLEM_WIDTH, EMBLEM_HEIGHT);
1613 rb->lcd_set_drawmode(DRMODE_FG);
1614 rb->lcd_mono_bitmap((const unsigned char *)bubbles_bubble,
1615 SHOTX+tempxofs, SHOTY+tempyofs,
1616 BUBBLE_WIDTH, BUBBLE_HEIGHT);
1617 rb->lcd_set_drawmode(DRMODE_SOLID);
1618 rb->lcd_update_rect(XOFS, 0, BB_WIDTH*BUBBLE_WIDTH, LCD_HEIGHT);
1620 /* find nearest position */
1621 nearrow = ((SHOTY+tempyofs)-
1622 (YOFS+bb->compress*ROW_HEIGHT)+
1623 (ROW_HEIGHT/2))/ROW_HEIGHT;
1624 if(nearrow >= BB_HEIGHT) nearrow = BB_HEIGHT-1;
1626 if(nearrow%2) { /* odd row */
1627 nearcol = ((SHOTX+tempxofs)-
1628 (XOFS+ROW_INDENT)+
1629 (BUBBLE_WIDTH/2))/BUBBLE_WIDTH;
1630 if(nearcol >= BB_WIDTH-1) nearcol = BB_WIDTH-2;
1631 } else { /* even row */
1632 nearcol = ((SHOTX+tempxofs)-XOFS+(BUBBLE_WIDTH/2))/BUBBLE_WIDTH;
1633 if(nearcol >= BB_WIDTH) nearcol = BB_WIDTH-1;
1635 if(nearcol < 0) nearcol = 0;
1637 /* if nearest position is occupied attach to last position */
1638 if(bb->playboard[nearrow][nearcol].type >= 0) {
1639 bb->playboard[lastrow][lastcol].type = bubblecur;
1640 break;
1643 /* save last position */
1644 lastrow = nearrow;
1645 lastcol = nearcol;
1647 /* if collision with neighbor then attach shot */
1648 if(bubbles_collision(bb, YOFS+SHOTY+tempyofs, SHOTX+tempxofs,
1649 nearrow, nearcol)) {
1650 bb->playboard[nearrow][nearcol].type = bubblecur;
1651 break;
1654 /* if at top then attach shot to the ceiling */
1655 if(nearrow == 0 && SHOTY+tempyofs <= YOFS+bb->compress*ROW_HEIGHT) {
1656 bb->playboard[nearrow][nearcol].type = bubblecur;
1657 break;
1660 /* handle button events */
1661 buttonres = bubbles_handlebuttons(bb, true, 0);
1662 if(buttonres != BB_NONE) return buttonres;
1664 /* framerate limiting */
1665 currenttick = *rb->current_tick;
1666 if(currenttick-lasttick < HZ/MAX_FPS) {
1667 rb->sleep((HZ/MAX_FPS)-(currenttick-lasttick));
1668 } else {
1669 rb->yield();
1671 lasttick = currenttick;
1674 bubbles_drawboard(bb);
1675 rb->lcd_update();
1677 /* clear appropriate bubbles from playing board */
1678 if(bubbles_ingroup(bb, lastrow, lastcol)) {
1679 buttonres = bubbles_remove(bb);
1680 if(buttonres != BB_NONE) return buttonres;
1683 /* update shots and compress amount */
1684 bb->shots++;
1685 if(bb->shots >= NUM_COMPRESS) {
1686 bb->shots = 0;
1687 bb->compress++;
1690 return BB_NONE;
1693 /*****************************************************************************
1694 * bubbles_collision() determines if a fired bubble has collided with another
1695 * bubble.
1696 ******************************************************************************/
1697 static bool bubbles_collision(struct game_context* bb, int y, int x,
1698 int nearrow, int nearcol) {
1699 int nx, ny;
1700 int adj = nearrow%2;
1702 /* check neighbors */
1703 if(nearcol-1 >= 0) {
1704 if(bb->playboard[nearrow][nearcol-1].type >= 0) {
1705 nx = XOFS+(nearrow%2 ? ROW_INDENT : 0)+BUBBLE_WIDTH*(nearcol-1);
1706 ny = YOFS+ROW_HEIGHT*nearrow+bb->compress*ROW_HEIGHT;
1707 if((x-nx)*(x-nx)+(y-ny)*(y-ny) < MIN_DISTANCE) return true;
1711 if(nearcol-1+adj >= 0) {
1712 if(nearrow-1 >= 0) {
1713 if(bb->playboard[nearrow-1][nearcol-1+adj].type >= 0) {
1714 nx = XOFS+((nearrow-1)%2 ? ROW_INDENT : 0)+
1715 BUBBLE_WIDTH*(nearcol-1+adj);
1716 ny = YOFS+ROW_HEIGHT*(nearrow-1)+bb->compress*ROW_HEIGHT;
1717 if((x-nx)*(x-nx)+(y-ny)*(y-ny) < MIN_DISTANCE) return true;
1721 if(nearrow+1 < BB_HEIGHT) {
1722 if(bb->playboard[nearrow+1][nearcol-1+adj].type >= 0) {
1723 nx = XOFS+((nearrow+1)%2 ? ROW_INDENT : 0)+
1724 BUBBLE_WIDTH*(nearcol-1+adj);
1725 ny = YOFS+ROW_HEIGHT*(nearrow+1)+bb->compress*ROW_HEIGHT;
1726 if((x-nx)*(x-nx)+(y-ny)*(y-ny) < MIN_DISTANCE) return true;
1731 if(nearcol+adj >= 0) {
1732 if(nearrow-1 >= 0) {
1733 if(bb->playboard[nearrow-1][nearcol+adj].type >= 0) {
1734 nx = XOFS+((nearrow-1)%2 ? ROW_INDENT : 0)+
1735 BUBBLE_WIDTH*(nearcol+adj);
1736 ny = YOFS+ROW_HEIGHT*(nearrow-1)+bb->compress*ROW_HEIGHT;
1737 if((x-nx)*(x-nx)+(y-ny)*(y-ny) < MIN_DISTANCE) return true;
1741 if(nearrow+1 < BB_HEIGHT) {
1742 if(bb->playboard[nearrow+1][nearcol+adj].type >= 0) {
1743 nx = XOFS+((nearrow+1)%2 ? ROW_INDENT : 0)+
1744 BUBBLE_WIDTH*(nearcol+adj);
1745 ny = YOFS+ROW_HEIGHT*(nearrow+1)+bb->compress*ROW_HEIGHT;
1746 if((x-nx)*(x-nx)+(y-ny)*(y-ny) < MIN_DISTANCE) return true;
1751 if(nearcol+1 < BB_WIDTH-adj) {
1752 if(bb->playboard[nearrow][nearcol+1].type >= 0) {
1753 nx = XOFS+(nearrow%2 ? ROW_INDENT : 0)+BUBBLE_WIDTH*(nearcol+1);
1754 ny = YOFS+ROW_HEIGHT*nearrow+bb->compress*ROW_HEIGHT;
1755 if((x-nx)*(x-nx)+(y-ny)*(y-ny) < MIN_DISTANCE) return true;
1759 return false;
1762 /*****************************************************************************
1763 * bubbles_ingroup() marks all bubbles that form the current group.
1764 ******************************************************************************/
1765 static bool bubbles_ingroup(struct game_context* bb, int row, int col) {
1766 int i, j;
1767 int count;
1769 count = bubbles_searchgroup(bb, row, col);
1771 /* unmark group if too small */
1772 if(count < 3) {
1773 for(i=0; i<BB_HEIGHT; i++) {
1774 for(j=0; j<BB_WIDTH; j++) {
1775 bb->playboard[i][j].ingroup = false;
1779 return false;
1782 return true;
1785 /*****************************************************************************
1786 * bubbles_searchgroup() return the size of the group of bubbles of the same
1787 * type that the current bubble belongs to.
1788 ******************************************************************************/
1789 static int bubbles_searchgroup(struct game_context* bb, int row, int col) {
1790 int i, adj;
1791 int myrow, mycol, mytype;
1792 int count = 0;
1794 struct coord {
1795 int row;
1796 int col;
1797 } search[(2*BB_WIDTH-1)*(BB_HEIGHT/2)];
1799 /* search initial bubble */
1800 bb->playboard[row][col].ingroup = true;
1801 search[count].row = row;
1802 search[count].col = col;
1803 count++;
1805 /* breadth-first search neighbors */
1806 for(i=0; i<count; i++) {
1807 myrow = search[i].row;
1808 mycol = search[i].col;
1809 mytype = bb->playboard[myrow][mycol].type;
1810 adj = myrow%2;
1812 if(mycol-1 >= 0) {
1813 if(bb->playboard[myrow][mycol-1].type == mytype &&
1814 !bb->playboard[myrow][mycol-1].ingroup) {
1815 bb->playboard[myrow][mycol-1].ingroup = true;
1816 search[count].row = myrow;
1817 search[count].col = mycol-1;
1818 count++;
1822 if(mycol-1+adj >= 0) {
1823 if(myrow-1 >= 0) {
1824 if(bb->playboard[myrow-1][mycol-1+adj].type == mytype &&
1825 !bb->playboard[myrow-1][mycol-1+adj].ingroup) {
1826 bb->playboard[myrow-1][mycol-1+adj].ingroup = true;
1827 search[count].row = myrow-1;
1828 search[count].col = mycol-1+adj;
1829 count++;
1833 if(myrow+1 < BB_HEIGHT) {
1834 if(bb->playboard[myrow+1][mycol-1+adj].type == mytype &&
1835 !bb->playboard[myrow+1][mycol-1+adj].ingroup) {
1836 bb->playboard[myrow+1][mycol-1+adj].ingroup = true;
1837 search[count].row = myrow+1;
1838 search[count].col = mycol-1+adj;
1839 count++;
1844 if(mycol+adj >= 0) {
1845 if(myrow-1 >= 0) {
1846 if(bb->playboard[myrow-1][mycol+adj].type == mytype &&
1847 !bb->playboard[myrow-1][mycol+adj].ingroup) {
1848 bb->playboard[myrow-1][mycol+adj].ingroup = true;
1849 search[count].row = myrow-1;
1850 search[count].col = mycol+adj;
1851 count++;
1855 if(myrow+1 < BB_HEIGHT) {
1856 if(bb->playboard[myrow+1][mycol+adj].type == mytype &&
1857 !bb->playboard[myrow+1][mycol+adj].ingroup) {
1858 bb->playboard[myrow+1][mycol+adj].ingroup = true;
1859 search[count].row = myrow+1;
1860 search[count].col = mycol+adj;
1861 count++;
1866 if(mycol+1 < BB_WIDTH-adj) {
1867 if(bb->playboard[myrow][mycol+1].type == mytype &&
1868 !bb->playboard[myrow][mycol+1].ingroup) {
1869 bb->playboard[myrow][mycol+1].ingroup = true;
1870 search[count].row = myrow;
1871 search[count].col = mycol+1;
1872 count++;
1877 return count;
1880 /*****************************************************************************
1881 * bubbles_remove() removes all bubbles in the current group and all
1882 * unanchored bubbles from the play board.
1883 ******************************************************************************/
1884 static int bubbles_remove(struct game_context* bb) {
1885 int i, j;
1886 int buttonres;
1888 /* determine all anchored bubbles */
1889 for(j=0; j<BB_WIDTH; j++) {
1890 if(bb->playboard[0][j].type >= 0 && !bb->playboard[0][j].ingroup) {
1891 bubbles_anchored(bb, 0, j);
1895 /* mark bubbles to be deleted */
1896 for(i=0; i<BB_HEIGHT; i++) {
1897 for(j=0; j<BB_WIDTH; j++) {
1898 if(bb->playboard[i][j].type >= 0 &&
1899 (!bb->playboard[i][j].anchored || bb->playboard[i][j].ingroup)) {
1900 bb->playboard[i][j].delete = true;
1905 /* animate falling bubbles */
1906 buttonres = bubbles_fall(bb);
1907 if(buttonres != BB_NONE) return buttonres;
1909 /* remove bubbles */
1910 for(i=0; i<BB_HEIGHT; i++) {
1911 for(j=0; j<BB_WIDTH; j++) {
1912 if(bb->playboard[i][j].delete) {
1913 bb->playboard[i][j].ingroup = false;
1914 bb->playboard[i][j].type = -1;
1915 bb->playboard[i][j].delete = false;
1916 } else {
1917 bb->playboard[i][j].anchored = false;
1922 bubbles_getonboard(bb);
1924 return BB_NONE;
1927 /*****************************************************************************
1928 * bubbles_anchored() marks all bubbles that are anchored in some way to the
1929 * current bubble.
1930 ******************************************************************************/
1931 static void bubbles_anchored(struct game_context* bb, int row, int col) {
1932 int i, adj;
1933 int myrow, mycol, mytype;
1934 int count = 0;
1936 struct coord {
1937 int row;
1938 int col;
1939 } search[(2*BB_WIDTH-1)*(BB_HEIGHT/2)];
1941 /* search initial bubble */
1942 bb->playboard[row][col].anchored = true;
1943 search[count].row = row;
1944 search[count].col = col;
1945 count++;
1947 /* breadth-first search neighbors */
1948 for(i=0; i<count; i++) {
1949 myrow = search[i].row;
1950 mycol = search[i].col;
1951 mytype = bb->playboard[myrow][mycol].type;
1952 adj = myrow%2;
1954 if(mycol-1 >= 0) {
1955 if(bb->playboard[myrow][mycol-1].type >= 0 &&
1956 !bb->playboard[myrow][mycol-1].ingroup &&
1957 !bb->playboard[myrow][mycol-1].anchored) {
1958 bb->playboard[myrow][mycol-1].anchored = true;
1959 search[count].row = myrow;
1960 search[count].col = mycol-1;
1961 count++;
1965 if(mycol-1+adj >= 0) {
1966 if(myrow-1 >= 0) {
1967 if(bb->playboard[myrow-1][mycol-1+adj].type >= 0 &&
1968 !bb->playboard[myrow-1][mycol-1+adj].ingroup &&
1969 !bb->playboard[myrow-1][mycol-1+adj].anchored) {
1970 bb->playboard[myrow-1][mycol-1+adj].anchored = true;
1971 search[count].row = myrow-1;
1972 search[count].col = mycol-1+adj;
1973 count++;
1977 if(myrow+1 < BB_HEIGHT) {
1978 if(bb->playboard[myrow+1][mycol-1+adj].type >= 0 &&
1979 !bb->playboard[myrow+1][mycol-1+adj].ingroup &&
1980 !bb->playboard[myrow+1][mycol-1+adj].anchored) {
1981 bb->playboard[myrow+1][mycol-1+adj].anchored = true;
1982 search[count].row = myrow+1;
1983 search[count].col = mycol-1+adj;
1984 count++;
1989 if(mycol+adj >= 0) {
1990 if(myrow-1 >= 0) {
1991 if(bb->playboard[myrow-1][mycol+adj].type >= 0 &&
1992 !bb->playboard[myrow-1][mycol+adj].ingroup &&
1993 !bb->playboard[myrow-1][mycol+adj].anchored) {
1994 bb->playboard[myrow-1][mycol+adj].anchored = true;
1995 search[count].row = myrow-1;
1996 search[count].col = mycol+adj;
1997 count++;
2001 if(myrow+1 < BB_HEIGHT) {
2002 if(bb->playboard[myrow+1][mycol+adj].type >= 0 &&
2003 !bb->playboard[myrow+1][mycol+adj].ingroup &&
2004 !bb->playboard[myrow+1][mycol+adj].anchored) {
2005 bb->playboard[myrow+1][mycol+adj].anchored = true;
2006 search[count].row = myrow+1;
2007 search[count].col = mycol+adj;
2008 count++;
2013 if(mycol+1 < BB_WIDTH-adj) {
2014 if(bb->playboard[myrow][mycol+1].type >= 0 &&
2015 !bb->playboard[myrow][mycol+1].ingroup &&
2016 !bb->playboard[myrow][mycol+1].anchored) {
2017 bb->playboard[myrow][mycol+1].anchored = true;
2018 search[count].row = myrow;
2019 search[count].col = mycol+1;
2020 count++;
2026 /*****************************************************************************
2027 * bubbles_fall() makes removed bubbles fall from the screen.
2028 ******************************************************************************/
2029 static int bubbles_fall(struct game_context* bb) {
2030 int i, j;
2031 int count;
2032 int indent;
2033 int xofs, yofs;
2034 int buttonres;
2035 bool onscreen;
2036 long lasttick, currenttick;
2038 /* give all falling bubbles an x axis movement */
2039 for(i=0; i<BB_HEIGHT; i++) {
2040 for(j=0; j<BB_WIDTH; j++) {
2041 if(bb->playboard[i][j].delete) {
2042 bb->playboard[i][j].fallx = rb->rand()%25 - 12;
2043 bb->playboard[i][j].fallvel = rb->rand()%5 + 6;
2048 /* draw bubbles falling off the screen
2049 * follows y=x^2-8x scaled to bubble size
2051 lasttick = *rb->current_tick;
2053 for(count=1; ;count++) {
2054 onscreen = false;
2055 bubbles_drawboard(bb);
2057 for(i=0; i<BB_HEIGHT; i++) {
2058 for(j=0; j<BB_WIDTH; j++) {
2059 if(bb->playboard[i][j].delete) {
2060 indent = (i%2 ? ROW_INDENT : 0);
2061 xofs = ((bb->playboard[i][j].fallx*count)*BUBBLE_WIDTH)/48;
2062 yofs = ((count*count - bb->playboard[i][j].fallvel*count)*
2063 BUBBLE_HEIGHT)/20;
2065 /* draw bubble if it is still on the screen */
2066 if(YOFS+ROW_HEIGHT*i+bb->compress*ROW_HEIGHT+yofs
2067 <= LCD_HEIGHT) {
2068 onscreen = true;
2070 rb->lcd_bitmap_part(bubbles_emblem, 0,
2071 EMBLEM_HEIGHT*bb->playboard[i][j].type,
2072 STRIDE( SCREEN_MAIN,
2073 BMPWIDTH_bubbles_emblem,
2074 BMPHEIGHT_bubbles_emblem),
2075 XOFS+indent+BUBBLE_WIDTH*j+
2076 (BUBBLE_WIDTH-EMBLEM_WIDTH)/2+xofs,
2077 YOFS+ROW_HEIGHT*i+(BUBBLE_HEIGHT-EMBLEM_HEIGHT)/2+
2078 bb->compress*ROW_HEIGHT+yofs,
2079 EMBLEM_WIDTH, EMBLEM_HEIGHT);
2080 rb->lcd_set_drawmode(DRMODE_FG);
2081 rb->lcd_mono_bitmap(
2082 (const unsigned char *)bubbles_bubble,
2083 XOFS+indent+BUBBLE_WIDTH*j+xofs,
2084 YOFS+ROW_HEIGHT*i+bb->compress*ROW_HEIGHT+yofs,
2085 BUBBLE_WIDTH, BUBBLE_HEIGHT);
2086 rb->lcd_set_drawmode(DRMODE_SOLID);
2092 rb->lcd_update();
2094 /* break out if all bubbles are off the screen */
2095 if(!onscreen) break;
2097 /* handle button events */
2098 buttonres = bubbles_handlebuttons(bb, true, 0);
2099 if(buttonres != BB_NONE) return buttonres;
2101 /* framerate limiting */
2102 currenttick = *rb->current_tick;
2103 if(currenttick-lasttick < HZ/MAX_FPS) {
2104 rb->sleep((HZ/MAX_FPS)-(currenttick-lasttick));
2105 } else {
2106 rb->yield();
2108 lasttick = currenttick;
2111 return BB_NONE;
2114 /*****************************************************************************
2115 * bubbles_checklevel() checks the state of the playboard for a win or loss.
2116 ******************************************************************************/
2117 static int bubbles_checklevel(struct game_context* bb) {
2118 int i, j;
2119 int points;
2120 char str[13];
2122 bubbles_drawboard(bb);
2123 rb->lcd_update();
2125 /* check for bubbles below cut off point */
2126 for(i=0; i<=bb->compress; i++) {
2127 for(j=0; j<BB_WIDTH; j++) {
2128 if(bb->playboard[BB_HEIGHT-1-i][j].type >= 0) return BB_LOSE;
2132 /* check for bubbles above cut off point */
2133 for(i=0; i<BB_HEIGHT-1-bb->compress; i++) {
2134 for(j=0; j<BB_WIDTH; j++) {
2135 if(bb->playboard[i][j].type >= 0) return BB_NONE;
2139 /* level complete, record score */
2140 points = 100 - bb->elapsedlvl/100;
2141 if(points > 0) {
2142 bb->score += points;
2143 } else {
2144 points = 0;
2147 rb->snprintf(str, 12, "%d points", points);
2148 rb->splash(HZ, str);
2150 /* advance to the next level */
2151 if(!bubbles_nextlevel(bb)) {
2152 return BB_WIN;
2155 bubbles_drawboard(bb);
2156 rb->lcd_update();
2157 rb->snprintf(str, 12, "Level %d", bb->level);
2158 rb->splash(HZ, str);
2159 bubbles_drawboard(bb);
2160 rb->lcd_update();
2162 return BB_NONE;
2165 /*****************************************************************************
2166 * bubbles_recordscore() inserts a high score into the high scores list and
2167 * returns the high score position.
2168 ******************************************************************************/
2169 static void bubbles_recordscore(struct game_context* bb) {
2171 int position;
2173 position = highscore_update(bb->score, bb->level-1, "",
2174 highscores, NUM_SCORES);
2175 if (position != -1)
2177 if (position == 0)
2178 rb->splash(HZ*2, "New High Score");
2179 highscore_show(position, highscores, NUM_SCORES, true);
2183 /*****************************************************************************
2184 * bubbles_loaddata() loads highest level beaten.
2185 ******************************************************************************/
2186 static void bubbles_loaddata(void) {
2187 int fd;
2189 last_highlevel = highlevel = 0;
2190 /* open data file */
2191 fd = rb->open(DATA_FILE, O_RDONLY);
2192 if (fd < 0) return;
2194 /* read in saved game */
2195 if (rb->read(fd, &highlevel, sizeof(highlevel)) < (long)sizeof(highlevel))
2197 highlevel = 0;
2199 if (highlevel >= NUM_LEVELS)
2200 highlevel = NUM_LEVELS-1;
2201 last_highlevel = highlevel;
2203 rb->close(fd);
2206 /*****************************************************************************
2207 * bubbles_savedata() saves the current game state.
2208 ******************************************************************************/
2209 static void bubbles_savedata(void) {
2210 int fd;
2212 if (last_highlevel >= highlevel) /* no need to save */
2213 return;
2215 fd = rb->open(DATA_FILE, O_WRONLY|O_CREAT, 0666);
2216 if (fd < 0) return;
2218 rb->write(fd, &highlevel, sizeof(highlevel));
2220 rb->close(fd);
2223 /*****************************************************************************
2224 * bubbles_loadgame() loads the saved game and returns load success.
2225 ******************************************************************************/
2226 static bool bubbles_loadgame(struct game_context* bb) {
2227 int fd;
2229 bool ret = true;
2230 /* open game file */
2231 fd = rb->open(SAVE_FILE, O_RDONLY);
2232 if(fd < 0) return false;
2234 /* read in saved game */
2235 if(rb->read(fd, bb, sizeof(struct game_context))
2236 < (long)sizeof(struct game_context))
2238 ret = false;
2241 rb->close(fd);
2243 return ret;
2246 /*****************************************************************************
2247 * bubbles_savegame() saves the current game state.
2248 ******************************************************************************/
2249 static void bubbles_savegame(struct game_context* bb) {
2250 int fd;
2252 if (!resume) /* nothing to save */
2253 return;
2254 /* write out the game state to the save file */
2255 fd = rb->open(SAVE_FILE, O_WRONLY|O_CREAT, 0666);
2256 if (fd < 0)
2258 rb->splash(HZ/2, "Failed to save game");
2259 return;
2261 if (rb->write(fd, bb, sizeof(struct game_context)) <= 0)
2263 rb->splash(HZ/2, "Failed to save game");
2266 rb->close(fd);
2269 /*****************************************************************************
2270 * bubbles_setcolors() set the foreground and background colors.
2271 ******************************************************************************/
2272 static inline void bubbles_setcolors(void) {
2273 #ifdef HAVE_LCD_COLOR
2274 rb->lcd_set_background(LCD_RGBPACK(181,181,222));
2275 rb->lcd_set_foreground(LCD_BLACK);
2276 #endif
2279 /*****************************************************************************
2280 * bubbles_callback() is the default event handler callback which is called
2281 * on usb connect and shutdown.
2282 ******************************************************************************/
2283 static void bubbles_callback(void* param) {
2284 (void) param;
2285 highscore_save(SCORE_FILE, highscores, NUM_SCORES);
2288 /*****************************************************************************
2289 * bubbles_handlebuttons() handles button events during a game.
2290 ******************************************************************************/
2291 static int bubbles_handlebuttons(struct game_context* bb, bool animblock,
2292 int timeout) {
2293 int button;
2294 int buttonres;
2295 long start;
2296 const struct button_mapping *plugin_contexts[]
2297 #if (CONFIG_KEYPAD == SANSA_E200_PAD) || \
2298 (CONFIG_KEYPAD == SANSA_FUZE_PAD)
2299 = {generic_directions,generic_actions};
2300 #else
2301 = {generic_left_right_fire,generic_actions};
2302 #endif
2304 if (timeout < 0)
2305 timeout = 0;
2306 button = pluginlib_getaction(timeout,plugin_contexts,2);
2307 #if defined(HAS_BUTTON_HOLD) && !defined(HAVE_REMOTE_LCD_AS_MAIN)
2308 /* FIXME: Should probably check remote hold here */
2309 if (rb->button_hold())
2310 button = BUBBLES_PAUSE;
2311 #endif
2313 switch(button){
2314 case BUBBLES_LEFT_REP:
2315 if(bb->angle > MIN_ANGLE) bb->angle -= ANGLE_STEP_REP;
2316 case BUBBLES_LEFT: /* change angle to the left */
2317 if(bb->angle > MIN_ANGLE) bb->angle -= ANGLE_STEP;
2318 break;
2320 case BUBBLES_RIGHT_REP:
2321 if(bb->angle < MAX_ANGLE) bb->angle += ANGLE_STEP_REP;
2322 case BUBBLES_RIGHT: /* change angle to the right */
2323 if(bb->angle < MAX_ANGLE) bb->angle += ANGLE_STEP;
2324 break;
2326 case BUBBLES_FIRE: /* fire the shot */
2327 if(!animblock) {
2328 bb->elapsedlvl += bb->elapsedshot;
2329 bb->elapsedshot = 0;
2330 buttonres = bubbles_fire(bb);
2331 if(buttonres != BB_NONE) return buttonres;
2332 buttonres = bubbles_checklevel(bb);
2333 if(buttonres != BB_NONE) return buttonres;
2334 bb->startedshot = *rb->current_tick;
2336 break;
2338 case BUBBLES_PAUSE: /* pause the game */
2339 start = *rb->current_tick;
2340 rb->splash(0, "Paused");
2341 while(pluginlib_getaction(TIMEOUT_BLOCK,plugin_contexts,2)
2342 != BUBBLES_PAUSE);
2343 bb->startedshot += *rb->current_tick-start;
2344 bubbles_drawboard(bb);
2345 rb->lcd_update();
2346 break;
2348 case BUBBLES_QUIT1:
2349 case BUBBLES_QUIT2: /* end the game */
2350 if(!animblock) {
2351 resume = true;
2352 return BB_END;
2354 break;
2356 case ACTION_UNKNOWN:
2357 case ACTION_NONE: /* no button pressed */
2358 break;
2360 default:
2361 if(rb->default_event_handler_ex(button, bubbles_callback,
2362 (void*) bb) == SYS_USB_CONNECTED)
2363 return BB_USB;
2364 break;
2367 return BB_NONE;
2370 static int bubbles_menu_cb(int action, const struct menu_item_ex *this_item)
2372 int i = ((intptr_t)this_item);
2373 if(action == ACTION_REQUEST_MENUITEM
2374 && !resume && (i==0))
2375 return ACTION_EXIT_MENUITEM;
2376 return action;
2379 /*****************************************************************************
2380 * bubbles_menu() is the initial menu at the start of the game.
2381 ******************************************************************************/
2382 static int bubbles_menu(struct game_context* bb) {
2383 static unsigned int startlevel = 0;
2384 int selected = 0;
2385 bool startgame = false;
2387 MENUITEM_STRINGLIST(menu,"Bubbles Menu",bubbles_menu_cb,
2388 "Resume Game", "Start New Game",
2389 "Level", "High Scores", "Playback Control",
2390 "Quit without Saving", "Quit");
2392 while(!startgame){
2393 switch (rb->do_menu(&menu, &selected, NULL, false))
2395 case 0: /* resume game */
2396 startgame = true;
2397 if(resume_file)
2398 rb->remove(SAVE_FILE);
2399 resume_file = false;
2400 break;
2401 case 1: /* new game */
2402 bb->level = startlevel;
2403 startgame = true;
2404 resume = false;
2405 resume_file = false;
2406 break;
2407 case 2: /* choose level */
2408 startlevel++;
2409 rb->set_int("Choose start level", "", UNIT_INT, &startlevel,
2410 NULL, 1, 1, highlevel+1, NULL);
2411 startlevel--;
2412 break;
2413 case 3: /* High scores */
2414 highscore_show(-1, highscores, NUM_SCORES, true);
2415 break;
2416 case 4: /* Playback Control */
2417 playback_control(NULL);
2418 break;
2419 case 5: /* quit but don't save */
2420 return BB_QUIT_WITHOUT_SAVING;
2421 case 6: /* save and quit */
2422 return BB_QUIT;
2423 case MENU_ATTACHED_USB:
2424 bubbles_callback(bb);
2425 return BB_USB;
2428 return 0;
2431 /*****************************************************************************
2432 * bubbles() is the main game subroutine, it returns the final game status.
2433 ******************************************************************************/
2434 static int bubbles(struct game_context* bb) {
2435 int buttonres;
2436 long timeout;
2438 /********************
2439 * menu *
2440 ********************/
2441 buttonres = bubbles_menu(bb);
2442 if(buttonres != 0)
2443 return buttonres;
2445 /********************
2446 * init *
2447 ********************/
2448 bubbles_init(bb);
2449 bubbles_drawboard(bb);
2450 rb->lcd_update();
2452 /**********************
2453 * play *
2454 **********************/
2455 bb->startedshot = *rb->current_tick;
2457 while(true) {
2458 /* refresh the board */
2459 bubbles_drawboard(bb);
2460 rb->lcd_update();
2462 /* manange idle framerate */
2463 bb->elapsedshot = *rb->current_tick-bb->startedshot;
2465 if(MAX_SHOTTIME-bb->elapsedshot < HZ/2) {
2466 timeout = MAX_SHOTTIME-bb->elapsedshot;
2467 } else {
2468 timeout = HZ/2;
2471 /* handle button events */
2472 buttonres = bubbles_handlebuttons(bb, false, timeout);
2473 if(buttonres != BB_NONE) return buttonres;
2475 /* handle timing */
2476 bb->elapsedshot = *rb->current_tick-bb->startedshot;
2478 if(bb->elapsedshot > MAX_SHOTTIME) {
2479 bb->elapsedlvl += bb->elapsedshot;
2480 bb->elapsedshot = 0;
2481 buttonres = bubbles_fire(bb);
2482 if(buttonres != BB_NONE) return buttonres;
2483 buttonres = bubbles_checklevel(bb);
2484 if(buttonres != BB_NONE) return buttonres;
2485 bb->startedshot = *rb->current_tick;
2490 /*****************************************************************************
2491 * plugin entry point.
2492 ******************************************************************************/
2493 enum plugin_status plugin_start(const void* parameter) {
2494 static struct game_context bb;
2495 bool exit = false;
2496 enum plugin_status ret = PLUGIN_OK;
2498 (void)parameter;
2500 /* load files */
2501 resume = bubbles_loadgame(&bb);
2502 resume_file = resume;
2503 bubbles_loaddata();
2504 highscore_load(SCORE_FILE, highscores, NUM_SCORES);
2505 rb->lcd_clear_display();
2507 /* start app */
2508 #if LCD_DEPTH > 1
2509 rb->lcd_set_backdrop(NULL);
2510 #endif
2511 rb->lcd_setfont(FONT_SYSFIXED);
2513 while(!exit) {
2514 switch(bubbles(&bb)){
2515 case BB_WIN:
2516 rb->splash(HZ*2, "You Win!");
2517 /* record high level */
2518 highlevel = NUM_LEVELS-1;
2519 /* record high score */
2520 bubbles_recordscore(&bb);
2521 break;
2523 case BB_LOSE:
2524 resume = false;
2525 rb->splash(HZ*2, "Game Over");
2526 /* record high score */
2527 bubbles_recordscore(&bb);
2528 /* fall through to BB_END */
2530 case BB_END:
2531 break;
2533 case BB_USB:
2534 ret = PLUGIN_USB_CONNECTED;
2535 exit = true;
2536 break;
2538 case BB_QUIT:
2539 rb->splash(HZ/3, "Saving game data ...");
2540 bubbles_savegame(&bb);
2541 bubbles_savedata();
2542 highscore_save(SCORE_FILE, highscores, NUM_SCORES);
2543 /* fall through */
2545 case BB_QUIT_WITHOUT_SAVING:
2546 exit = true;
2547 break;
2549 default:
2550 break;
2553 rb->lcd_setfont(FONT_UI);
2554 return ret;
2557 #endif