when changing settings from the Talk and Voice window also update the main widgets...
[Rockbox.git] / apps / plugins / bubbles.c
blob05ce15d75b3e1a138ec04a0692112c271ded8ae1
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 * All files in this archive are subject to the GNU General Public License.
15 * See the file COPYING in the source tree root for full license agreement.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
22 #include "plugin.h"
24 #ifdef HAVE_LCD_BITMAP
26 #include "xlcd.h"
27 #include "pluginlib_actions.h"
28 #include "fixedpoint.h"
30 PLUGIN_HEADER
32 /* files */
33 #define SCORE_FILE PLUGIN_GAMES_DIR "/bubbles.score"
34 #define SAVE_FILE PLUGIN_GAMES_DIR "/bubbles.save"
36 /* final game return status */
37 #define BB_NONE 5
38 #define BB_WIN 4
39 #define BB_END 3
40 #define BB_USB 2
41 #define BB_QUIT 1
42 #define BB_LOSE 0
44 /* play board dimension */
45 #define BB_HEIGHT 12
46 #define BB_WIDTH 8
47 #define BB_LEVEL_HEIGHT 10
49 /* various amounts */
50 #define NUM_SCORES 10
51 #define NUM_LEVELS 100
52 #define NUM_QUEUE 2
53 #define NUM_BUBBLES 8
54 #define MIN_ANGLE -76
55 #define MAX_ANGLE 76
56 #define NUM_COMPRESS 9
57 #define MAX_SHOTTIME 1000
59 /* keyboard layouts */
60 #if CONFIG_KEYPAD != SANSA_E200_PAD
61 /* sansa uses the wheel instead of left/right */
62 #define BUBBLES_LEFT PLA_LEFT
63 #define BUBBLES_LEFT_REP PLA_LEFT_REPEAT
64 #define BUBBLES_RIGHT PLA_RIGHT
65 #define BUBBLES_RIGHT_REP PLA_RIGHT_REPEAT
66 #define ANGLE_STEP 4
67 #define ANGLE_STEP_REP 4
68 #else
69 #define BUBBLES_LEFT PLA_UP
70 #define BUBBLES_LEFT_REP PLA_UP_REPEAT
71 #define BUBBLES_RIGHT PLA_DOWN
72 #define BUBBLES_RIGHT_REP PLA_DOWN_REPEAT
73 #define ANGLE_STEP 2
74 #define ANGLE_STEP_REP 4
75 #endif
77 #define BUBBLES_QUIT PLA_QUIT
78 #define BUBBLES_START PLA_START
79 #define BUBBLES_SELECT PLA_FIRE
80 #define BUBBLES_RESUME PLA_MENU
82 #if CONFIG_KEYPAD != ONDIO_PAD
84 #define BUBBLES_LVLINC PLA_UP
85 #define BUBBLES_LVLINC_REP PLA_UP_REPEAT
86 #define BUBBLES_LVLDEC PLA_DOWN
87 #define BUBBLES_LVLDEC_REP PLA_DOWN_REPEAT
89 #else /* ondio keys */
91 #define BUBBLES_LVLINC PLA_RIGHT
92 #define BUBBLES_LVLINC_REP PLA_RIGHT_REPEAT
93 #define BUBBLES_LVLDEC PLA_LEFT
94 #define BUBBLES_LVLDEC_REP PLA_LEFT_REPEAT
96 #endif
99 /* bubbles will consume height of ROW_HEIGHT*(BB_HEIGHT-1)+BUBBLE_HEIGHT*3/2 */
100 /* 22x22 bubbles (iPod Video) */
101 #if (LCD_HEIGHT == 240) && (LCD_WIDTH == 320)
102 #define BUBBLE_WIDTH 22
103 #define BUBBLE_HEIGHT 22
104 #define EMBLEM_WIDTH 16
105 #define EMBLEM_HEIGHT 16
106 #define XOFS 72
107 #define ROW_HEIGHT 18
108 #define ROW_INDENT 11
109 #define MAX_FPS 40
111 /* 22x22 bubbles (Gigabeat) */
112 #elif (LCD_HEIGHT == 320) && (LCD_WIDTH == 240)
113 #define BUBBLE_WIDTH 22
114 #define BUBBLE_HEIGHT 22
115 #define EMBLEM_WIDTH 16
116 #define EMBLEM_HEIGHT 16
117 #define XOFS 64
118 #define ROW_HEIGHT 18
119 #define ROW_INDENT 11
120 #define MAX_FPS 30
122 /* 16x16 bubbles (H300, iPod Color) */
123 #elif (LCD_HEIGHT == 176) && (LCD_WIDTH == 220)
124 #define BUBBLE_WIDTH 16
125 #define BUBBLE_HEIGHT 16
126 #define EMBLEM_WIDTH 12
127 #define EMBLEM_HEIGHT 12
128 #define XOFS 46
129 #define ROW_HEIGHT 14
130 #define ROW_INDENT 8
131 #define MAX_FPS 30
133 /* 16x16 bubbles (Sansa E200) */
134 #elif (LCD_HEIGHT == 220) && (LCD_WIDTH == 176)
135 #define BUBBLE_WIDTH 16
136 #define BUBBLE_HEIGHT 16
137 #define EMBLEM_WIDTH 12
138 #define EMBLEM_HEIGHT 12
139 #define XOFS 48
140 #define ROW_HEIGHT 14
141 #define ROW_INDENT 8
142 #define MAX_FPS 30
144 /* 12x12 bubbles (iPod Nano) */
145 #elif (LCD_HEIGHT == 132) && (LCD_WIDTH == 176)
146 #define BUBBLE_WIDTH 12
147 #define BUBBLE_HEIGHT 12
148 #define EMBLEM_WIDTH 8
149 #define EMBLEM_HEIGHT 8
150 #define XOFS 40
151 #define ROW_HEIGHT 10
152 #define ROW_INDENT 6
153 #define MAX_FPS 40
155 /* 12x12 bubbles (H100, H10, iAudio X5, iPod 3G, iPod 4G grayscale) */
156 #elif (LCD_HEIGHT == 128) && ((LCD_WIDTH == 160) || (LCD_WIDTH == 128))
157 #define BUBBLE_WIDTH 12
158 #define BUBBLE_HEIGHT 12
159 #define EMBLEM_WIDTH 8
160 #define EMBLEM_HEIGHT 8
161 #define XOFS 33
162 #define ROW_HEIGHT 10
163 #define ROW_INDENT 6
164 #define MAX_FPS 30
166 /* 10x10 bubbles (iPod Mini) */
167 #elif (LCD_HEIGHT == 110) && (LCD_WIDTH == 138)
168 #define BUBBLE_WIDTH 10
169 #define BUBBLE_HEIGHT 10
170 #define EMBLEM_WIDTH 6
171 #define EMBLEM_HEIGHT 6
172 #define XOFS 33
173 #define ROW_HEIGHT 8
174 #define ROW_INDENT 5
175 #define MAX_FPS 30
177 /* 8x8 bubbles (Sansa C200) */
178 #elif (LCD_HEIGHT == 80) && (LCD_WIDTH == 132)
179 #define BUBBLE_WIDTH 8
180 #define BUBBLE_HEIGHT 8
181 #define EMBLEM_WIDTH 6
182 #define EMBLEM_HEIGHT 6
183 #define XOFS 45
184 #define ROW_HEIGHT 6
185 #define ROW_INDENT 4
186 #define MAX_FPS 30
188 /* 8x7 bubbles (Archos recorder, Ondio) */
189 #elif (LCD_HEIGHT == 64) && (LCD_WIDTH == 112)
190 #define BUBBLE_WIDTH 8
191 #define BUBBLE_HEIGHT 7
192 #define EMBLEM_WIDTH 7
193 #define EMBLEM_HEIGHT 5
194 #define XOFS 33
195 #define ROW_HEIGHT 5
196 #define ROW_INDENT 4
197 #define MAX_FPS 20
199 #else
200 #error BUBBLES: Unsupported LCD type
201 #endif
203 #define TEXT_LINES (LCD_HEIGHT/8)
205 /* shot position */
206 #define SHOTX XOFS+ROW_INDENT+BUBBLE_WIDTH*3
207 #define SHOTY ROW_HEIGHT*(BB_HEIGHT-1)+BUBBLE_HEIGHT/2
209 /* collision distance squared */
210 #define MIN_DISTANCE ((BUBBLE_WIDTH*8)/10)*((BUBBLE_HEIGHT*8)/10)
212 /* external bitmaps */
213 extern const fb_data bubbles_bubble[];
214 extern const fb_data bubbles_emblem[];
215 #ifdef HAVE_LCD_COLOR
216 extern const fb_data bubbles_background[];
217 #endif
219 /* global rockbox api */
220 static struct plugin_api* rb;
222 /* levels */
223 char level[NUM_LEVELS][BB_LEVEL_HEIGHT][BB_WIDTH] = {
224 {{ 6, 6, 4, 4, 2, 2, 3, 3},
225 { 6, 6, 4, 4, 2, 2, 3, -1},
226 { 2, 2, 3, 3, 6, 6, 4, 4},
227 { 2, 3, 3, 6, 6, 4, 4, -1},
228 {-1, -1, -1, -1, -1, -1, -1, -1},
229 {-1, -1, -1, -1, -1, -1, -1, -1},
230 {-1, -1, -1, -1, -1, -1, -1, -1},
231 {-1, -1, -1, -1, -1, -1, -1, -1},
232 {-1, -1, -1, -1, -1, -1, -1, -1},
233 {-1, -1, -1, -1, -1, -1, -1, -1}},
234 {{-1, 7, 7, 7, 7, 7, 7, -1},
235 {-1, 1, 1, 1, 1, 1, -1, -1},
236 {-1, -1, 2, 2, 2, 2, -1, -1},
237 {-1, -1, -1, 2, -1, -1, -1, -1},
238 {-1, -1, -1, 2, 2, -1, -1, -1},
239 {-1, -1, -1, 5, -1, -1, -1, -1},
240 {-1, -1, -1, 5, 5, -1, -1, -1},
241 {-1, -1, -1, -1, -1, -1, -1, -1},
242 {-1, -1, -1, -1, -1, -1, -1, -1},
243 {-1, -1, -1, -1, -1, -1, -1, -1}},
244 {{-1, -1, 7, -1, -1, 7, -1, -1},
245 {-1, -1, 7, 1, 7, -1, -1, -1},
246 {-1, -1, -1, 1, 2, -1, -1, -1},
247 {-1, -1, 1, 2, 1, -1, -1, -1},
248 {-1, -1, -1, 2, 5, -1, -1, -1},
249 {-1, -1, 3, 5, 3, -1, -1, -1},
250 {-1, -1, -1, 5, 3, -1, -1, -1},
251 {-1, -1, -1, 3, -1, -1, -1, -1},
252 {-1, -1, -1, -1, -1, -1, -1, -1},
253 {-1, -1, -1, -1, -1, -1, -1, -1}},
254 {{-1, -1, -1, 0, 0, -1, -1, -1},
255 {-1, -1, 5, 0, 1, -1, -1, -1},
256 {-1, -1, 3, 5, 1, 6, -1, -1},
257 {-1, 4, 3, -1, 6, 7, -1, -1},
258 {-1, 7, 4, -1, -1, 7, 4, -1},
259 { 6, 7, -1, -1, -1, 4, 3, -1},
260 { 1, 6, -1, -1, -1, -1, 3, 5},
261 { 1, -1, -1, -1, -1, -1, 5, -1},
262 {-1, -1, -1, -1, -1, -1, -1, -1},
263 {-1, -1, -1, -1, -1, -1, -1, -1}},
264 {{-1, -1, 0, 0, 0, 0, -1, -1},
265 {-1, 0, 1, 1, 1, 0, -1, -1},
266 {-1, 0, 1, 0, 0, 1, 0, -1},
267 {-1, 0, 1, 1, 1, 0, -1, -1},
268 {-1, -1, 0, 0, 0, 0, -1, -1},
269 {-1, -1, 7, -1, 7, -1, -1, -1},
270 {-1, -1, 7, 7, 7, 7, -1, -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, 4, 4, 4, 6, 6, 6, -1},
275 { 4, -1, -1, -1, -1, -1, 6, -1},
276 {-1, 4, -1, -1, -1, -1, 6, -1},
277 { 4, 2, 3, 1, 2, 3, 6, -1},
278 {-1, 3, 1, 2, 3, 1, 2, -1},
279 {-1, -1, -1, -1, -1, -1, -1, -1},
280 {-1, -1, -1, -1, -1, -1, -1, -1},
281 {-1, -1, -1, -1, -1, -1, -1, -1},
282 {-1, -1, -1, -1, -1, -1, -1, -1},
283 {-1, -1, -1, -1, -1, -1, -1, -1}},
284 {{-1, 4, 4, 4, 6, 6, 6, -1},
285 { 4, -1, -1, -1, -1, -1, 6, -1},
286 {-1, 4, -1, -1, -1, -1, 6, -1},
287 { 4, 2, 3, 1, 2, 3, 6, -1},
288 {-1, 3, 1, 2, 3, 1, 2, -1},
289 {-1, 2, 3, 1, 2, 3, -1, -1},
290 {-1, -1, -1, -1, -1, -1, -1, -1},
291 {-1, -1, -1, -1, -1, -1, -1, -1},
292 {-1, -1, -1, -1, -1, -1, -1, -1},
293 {-1, -1, -1, -1, -1, -1, -1, -1}},
294 {{-1, 0, 0, -1, -1, 2, 2, -1},
295 {-1, 5, -1, -1, -1, 3, -1, -1},
296 {-1, 0, -1, -1, -1, 6, -1, -1},
297 {-1, 3, -1, -1, -1, 0, -1, -1},
298 {-1, 4, -1, -1, -1, 5, -1, -1},
299 {-1, 2, -1, -1, -1, 3, -1, -1},
300 {-1, 2, -1, -1, -1, 1, -1, -1},
301 {-1, 3, -1, -1, -1, 4, -1, -1},
302 {-1, -1, -1, -1, -1, -1, -1, -1},
303 {-1, -1, -1, -1, -1, -1, -1, -1}},
304 {{ 3, -1, -1, -1, -1, -1, -1, 3},
305 { 6, 3, 2, 4, 6, 3, 2, -1},
306 { 4, -1, -1, -1, -1, -1, -1, 4},
307 { 2, 4, 6, 3, 2, 4, 6, -1},
308 {-1, -1, -1, 6, -1, -1, -1, -1},
309 {-1, -1, -1, 3, -1, -1, -1, -1},
310 {-1, -1, -1, -1, -1, -1, -1, -1},
311 {-1, -1, -1, -1, -1, -1, -1, -1},
312 {-1, -1, -1, -1, -1, -1, -1, -1},
313 {-1, -1, -1, -1, -1, -1, -1, -1}},
314 {{-1, 2, -1, 1, -1, 1, -1, 2},
315 { 1, 2, -1, 2, 1, -1, 1, -1},
316 { 1, -1, 1, -1, 2, -1, 2, -1},
317 { 2, 1, -1, 1, 2, -1, 2, -1},
318 {-1, 2, -1, 2, -1, 2, -1, 2},
319 { 1, 2, -1, 2, 1, -1, 1, -1},
320 { 1, -1, 1, -1, 2, -1, 1, -1},
321 { 2, 2, -1, 1, 1, -1, 2, -1},
322 {-1, 2, -1, 1, -1, 1, -1, 1},
323 {-1, -1, -1, -1, -1, -1, -1, -1}},
324 {{-1, 7, 7, -1, -1, 5, 5, -1},
325 { 1, -1, -1, -1, -1, -1, 4, -1},
326 { 2, 1, -1, -1, -1, -1, 4, 3},
327 { 2, -1, -1, -1, -1, -1, 3, -1},
328 { 1, 2, -1, -1, -1, -1, 3, 4},
329 { 1, -1, -1, -1, -1, -1, 4, -1},
330 { 7, 1, -1, -1, -1, -1, 4, 5},
331 { 7, 7, -1, -1, -1, 5, 5, -1},
332 {-1, -1, -1, -1, -1, -1, -1, -1},
333 {-1, -1, -1, -1, -1, -1, -1, -1}},
334 {{ 7, 7, -1, -1, -1, -1, 5, 5},
335 { 1, 5, -1, -1, -1, 7, 4, -1},
336 { 2, 1, -1, -1, -1, -1, 4, 3},
337 { 2, -1, -1, -1, -1, -1, 3, -1},
338 { 1, 5, -1, -1, -1, -1, 7, 4},
339 { 1, -1, -1, -1, -1, -1, 4, -1},
340 { 7, 1, -1, -1, -1, -1, 4, 5},
341 { 7, 5, -1, -1, -1, 7, 5, -1},
342 {-1, -1, -1, -1, -1, -1, -1, -1},
343 {-1, -1, -1, -1, -1, -1, -1, -1}},
344 {{-1, -1, -1, 0, 0, -1, -1, -1},
345 {-1, -1, 5, 0, 1, -1, -1, -1},
346 {-1, -1, 3, 5, 1, 6, -1, -1},
347 {-1, 4, 3, 2, 6, 2, -1, -1},
348 {-1, 7, 4, 7, 2, 2, 4, -1},
349 { 6, 7, 7, 3, 3, 4, 3, -1},
350 { 1, 6, 1, 1, 1, 3, 3, 5},
351 { 1, 1, -1, -1, -1, -1, 5, -1},
352 {-1, -1, -1, -1, -1, -1, -1, -1},
353 {-1, -1, -1, -1, -1, -1, -1, -1}},
354 {{-1, -1, 0, -1, -1, 0, -1, -1},
355 {-1, 3, 3, -1, 3, 3, -1, -1},
356 {-1, 0, 2, 0, 0, 2, 0, -1},
357 {-1, 3, 3, -1, 3, 3, -1, -1},
358 {-1, -1, 0, -1, -1, 0, -1, -1},
359 {-1, -1, -1, -1, -1, -1, -1, -1},
360 {-1, -1, -1, -1, -1, -1, -1, -1},
361 {-1, -1, -1, -1, -1, -1, -1, -1},
362 {-1, -1, -1, -1, -1, -1, -1, -1},
363 {-1, -1, -1, -1, -1, -1, -1, -1}},
364 {{-1, -1, -1, 1, 1, -1, -1, -1},
365 {-1, -1, 2, 2, 2, -1, -1, -1},
366 {-1, -1, 3, 3, 3, 3, -1, -1},
367 {-1, 4, 4, 4, 4, 4, -1, -1},
368 {-1, 5, 5, 5, 5, 5, 5, -1},
369 {-1, -1, -1, 6, -1, -1, -1, -1},
370 {-1, -1, -1, 7, 7, -1, -1, -1},
371 {-1, -1, -1, 0, -1, -1, -1, -1},
372 {-1, -1, -1, -1, -1, -1, -1, -1},
373 {-1, -1, -1, -1, -1, -1, -1, -1}},
374 {{-1, -1, -1, 2, 5, -1, -1, -1},
375 {-1, 4, 3, -1, -1, -1, -1, -1},
376 { 6, 7, -1, 5, 2, -1, -1, -1},
377 {-1, -1, -1, -1, 3, 4, -1, -1},
378 {-1, -1, -1, 2, 5, -1, 7, 6},
379 {-1, 4, 3, -1, -1, -1, -1, -1},
380 { 6, 7, -1, 5, 2, -1, -1, -1},
381 {-1, -1, -1, -1, 3, 4, -1, -1},
382 {-1, -1, -1, -1, -1, -1, 7, 6},
383 {-1, -1, -1, -1, -1, -1, -1, -1}},
384 {{-1, -1, -1, 5, 5, -1, -1, -1},
385 {-1, -1, -1, 3, -1, -1, -1, -1},
386 {-1, -1, -1, 1, -1, -1, -1, -1},
387 {-1, -1, -1, 7, -1, -1, -1, -1},
388 {-1, -1, -1, 2, -1, -1, -1, -1},
389 {-1, -1, -1, 4, -1, -1, -1, -1},
390 {-1, -1, -1, 5, -1, -1, -1, -1},
391 {-1, -1, -1, 3, -1, -1, -1, -1},
392 {-1, -1, -1, -1, -1, -1, -1, -1},
393 {-1, -1, -1, -1, -1, -1, -1, -1}},
394 {{-1, -1, -1, 0, 1, -1, -1, -1},
395 {-1, -1, 0, 2, 7, 7, -1, -1},
396 {-1, -1, -1, 0, 1, 7, -1, -1},
397 {-1, 0, 0, 0, 0, -1, -1, -1},
398 {-1, 0, 0, 0, 1, 1, -1, -1},
399 { 0, 0, 0, 1, 1, 1, -1, -1},
400 {-1, 0, 0, 1, 1, 1, -1, -1},
401 {-1, 0, 0, 0, 7, 7, -1, -1},
402 {-1, -1, 7, 7, -1, -1, -1, -1},
403 {-1, -1, -1, -1, -1, -1, -1, -1}},
404 {{-1, 1, -1, -1, -1, -1, -1, -1},
405 { 1, -1, -1, -1, -1, -1, -1, -1},
406 {-1, 2, 3, 4, 7, 6, 5, -1},
407 {-1, -1, -1, -1, -1, -1, 1, -1},
408 {-1, -1, -1, -1, -1, -1, 1, -1},
409 {-1, 2, 3, 4, 7, 6, -1, -1},
410 {-1, 1, -1, -1, -1, -1, -1, -1},
411 { 1, -1, -1, -1, -1, -1, -1, -1},
412 {-1, 2, 3, 4, 7, 6, 5, -1},
413 {-1, -1, -1, -1, -1, -1, -1, -1}},
414 {{-1, 6, -1, -1, -1, -1, -1, -1},
415 { 5, -1, -1, -1, -1, -1, -1, -1},
416 { 2, 3, 4, 7, 6, 5, 2, 3},
417 {-1, -1, -1, -1, -1, -1, 4, -1},
418 {-1, -1, -1, -1, -1, -1, 7, -1},
419 {-1, 4, 3, 2, 5, 6, -1, -1},
420 {-1, 7, -1, -1, -1, -1, -1, -1},
421 { 6, -1, -1, -1, -1, -1, -1, -1},
422 { 5, 2, 3, 4, 7, 6, 5, -1},
423 {-1, -1, -1, -1, -1, -1, -1, -1}},
424 {{ 3, 2, 1, 0, 0, 1, 2, 3},
425 { 3, 2, 1, 0, 1, 2, 3, -1},
426 { 4, 3, 2, 1, 1, 2, 3, 4},
427 { 4, 3, 2, 1, 2, 3, 4, -1},
428 { 5, 4, 3, 2, 2, 3, 4, 5},
429 { 5, 4, 3, 2, 3, 4, 5, -1},
430 { 6, 5, 4, 3, 3, 4, 5, 6},
431 { 6, 5, 4, 3, 4, 5, 6, -1},
432 { 7, 6, 5, 4, 4, 5, 6, 7},
433 {-1, -1, -1, -1, -1, -1, -1, -1}},
434 {{-1, -1, -1, 5, 5, -1, -1, -1},
435 {-1, -1, -1, 3, -1, -1, -1, -1},
436 {-1, -1, -1, 2, 4, -1, -1, -1},
437 {-1, -1, -1, 6, -1, -1, -1, -1},
438 {-1, -1, -1, 2, 4, -1, -1, -1},
439 {-1, 2, -1, 5, -1, 4, -1, -1},
440 { 1, 0, 1, 0, 1, 0, 1, 0},
441 { 3, -1, 3, -1, 2, -1, 6, -1},
442 {-1, -1, -1, -1, -1, -1, -1, -1},
443 {-1, -1, -1, -1, -1, -1, -1, -1}},
444 {{-1, -1, -1, -1, 1, -1, -1, -1},
445 { 7, 4, 3, 5, -1, -1, -1, -1},
446 { 6, -1, -1, 1, -1, -1, -1, -1},
447 {-1, -1, -1, 5, 3, 4, 7, -1},
448 { 6, -1, -1, -1, 1, -1, -1, 6},
449 { 7, 4, 3, 5, -1, -1, -1, -1},
450 {-1, -1, -1, 1, -1, -1, -1, 6},
451 {-1, -1, -1, 5, 3, 4, 7, -1},
452 {-1, -1, -1, -1, -1, -1, -1, -1},
453 {-1, -1, -1, -1, -1, -1, -1, -1}},
454 {{-1, -1, -1, -1, 7, 3, 6, -1},
455 {-1, -1, 3, 7, 3, 6, 3, -1},
456 {-1, -1, 5, 7, 3, 6, 3, -1},
457 {-1, 6, 7, 3, 6, 7, -1, -1},
458 {-1, 7, 7, 3, 6, 1, -1, -1},
459 { 3, 7, 3, 6, 3, -1, -1, -1},
460 { 5, 6, 2, 7, 1, -1, -1, -1},
461 {-1, -1, -1, -1, -1, -1, -1, -1},
462 {-1, -1, -1, -1, -1, -1, -1, -1},
463 {-1, -1, -1, -1, -1, -1, -1, -1}},
464 {{ 5, -1, -1, -1, -1, -1, -1, 5},
465 { 5, -1, 6, 6, 6, -1, 5, -1},
466 {-1, 5, 4, -1, -1, 4, 5, -1},
467 {-1, 3, -1, -1, -1, 3, -1, -1},
468 {-1, 6, 0, -1, -1, 0, 6, -1},
469 {-1, 3, -1, -1, -1, 3, -1, -1},
470 {-1, -1, 4, -1, -1, 4, -1, -1},
471 {-1, -1, 6, 6, 6, -1, -1, -1},
472 {-1, -1, -1, -1, -1, -1, -1, -1},
473 {-1, -1, -1, -1, -1, -1, -1, -1}},
474 {{-1, 7, 0, -1, -1, 0, 7, -1},
475 { 7, -1, 0, -1, 0, -1, 7, -1},
476 { 7, 1, -1, 0, 0, -1, 1, 7},
477 { 7, 1, 2, 0, 2, 1, 7, -1},
478 { 7, 6, 3, 2, 2, 3, 6, 7},
479 { 7, -1, 3, 2, 3, -1, 7, -1},
480 {-1, 7, 7, 3, 3, 7, 7, -1},
481 {-1, -1, -1, 3, -1, -1, -1, -1},
482 {-1, -1, -1, -1, -1, -1, -1, -1},
483 {-1, -1, -1, -1, -1, -1, -1, -1}},
484 {{-1, 3, -1, 1, -1, 7, -1, 6},
485 { 5, -1, 7, -1, 7, -1, 6, -1},
486 { 6, -1, 0, -1, 5, -1, 3, -1},
487 {-1, 2, -1, 1, -1, 5, -1, -1},
488 {-1, 4, -1, 3, -1, 4, -1, -1},
489 { 2, -1, 3, -1, 2, -1, -1, -1},
490 {-1, -1, 4, -1, 6, -1, -1, -1},
491 {-1, -1, -1, 5, -1, -1, -1, -1},
492 {-1, -1, -1, -1, -1, -1, -1, -1},
493 {-1, -1, -1, -1, -1, -1, -1, -1}},
494 {{-1, -1, -1, -1, 1, -1, -1, -1},
495 {-1, -1, -1, -1, 3, -1, -1, -1},
496 { 6, 1, 3, 1, 2, 1, 4, 1},
497 {-1, -1, -1, -1, 6, -1, -1, -1},
498 {-1, -1, -1, 4, 1, -1, -1, -1},
499 {-1, -1, 1, -1, 3, -1, -1, -1},
500 {-1, -1, -1, 2, 1, -1, -1, -1},
501 {-1, -1, -1, -1, 4, -1, -1, -1},
502 {-1, -1, -1, 6, 1, -1, -1, -1},
503 {-1, -1, -1, 6, -1, -1, -1, -1}},
504 {{-1, -1, -1, 5, 4, -1, -1, -1},
505 {-1, -1, 4, 1, 0, -1, -1, -1},
506 {-1, -1, -1, 2, 3, -1, -1, -1},
507 {-1, 1, 4, -1, 2, 2, -1, -1},
508 {-1, 3, 1, 2, 5, 1, 4, -1},
509 {-1, 4, 2, -1, 0, 4, -1, -1},
510 {-1, -1, -1, -1, -1, -1, -1, -1},
511 {-1, -1, -1, -1, -1, -1, -1, -1},
512 {-1, -1, -1, -1, -1, -1, -1, -1},
513 {-1, -1, -1, -1, -1, -1, -1, -1}},
514 {{-1, -1, -1, -1, 1, -1, -1, -1},
515 {-1, -1, -1, 1, -1, -1, -1, -1},
516 {-1, 2, -1, -1, 1, -1, 5, -1},
517 { 5, -1, -1, 1, -1, -1, 0, -1},
518 {-1, 6, -1, -1, 1, -1, 4, -1},
519 {-1, 0, -1, 1, -1, 5, -1, -1},
520 {-1, -1, 5, 5, 0, 1, -1, -1},
521 {-1, -1, -1, -1, -1, -1, -1, -1},
522 {-1, -1, -1, -1, -1, -1, -1, -1},
523 {-1, -1, -1, -1, -1, -1, -1, -1}},
524 {{-1, -1, -1, 6, 3, -1, -1, -1},
525 {-1, -1, 3, 2, 6, -1, -1, -1},
526 {-1, -1, 2, 6, 3, 2, -1, -1},
527 {-1, 6, 3, 2, 6, 3, -1, -1},
528 {-1, 3, 2, 6, 3, 2, 6, -1},
529 { 2, 6, 3, 2, 6, 3, 2, -1},
530 { 6, 3, 2, 6, 3, 2, 6, 3},
531 {-1, -1, -1, -1, -1, -1, -1, -1},
532 {-1, -1, -1, -1, -1, -1, -1, -1},
533 {-1, -1, -1, -1, -1, -1, -1, -1}},
534 {{ 6, 6, 6, 6, 6, 6, 6, 6},
535 { 4, -1, -1, -1, -1, -1, -1, -1},
536 {-1, 3, 2, 5, 7, 6, 4, 3},
537 {-1, 5, -1, -1, -1, -1, -1, -1},
538 {-1, -1, 7, 6, 4, 3, 2, 5},
539 {-1, -1, 4, -1, -1, -1, -1, -1},
540 {-1, -1, -1, 3, 2, 5, 7, 6},
541 {-1, -1, -1, -1, -1, -1, -1, -1},
542 {-1, -1, -1, -1, -1, -1, -1, -1},
543 {-1, -1, -1, -1, -1, -1, -1, -1}},
544 {{ 1, -1, 7, -1, -1, 6, -1, 2},
545 { 6, -1, 1, -1, 6, 1, 3, -1},
546 {-1, 4, -1, 7, 2, -1, 7, -1},
547 { 2, 7, -1, -1, -1, 4, -1, -1},
548 { 6, -1, 3, 5, 0, 2, -1, 7},
549 { 1, -1, -1, -1, -1, -1, 1, -1},
550 {-1, 1, 4, 5, 7, 5, 1, -1},
551 {-1, -1, -1, -1, -1, -1, -1, -1},
552 {-1, -1, -1, -1, -1, -1, -1, -1},
553 {-1, -1, -1, -1, -1, -1, -1, -1}},
554 {{ 6, 6, 6, -1, -1, 6, 6, 6},
555 {-1, -1, 6, -1, 6, -1, -1, -1},
556 {-1, -1, 2, 3, 3, 2, -1, -1},
557 {-1, 3, -1, 5, -1, 3, -1, -1},
558 {-1, -1, 5, 3, 3, 5, -1, -1},
559 {-1, -1, 6, 1, 6, -1, -1, -1},
560 {-1, 4, 2, -1, -1, 2, 4, -1},
561 {-1, -1, -1, -1, -1, -1, -1, -1},
562 {-1, -1, -1, -1, -1, -1, -1, -1},
563 {-1, -1, -1, -1, -1, -1, -1, -1}},
564 {{-1, -1, -1, 5, 5, -1, -1, -1},
565 {-1, -1, 5, -1, -1, -1, -1, -1},
566 {-1, 3, 4, 6, 6, -1, -1, 5},
567 { 3, 3, 4, 6, 5, -1, 5, -1},
568 { 3, 2, 3, 6, 6, 5, 5, -1},
569 { 3, 3, 4, 6, 5, -1, 5, -1},
570 {-1, 3, 4, 6, 6, -1, -1, 5},
571 {-1, -1, 5, -1, -1, -1, -1, -1},
572 {-1, -1, -1, 5, 5, -1, -1, -1},
573 {-1, -1, -1, -1, -1, -1, -1, -1}},
574 {{ 1, -1, -1, -1, -1, -1, -1, 1},
575 { 1, -1, 2, 2, 2, -1, 1, -1},
576 {-1, 1, 2, 3, 3, 2, 1, -1},
577 { 6, 2, 3, -1, 3, 2, 6, -1},
578 { 6, 2, 3, -1, -1, 3, 2, 6},
579 { 6, 2, 3, -1, 3, 2, 6, -1},
580 { 3, 3, 3, 7, 7, 3, 3, 3},
581 { 0, 5, 0, 2, 0, 5, 0, -1},
582 {-1, -1, -1, -1, -1, -1, -1, -1},
583 {-1, -1, -1, -1, -1, -1, -1, -1}},
584 {{-1, -1, 7, 7, 7, -1, -1, -1},
585 {-1, 7, 2, 2, 7, -1, -1, -1},
586 {-1, 7, 5, 5, 5, 7, -1, -1},
587 { 7, 7, 7, 7, 7, 7, -1, -1},
588 {-1, -1, 6, -1, 6, -1, -1, -1},
589 {-1, 6, -1, -1, 6, -1, -1, -1},
590 {-1, 6, 4, 4, -1, 6, 4, 4},
591 {-1, -1, -1, -1, -1, -1, -1, -1},
592 {-1, -1, -1, -1, -1, -1, -1, -1},
593 {-1, -1, -1, -1, -1, -1, -1, -1}},
594 {{-1, 3, 3, -1, 3, 3, 3, -1},
595 { 3, 7, 5, 4, 6, 5, 3, -1},
596 { 1, 3, 3, 3, -1, 3, 3, 1},
597 { 2, 1, 2, 1, 2, 1, 2, -1},
598 { 1, 3, 3, -1, 3, 3, 3, 1},
599 { 3, 5, 6, 4, 5, 7, 3, -1},
600 { 2, 3, 3, 3, -1, 3, 3, 2},
601 { 1, 1, 2, 2, 2, 1, 1, -1},
602 {-1, -1, -1, -1, -1, -1, -1, -1},
603 {-1, -1, -1, -1, -1, -1, -1, -1}},
604 {{-1, 6, 5, -1, -1, -1, -1, -1},
605 { 3, 1, 3, -1, -1, -1, -1, -1},
606 {-1, 5, 6, -1, -1, -1, -1, -1},
607 {-1, -1, 5, 3, -1, -1, -1, -1},
608 {-1, -1, 6, 1, 6, -1, -1, -1},
609 {-1, -1, 3, 5, -1, -1, -1, -1},
610 {-1, -1, -1, -1, 3, 6, -1, -1},
611 {-1, -1, -1, 5, 6, 5, -1, -1},
612 {-1, -1, -1, -1, 6, 3, -1, -1},
613 {-1, -1, -1, -1, -1, -1, -1, -1}},
614 {{ 6, 3, 7, 4, 5, 1, 6, 3},
615 { 5, 1, 6, 3, 7, 4, 5, -1},
616 { 6, 3, 7, 4, 5, 1, 6, 3},
617 {-1, -1, -1, -1, -1, -1, -1, -1},
618 {-1, -1, -1, -1, -1, -1, -1, -1},
619 {-1, -1, -1, -1, -1, -1, -1, -1},
620 {-1, -1, -1, -1, -1, -1, -1, -1},
621 {-1, -1, -1, -1, -1, -1, -1, -1},
622 {-1, -1, -1, -1, -1, -1, -1, -1},
623 {-1, -1, -1, -1, -1, -1, -1, -1}},
624 {{-1, -1, -1, -1, -1, -1, 4, 4},
625 {-1, -1, 7, 7, 7, 4, 4, -1},
626 {-1, -1, -1, -1, -1, -1, 4, 4},
627 {-1, 1, -1, -1, -1, 7, -1, -1},
628 {-1, 1, 1, -1, -1, 7, -1, -1},
629 { 3, 3, 3, -1, 7, -1, -1, -1},
630 { 3, -1, 2, 3, 3, 3, -1, 3},
631 {-1, 2, -1, 3, -1, 3, 3, -1},
632 {-1, 2, -1, -1, -1, -1, -1, -1},
633 {-1, -1, -1, -1, -1, -1, -1, -1}},
634 {{-1, -1, 4, -1, -1, -1, -1, -1},
635 {-1, 7, 4, -1, -1, -1, -1, -1},
636 {-1, -1, 7, 4, -1, -1, -1, -1},
637 {-1, 4, 7, 4, -1, -1, -1, -1},
638 { 1, 1, 1, 1, 1, 1, 1, -1},
639 { 1, 2, 1, 2, 1, 1, -1, -1},
640 { 2, 2, 2, 2, 2, 2, 2, 2},
641 {-1, -1, -1, -1, -1, -1, -1, -1},
642 {-1, -1, -1, -1, -1, -1, -1, -1},
643 {-1, -1, -1, -1, -1, -1, -1, -1}},
644 {{ 0, -1, -1, -1, -1, -1, -1, 6},
645 { 6, 1, 4, 3, 7, 5, 0, -1},
646 { 0, -1, -1, -1, -1, -1, -1, 6},
647 { 6, 1, 4, 3, 7, 5, 0, -1},
648 { 0, -1, -1, -1, -1, -1, -1, 6},
649 { 6, 1, 4, 3, 7, 5, 0, -1},
650 {-1, -1, -1, -1, -1, -1, -1, -1},
651 {-1, -1, -1, -1, -1, -1, -1, -1},
652 {-1, -1, -1, -1, -1, -1, -1, -1},
653 {-1, -1, -1, -1, -1, -1, -1, -1}},
654 {{ 3, 3, 4, 6, 6, 4, 3, 3},
655 { 0, 3, 4, 6, 4, 3, 1, -1},
656 { 5, 1, 3, 4, 4, 3, 0, 1},
657 { 0, 1, 3, 4, 3, 1, 0, -1},
658 { 2, 1, 6, 3, 3, 0, 0, 1},
659 { 0, 3, 4, 3, 6, 1, 5, -1},
660 { 6, 1, 2, 6, 4, 0, 0, 2},
661 {-1, -1, -1, -1, -1, -1, -1, -1},
662 {-1, -1, -1, -1, -1, -1, -1, -1},
663 {-1, -1, -1, -1, -1, -1, -1, -1}},
664 {{ 6, 6, -1, -1, -1, -1, 4, 4},
665 { 4, 0, -1, -1, -1, 3, 6, -1},
666 { 0, 6, -1, -1, -1, -1, 4, 2},
667 { 7, -1, -1, -1, -1, -1, 7, -1},
668 { 4, 4, -1, -1, -1, -1, 5, 6},
669 { 6, 4, 7, 7, 5, 6, 4, -1},
670 {-1, 7, 6, 4, 6, 4, 7, -1},
671 {-1, 0, -1, 7, -1, 7, -1, -1},
672 {-1, -1, -1, -1, -1, -1, -1, -1},
673 {-1, -1, -1, -1, -1, -1, -1, -1}},
674 {{-1, 5, -1, -1, -1, -1, 4, -1},
675 {-1, 5, -1, -1, -1, 4, -1, -1},
676 {-1, -1, 5, 6, 6, 4, -1, -1},
677 {-1, -1, 2, -1, 2, -1, -1, -1},
678 { 0, 0, 6, -1, -1, 6, 1, 1},
679 {-1, -1, 2, -1, 2, -1, -1, -1},
680 {-1, -1, 7, 6, 6, 3, -1, -1},
681 {-1, 7, -1, -1, -1, 3, -1, -1},
682 {-1, 7, -1, -1, -1, -1, 3, -1},
683 {-1, -1, -1, -1, -1, -1, -1, -1}},
684 {{-1, 6, -1, -1, -1, -1, 2, -1},
685 { 1, 7, 1, 1, 1, 3, 1, -1},
686 {-1, -1, 4, 1, 1, 4, -1, -1},
687 {-1, 1, 3, 1, 7, 1, -1, -1},
688 {-1, -1, -1, 2, 6, -1, -1, -1},
689 {-1, -1, 1, 5, 1, -1, -1, -1},
690 {-1, -1, -1, -1, -1, -1, -1, -1},
691 {-1, -1, -1, -1, -1, -1, -1, -1},
692 {-1, -1, -1, -1, -1, -1, -1, -1},
693 {-1, -1, -1, -1, -1, -1, -1, -1}},
694 {{ 7, 7, 7, 7, 7, 7, 7, 7},
695 { 7, -1, -1, -1, -1, -1, 7, -1},
696 { 7, -1, -1, 2, 0, 5, 2, 2},
697 { 7, -1, -1, -1, 0, 3, 6, -1},
698 { 7, -1, -1, -1, -1, -1, 4, 0},
699 { 5, 5, -1, -1, -1, -1, -1, -1},
700 { 4, 3, 6, 2, -1, -1, -1, -1},
701 { 0, 2, 0, 4, -1, -1, -1, -1},
702 {-1, -1, -1, -1, -1, -1, -1, -1},
703 {-1, -1, -1, -1, -1, -1, -1, -1}},
704 {{-1, -1, 1, -1, -1, 1, -1, -1},
705 {-1, 4, -1, -1, 5, -1, -1, -1},
706 {-1, 7, -1, -1, 1, 1, 1, -1},
707 { 6, -1, -1, -1, -1, 7, -1, -1},
708 { 1, 1, 1, 1, -1, 4, -1, -1},
709 {-1, -1, 5, -1, -1, -1, -1, -1},
710 {-1, -1, 0, -1, -1, -1, -1, -1},
711 {-1, 3, -1, -1, -1, -1, -1, -1},
712 {-1, 1, -1, -1, -1, -1, -1, -1},
713 {-1, -1, -1, -1, -1, -1, -1, -1}},
714 {{-1, 7, 7, -1, -1, 7, 7, -1},
715 { 6, -1, 4, -1, 4, -1, 6, -1},
716 { 5, -1, -1, 3, 3, -1, -1, 5},
717 { 6, -1, -1, -1, -1, -1, 6, -1},
718 {-1, 7, -1, -1, -1, -1, 7, -1},
719 {-1, 4, -1, -1, -1, 4, -1, -1},
720 {-1, -1, 3, -1, -1, 3, -1, -1},
721 {-1, -1, 2, -1, 2, -1, -1, -1},
722 {-1, -1, -1, 5, 5, -1, -1, -1},
723 {-1, -1, -1, -1, -1, -1, -1, -1}},
724 {{-1, 0, 0, -1, -1, 0, 0, -1},
725 { 7, 4, 6, 6, 6, 4, 3, -1},
726 { 5, 6, 6, 6, 2, 6, 6, 3},
727 { 7, 4, 6, 6, 6, 4, 3, -1},
728 {-1, 0, 0, -1, -1, 0, 0, -1},
729 {-1, -1, -1, -1, -1, -1, -1, -1},
730 {-1, -1, -1, -1, -1, -1, -1, -1},
731 {-1, -1, -1, -1, -1, -1, -1, -1},
732 {-1, -1, -1, -1, -1, -1, -1, -1},
733 {-1, -1, -1, -1, -1, -1, -1, -1}},
734 {{-1, -1, -1, -1, -1, 7, 7, 7},
735 {-1, -1, -1, -1, 2, 7, 7, -1},
736 {-1, 0, 7, 7, 7, -1, 7, 7},
737 { 6, 7, 7, 7, -1, -1, -1, -1},
738 { 6, -1, -1, -1, 7, 7, 7, 7},
739 { 6, -1, -1, -1, -1, -1, -1, -1},
740 { 4, 2, 2, 2, 4, -1, 3, -1},
741 { 4, 4, 4, 4, 3, 3, 3, -1},
742 {-1, -1, -1, -1, -1, -1, -1, -1},
743 {-1, -1, -1, -1, -1, -1, -1, -1}},
744 {{ 4, -1, -1, 7, -1, 6, -1, 7},
745 { 7, 6, 7, -1, -1, 7, 4, -1},
746 {-1, -1, 7, -1, -1, 7, -1, -1},
747 {-1, 0, 0, 0, 0, 0, 3, -1},
748 {-1, -1, 0, 2, 2, 0, 6, 4},
749 {-1, -1, 0, 0, 0, 1, 3, -1},
750 {-1, -1, -1, 0, 0, -1, 3, 4},
751 {-1, -1, -1, 6, -1, 5, 6, -1},
752 {-1, -1, -1, -1, -1, -1, 1, 0},
753 {-1, -1, -1, -1, -1, -1, -1, -1}},
754 {{-1, 5, -1, -1, -1, -1, 5, -1},
755 { 0, -1, -1, 0, -1, -1, 0, -1},
756 { 0, 0, 0, 2, 2, 0, 0, 0},
757 { 0, -1, -1, 0, -1, -1, 0, -1},
758 {-1, 7, -1, 3, -1, -1, 7, -1},
759 {-1, -1, 3, 6, -1, -1, -1, -1},
760 {-1, -1, -1, 6, -1, -1, -1, -1},
761 {-1, 3, 6, -1, -1, -1, -1, -1},
762 {-1, 3, -1, -1, -1, -1, -1, -1},
763 {-1, -1, -1, -1, -1, -1, -1, -1}},
764 {{-1, -1, -1, 6, 5, -1, -1, -1},
765 {-1, -1, 2, 6, 3, -1, -1, -1},
766 {-1, -1, 5, 4, 7, 1, -1, -1},
767 {-1, 6, 2, 2, 3, 4, -1, -1},
768 {-1, -1, 3, 7, 3, 6, -1, -1},
769 {-1, -1, 1, 3, 2, -1, -1, -1},
770 {-1, -1, -1, 4, 5, -1, -1, -1},
771 {-1, -1, -1, 4, -1, -1, -1, -1},
772 {-1, -1, -1, -1, -1, -1, -1, -1},
773 {-1, -1, -1, -1, -1, -1, -1, -1}},
774 {{ 7, 7, -1, 2, 2, -1, 6, 6},
775 { 6, -1, -1, 6, -1, -1, 3, -1},
776 { 2, -1, -1, 1, -1, -1, 2, -1},
777 { 5, -1, -1, 3, -1, -1, 2, -1},
778 { 1, -1, -1, 2, -1, -1, 1, -1},
779 { 5, -1, -1, 2, -1, -1, 2, -1},
780 { 6, -1, -1, 1, -1, -1, 7, -1},
781 { 5, -1, -1, 5, -1, -1, 4, -1},
782 {-1, -1, -1, -1, -1, -1, -1, -1},
783 {-1, -1, -1, -1, -1, -1, -1, -1}},
784 {{-1, -1, -1, 6, 6, -1, -1, -1},
785 {-1, 0, 4, 4, 4, 0, -1, -1},
786 {-1, -1, -1, 6, 6, -1, -1, -1},
787 {-1, -1, 2, 7, 2, -1, -1, -1},
788 {-1, -1, -1, 6, 6, -1, -1, -1},
789 {-1, 0, 5, 5, 5, 0, -1, -1},
790 {-1, -1, -1, 3, 3, -1, -1, -1},
791 {-1, -1, -1, -1, -1, -1, -1, -1},
792 {-1, -1, -1, -1, -1, -1, -1, -1},
793 {-1, -1, -1, -1, -1, -1, -1, -1}},
794 {{-1, -1, 4, 1, 3, -1, -1, -1},
795 {-1, 1, -1, -1, 1, -1, -1, -1},
796 {-1, -1, 4, 1, 3, 4, 1, -1},
797 {-1, 1, 3, 4, -1, -1, 4, -1},
798 {-1, 3, -1, -1, 3, 4, 1, -1},
799 {-1, 1, 3, 4, 1, 3, -1, -1},
800 {-1, -1, 4, 1, -1, -1, -1, -1},
801 {-1, -1, -1, -1, -1, -1, -1, -1},
802 {-1, -1, -1, -1, -1, -1, -1, -1},
803 {-1, -1, -1, -1, -1, -1, -1, -1}},
804 {{-1, 6, 4, -1, 3, 2, 5, -1},
805 { 0, -1, -1, -1, -1, -1, 1, -1},
806 {-1, 2, 3, 5, -1, 4, 6, -1},
807 { 0, -1, -1, -1, -1, -1, 1, -1},
808 {-1, 4, 6, -1, 2, 5, 3, -1},
809 { 0, -1, -1, -1, -1, -1, 1, -1},
810 {-1, 5, 2, 3, -1, 4, 6, -1},
811 {-1, -1, -1, -1, -1, -1, -1, -1},
812 {-1, -1, -1, -1, -1, -1, -1, -1},
813 {-1, -1, -1, -1, -1, -1, -1, -1}},
814 {{-1, -1, -1, 6, 6, -1, -1, -1},
815 {-1, -1, 7, 6, 4, -1, -1, -1},
816 {-1, 2, 1, 7, 4, 1, 3, -1},
817 { 2, 1, 1, 1, 1, 1, 3, -1},
818 {-1, 2, 2, 2, 3, 3, 3, -1},
819 {-1, -1, -1, 5, -1, -1, -1, -1},
820 {-1, -1, -1, 2, 3, -1, -1, -1},
821 {-1, -1, -1, 5, -1, -1, -1, -1},
822 {-1, -1, 2, 2, 3, 3, -1, -1},
823 {-1, -1, -1, -1, -1, -1, -1, -1}},
824 {{ 4, -1, 5, -1, -1, 3, -1, 6},
825 { 2, -1, 3, -1, 2, -1, 4, -1},
826 { 4, -1, -1, 1, 0, -1, -1, 6},
827 { 6, -1, 2, 3, 5, -1, 4, -1},
828 { 4, -1, -1, 0, 1, -1, -1, 6},
829 { 2, -1, 5, -1, 3, -1, 4, -1},
830 { 4, -1, 3, -1, -1, 2, -1, 6},
831 { 6, -1, -1, -1, -1, -1, 4, -1},
832 {-1, -1, -1, -1, -1, -1, -1, -1},
833 {-1, -1, -1, -1, -1, -1, -1, -1}},
834 {{ 2, 6, 0, 5, 5, 1, 3, 4},
835 { 1, -1, -1, 2, -1, -1, 0, -1},
836 { 4, -1, -1, 3, 6, -1, -1, 2},
837 {-1, -1, -1, 0, -1, -1, -1, -1},
838 {-1, -1, -1, 1, 4, -1, -1, -1},
839 {-1, -1, -1, 2, -1, -1, -1, -1},
840 {-1, -1, -1, 6, 3, -1, -1, -1},
841 {-1, -1, -1, 5, -1, -1, -1, -1},
842 {-1, -1, -1, 4, 1, -1, -1, -1},
843 {-1, -1, -1, -1, -1, -1, -1, -1}},
844 {{-1, -1, -1, -1, 5, 1, 1, 3},
845 { 0, 5, 1, 0, 5, 3, 3, -1},
846 { 5, 1, 0, 5, 1, 0, 5, 1},
847 { 0, 5, 1, 0, 5, 1, 6, -1},
848 {-1, -1, -1, -1, 1, 6, 5, 1},
849 {-1, -1, -1, -1, 5, 1, 6, -1},
850 {-1, -1, -1, -1, 1, 0, 5, 1},
851 {-1, -1, -1, -1, 5, 1, 0, -1},
852 {-1, -1, -1, -1, -1, -1, -1, -1},
853 {-1, -1, -1, -1, -1, -1, -1, -1}},
854 {{-1, 0, 7, 3, -1, -1, 2, 2},
855 {-1, 0, 7, 3, -1, -1, 2, -1},
856 {-1, 0, 7, 3, -1, -1, 2, 2},
857 {-1, 0, 7, 3, -1, 3, 1, -1},
858 {-1, 0, 7, 3, -1, 6, 4, 5},
859 {-1, 0, 7, 3, -1, 7, 0, -1},
860 {-1, 0, 7, 3, -1, 2, 3, 4},
861 {-1, 0, 7, 3, -1, 5, 6, -1},
862 {-1, -1, -1, -1, -1, 7, 0, 1},
863 {-1, -1, -1, -1, -1, -1, -1, -1}},
864 {{-1, -1, -1, 7, 7, 7, 7, -1},
865 { 3, 4, 5, -1, -1, -1, 7, -1},
866 { 2, -1, -1, -1, -1, -1, -1, 3},
867 { 7, -1, -1, -1, -1, -1, 4, -1},
868 { 7, -1, -1, -1, 3, 4, 5, 6},
869 { 7, -1, -1, 2, 0, 1, 2, -1},
870 { 6, -1, -1, -1, 3, 4, 5, 6},
871 { 0, 1, -1, -1, -1, -1, -1, -1},
872 { 2, 3, 4, -1, -1, -1, -1, -1},
873 { 5, 6, 0, -1, -1, -1, -1, -1}},
874 {{-1, 7, -1, -1, -1, -1, 2, -1},
875 { 1, 1, -1, -1, -1, 3, 3, -1},
876 {-1, 2, -1, -1, -1, -1, 4, -1},
877 { 3, 3, -1, -1, -1, 5, 5, -1},
878 {-1, 4, -1, -1, -1, -1, 6, -1},
879 { 5, 5, -1, -1, -1, 1, 1, -1},
880 {-1, 6, -1, -1, -1, -1, 7, -1},
881 {-1, -1, -1, -1, -1, -1, -1, -1},
882 {-1, -1, -1, -1, -1, -1, -1, -1},
883 {-1, -1, -1, -1, -1, -1, -1, -1}},
884 {{-1, 4, -1, -1, -1, -1, 4, -1},
885 { 2, -1, -1, 1, -1, -1, 2, -1},
886 { 5, -1, -1, 0, 0, -1, -1, 5},
887 { 5, -1, -1, 1, -1, -1, 6, -1},
888 {-1, 4, 2, 7, 7, 5, 4, -1},
889 {-1, -1, -1, 6, -1, -1, -1, -1},
890 {-1, -1, -1, 3, 3, -1, -1, -1},
891 {-1, -1, -1, 7, -1, -1, -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, 2, 3, 4, -1},
895 { 2, -1, -1, 3, 0, 4, -1, -1},
896 { 4, -1, -1, 2, 3, 1, -1, -1},
897 { 3, -1, 4, 3, 0, -1, -1, -1},
898 { 4, -1, -1, 2, 5, 1, -1, -1},
899 { 3, -1, 4, 5, 0, 4, -1, -1},
900 {-1, -1, -1, -1, -1, -1, -1, -1},
901 {-1, -1, -1, -1, -1, -1, -1, -1},
902 {-1, -1, -1, -1, -1, -1, -1, -1},
903 {-1, -1, -1, -1, -1, -1, -1, -1}},
904 {{ 2, -1, -1, 1, 1, -1, -1, 2},
905 { 2, -1, 3, 3, 3, -1, 2, -1},
906 {-1, 2, -1, 4, 4, -1, 2, -1},
907 {-1, 7, 7, 0, 7, 7, -1, -1},
908 {-1, -1, -1, 4, 4, -1, -1, -1},
909 {-1, -1, 5, 7, 5, -1, -1, -1},
910 { 6, 3, 2, 6, 4, 2, 3, 6},
911 { 5, -1, -1, -1, -1, -1, 1, -1},
912 {-1, -1, -1, -1, -1, -1, -1, -1},
913 {-1, -1, -1, -1, -1, -1, -1, -1}},
914 {{ 4, 2, 3, 5, 7, 1, 3, 6},
915 { 1, -1, -1, 1, -1, -1, 1, -1},
916 { 3, 0, 1, 3, 2, 4, 3, 5},
917 { 4, -1, -1, 4, -1, -1, 4, -1},
918 {-1, 5, -1, -1, 5, -1, -1, 5},
919 { 0, 3, 2, 0, 4, 5, 0, -1},
920 {-1, 6, -1, -1, 6, -1, -1, 6},
921 { 7, -1, -1, 7, -1, -1, 7, -1},
922 {-1, -1, -1, -1, -1, -1, -1, -1},
923 {-1, -1, -1, -1, -1, -1, -1, -1}},
924 {{-1, 5, 4, -1, 1, 1, -1, -1},
925 { 5, -1, 4, 1, -1, 1, -1, -1},
926 { 0, -1, -1, -1, -1, -1, 0, -1},
927 { 0, 6, 4, -1, -1, 4, 2, -1},
928 {-1, 4, 3, 5, 2, 6, 3, 6},
929 {-1, 2, 6, -1, -1, 5, 4, -1},
930 {-1, -1, -1, -1, -1, -1, -1, -1},
931 {-1, -1, -1, -1, -1, -1, -1, -1},
932 {-1, -1, -1, -1, -1, -1, -1, -1},
933 {-1, -1, -1, -1, -1, -1, -1, -1}},
934 {{-1, -1, -1, 6, 6, -1, -1, -1},
935 {-1, -1, 5, 5, 4, -1, -1, -1},
936 {-1, -1, 1, 6, 6, 4, -1, -1},
937 {-1, 1, 7, 2, 5, 3, -1, -1},
938 {-1, 2, 7, 2, 1, 5, 3, -1},
939 { 2, 1, 3, 1, 4, 2, 7, -1},
940 {-1, 3, 1, 3, 4, 2, 7, -1},
941 {-1, 3, 5, 5, 6, 6, -1, -1},
942 {-1, -1, -1, -1, -1, -1, -1, -1},
943 {-1, -1, -1, -1, -1, -1, -1, -1}},
944 {{-1, -1, 7, 3, -1, -1, -1, -1},
945 {-1, 1, 7, 6, -1, -1, -1, -1},
946 {-1, 3, 7, 5, 1, 5, -1, -1},
947 { 7, 7, 0, 2, 4, 0, 4, -1},
948 { 7, 1, 4, 6, 5, 6, 5, 7},
949 { 1, 7, 7, 1, 7, 7, 1, -1},
950 {-1, -1, -1, -1, -1, -1, -1, -1},
951 {-1, -1, -1, -1, -1, -1, -1, -1},
952 {-1, -1, -1, -1, -1, -1, -1, -1},
953 {-1, -1, -1, -1, -1, -1, -1, -1}},
954 {{-1, -1, 1, -1, -1, 1, -1, -1},
955 {-1, 5, 6, 1, 5, 6, -1, -1},
956 {-1, 1, 1, 2, 2, 1, 1, -1},
957 { 4, 7, 1, 0, 1, 7, 4, -1},
958 {-1, 3, 7, 5, 7, 5, 3, -1},
959 {-1, 1, 1, 1, 1, 1, -1, -1},
960 {-1, -1, -1, -1, -1, -1, -1, -1},
961 {-1, -1, -1, -1, -1, -1, -1, -1},
962 {-1, -1, -1, -1, -1, -1, -1, -1},
963 {-1, -1, -1, -1, -1, -1, -1, -1}},
964 {{ 4, -1, -1, -1, 5, -1, -1, 4},
965 { 6, 6, 7, 6, -1, 4, 5, -1},
966 { 4, 2, 7, 5, 2, 2, 6, 4},
967 {-1, -1, 4, 1, -1, 5, 2, -1},
968 {-1, 5, 2, 7, 7, -1, 7, 4},
969 { 4, 6, 5, 4, -1, 4, 2, -1},
970 {-1, -1, -1, 4, -1, 4, 1, -1},
971 { 0, 0, 0, 5, -1, -1, -1, -1},
972 {-1, -1, -1, -1, 0, 0, 0, 0},
973 {-1, -1, -1, -1, -1, -1, -1, -1}},
974 {{ 1, -1, -1, -1, 0, 0, -1, -1},
975 { 2, -1, -1, 0, 1, 0, -1, -1},
976 { 3, -1, -1, 0, 2, 2, 0, -1},
977 { 4, -1, 0, 1, 1, 1, 0, -1},
978 { 5, -1, -1, 0, 4, 4, 0, -1},
979 { 6, -1, -1, 4, 4, 4, -1, -1},
980 { 7, -1, -1, -1, 4, 4, -1, -1},
981 {-1, -1, -1, 0, 1, 0, -1, -1},
982 {-1, -1, -1, 0, 1, 1, 0, -1},
983 {-1, -1, -1, -1, -1, -1, -1, -1}},
984 {{-1, -1, 3, -1, -1, 1, 7, -1},
985 {-1, 7, 4, -1, -1, 4, 3, -1},
986 { 1, -1, -1, 0, 2, 0, -1, -1},
987 { 5, 4, -1, 3, -1, -1, -1, -1},
988 { 4, -1, 3, 6, 1, 1, 6, -1},
989 {-1, 1, -1, -1, 4, -1, 1, -1},
990 {-1, 7, 5, -1, -1, -1, 3, -1},
991 {-1, -1, 3, -1, -1, -1, -1, -1},
992 {-1, -1, -1, -1, -1, -1, -1, -1},
993 {-1, -1, -1, -1, -1, -1, -1, -1}},
994 {{ 1, -1, -1, -1, 1, -1, -1, -1},
995 { 2, -1, -1, -1, 2, -1, -1, -1},
996 {-1, 3, -1, -1, 3, 3, -1, -1},
997 {-1, 4, -1, 4, -1, 4, -1, -1},
998 {-1, 5, -1, -1, 5, 5, -1, -1},
999 { 6, -1, -1, 7, 1, 7, -1, -1},
1000 { 7, -1, -1, -1, 6, 6, -1, -1},
1001 {-1, -1, -1, -1, -1, -1, -1, -1},
1002 {-1, -1, -1, -1, -1, -1, -1, -1},
1003 {-1, -1, -1, -1, -1, -1, -1, -1}},
1004 {{ 2, -1, -1, 6, -1, 2, 5, 1},
1005 { 5, -1, 4, -1, 4, -1, 4, -1},
1006 { 6, -1, -1, 3, -1, -1, -1, 3},
1007 { 4, 2, 0, -1, -1, -1, 5, -1},
1008 {-1, -1, -1, 6, -1, 3, 6, -1},
1009 {-1, -1, 5, -1, 5, -1, -1, -1},
1010 {-1, -1, -1, 3, -1, 4, 2, 5},
1011 {-1, -1, -1, -1, -1, -1, -1, -1},
1012 {-1, -1, -1, -1, -1, -1, -1, -1},
1013 {-1, -1, -1, -1, -1, -1, -1, -1}},
1014 {{ 6, -1, -1, -1, 4, -1, -1, 3},
1015 { 0, 3, -1, -1, 6, -1, 0, -1},
1016 {-1, -1, 7, -1, 1, -1, 3, -1},
1017 { 7, -1, 4, 7, -1, 2, -1, -1},
1018 { 5, 2, 3, 2, 1, 6, -1, 3},
1019 {-1, -1, 0, 4, 3, 5, 4, -1},
1020 {-1, 7, 6, -1, -1, 0, -1, -1},
1021 { 4, 3, -1, -1, -1, 4, 2, -1},
1022 { 0, -1, -1, -1, -1, -1, 6, -1},
1023 {-1, -1, -1, -1, -1, -1, -1, -1}},
1024 {{ 6, 1, 2, 5, 1, 6, 3, 0},
1025 {-1, -1, -1, -1, -1, -1, 4, -1},
1026 { 0, 5, 2, 7, 1, 6, 2, -1},
1027 { 3, -1, -1, -1, -1, -1, -1, -1},
1028 { 6, 7, 6, 4, 0, 5, 2, 6},
1029 {-1, -1, -1, -1, -1, -1, 1, -1},
1030 { 6, 1, 4, 0, 6, 2, 3, -1},
1031 { 0, -1, -1, -1, -1, -1, -1, -1},
1032 {-1, 0, 4, 5, 3, 7, 6, 0},
1033 {-1, -1, -1, -1, -1, -1, -1, -1}},
1034 {{-1, -1, -1, 0, 1, -1, -1, -1},
1035 {-1, -1, 0, 7, 0, -1, -1, -1},
1036 {-1, -1, 1, 2, 2, 0, -1, -1},
1037 {-1, 0, 7, 0, 7, 0, -1, -1},
1038 {-1, 6, -1, 7, 7, -1, 6, -1},
1039 { 4, 1, 6, 6, 6, 4, 1, -1},
1040 {-1, 5, -1, 7, 7, -1, 5, -1},
1041 {-1, -1, -1, -1, -1, -1, -1, -1},
1042 {-1, -1, -1, -1, -1, -1, -1, -1},
1043 {-1, -1, -1, -1, -1, -1, -1, -1}},
1044 {{-1, -1, -1, 5, 6, -1, -1, -1},
1045 {-1, -1, 3, 3, 3, -1, -1, -1},
1046 {-1, -1, 7, 5, 3, 7, -1, -1},
1047 {-1, 3, -1, 6, -1, 3, -1, -1},
1048 { 2, -1, -1, 3, 7, -1, -1, 1},
1049 { 2, 2, -1, 3, -1, 1, 1, -1},
1050 {-1, 0, 2, 5, 6, 1, 0, -1},
1051 {-1, -1, -1, 3, -1, -1, -1, -1},
1052 {-1, -1, -1, 3, 7, -1, -1, -1},
1053 {-1, -1, -1, -1, -1, -1, -1, -1}},
1054 {{-1, 6, -1, -1, -1, -1, 2, -1},
1055 {-1, 2, 6, 0, 6, 0, -1, -1},
1056 {-1, 0, -1, -1, -1, -1, -1, -1},
1057 { 6, -1, -1, -1, -1, -1, -1, -1},
1058 {-1, 3, 3, 2, 0, 6, 0, 0},
1059 {-1, 6, -1, -1, -1, -1, 0, -1},
1060 {-1, -1, -1, 6, 0, 2, 6, -1},
1061 {-1, 2, 0, -1, -1, -1, -1, -1},
1062 {-1, -1, -1, -1, -1, -1, -1, -1},
1063 {-1, -1, -1, -1, -1, -1, -1, -1}},
1064 {{ 0, 7, -1, -1, -1, -1, -1, -1},
1065 { 1, 5, -1, -1, -1, -1, -1, -1},
1066 { 7, 2, 5, -1, -1, -1, -1, -1},
1067 { 6, 3, 4, -1, -1, -1, -1, -1},
1068 { 5, 5, 4, 4, -1, -1, -1, -1},
1069 { 3, 3, 5, 3, -1, -1, -1, -1},
1070 { 1, 2, 2, 5, 3, -1, -1, -1},
1071 { 1, 0, 0, 7, 6, -1, -1, -1},
1072 { 3, 3, 5, 5, 7, 6, -1, -1},
1073 {-1, -1, -1, -1, -1, -1, -1, -1}},
1074 {{-1, -1, 2, 6, 6, 2, -1, -1},
1075 {-1, 2, 1, 1, 0, 2, -1, -1},
1076 {-1, 2, 3, 2, 2, 0, 2, -1},
1077 { 2, 3, 2, 5, 2, 7, 2, -1},
1078 { 2, 4, 2, 5, 2, 7, 2, 0},
1079 { 2, 4, 2, 6, 6, 2, 0, -1},
1080 {-1, 2, 5, 2, 2, 2, 7, 2},
1081 {-1, 2, 5, 6, 6, 7, 2, -1},
1082 {-1, -1, 2, 2, 2, 2, 2, -1},
1083 {-1, -1, -1, -1, -1, -1, -1, -1}},
1084 {{-1, -1, 0, -1, -1, 0, -1, -1},
1085 { 1, 0, 0, 1, 0, 0, 1, -1},
1086 { 1, 7, 7, 5, 5, 7, 7, 1},
1087 { 3, 2, -1, 2, -1, 2, 3, -1},
1088 { 3, 7, -1, 6, 6, -1, 7, 3},
1089 { 7, -1, -1, 6, -1, -1, 7, -1},
1090 { 4, 4, 5, -1, -1, 5, 4, 4},
1091 {-1, -1, -1, -1, -1, -1, -1, -1},
1092 {-1, -1, -1, -1, -1, -1, -1, -1},
1093 {-1, -1, -1, -1, -1, -1, -1, -1}},
1094 {{-1, 6, 3, -1, -1, 3, 6, -1},
1095 { 6, -1, 2, -1, 2, -1, 6, -1},
1096 { 2, -1, 0, 1, 1, 0, -1, 2},
1097 { 5, 0, -1, 7, -1, 0, 5, -1},
1098 {-1, 5, -1, 6, 6, -1, 5, -1},
1099 { 7, 1, 4, -1, 4, 1, 7, -1},
1100 { 7, -1, 4, -1, -1, 4, -1, 7},
1101 { 2, 0, -1, -1, -1, 0, 2, -1},
1102 {-1, 2, -1, -1, -1, -1, 2, -1},
1103 {-1, -1, -1, -1, -1, -1, -1, -1}},
1104 {{ 6, 1, -1, -1, -1, -1, 4, 0},
1105 { 2, 7, 5, 5, 5, 7, 3, -1},
1106 { 6, 1, -1, -1, -1, -1, 4, 0},
1107 { 2, 5, 7, 7, 7, 5, 3, -1},
1108 { 6, 1, -1, -1, -1, -1, 4, 0},
1109 { 2, 0, 6, 6, 6, 0, 3, -1},
1110 { 6, 1, -1, -1, -1, -1, 4, 0},
1111 {-1, -1, -1, -1, -1, -1, -1, -1},
1112 {-1, -1, -1, -1, -1, -1, -1, -1},
1113 {-1, -1, -1, -1, -1, -1, -1, -1}},
1114 {{ 5, -1, -1, 1, 1, -1, -1, 5},
1115 { 5, -1, 4, -1, 4, -1, 5, -1},
1116 {-1, 2, 4, -1, -1, 4, 2, -1},
1117 { 7, 2, -1, -1, -1, 2, 7, -1},
1118 { 0, -1, 0, 4, 4, 0, -1, 0},
1119 { 7, 2, -1, -1, -1, 2, 7, -1},
1120 {-1, 2, 3, -1, -1, 3, 2, -1},
1121 { 5, -1, 3, -1, 3, -1, 5, -1},
1122 { 5, -1, -1, 6, 6, -1, -1, 5},
1123 {-1, -1, -1, -1, -1, -1, -1, -1}},
1124 {{ 2, 2, -1, -1, -1, -1, 5, 5},
1125 { 5, -1, -1, -1, -1, -1, 2, -1},
1126 { 5, -1, -1, -1, -1, -1, -1, 2},
1127 { 1, -1, 1, 5, 1, -1, 3, -1},
1128 { 5, 2, 5, 3, 1, 2, 5, 2},
1129 { 2, 0, 5, -1, 2, 0, 5, -1},
1130 {-1, 3, 7, -1, -1, 3, 7, -1},
1131 {-1, -1, 2, 0, 5, -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, -1, 1, -1, -1, -1, -1, -1},
1138 { 7, 1, 4, 3, 2, 5, 6, 0},
1139 {-1, -1, -1, -1, 1, -1, -1, -1},
1140 {-1, -1, -1, 1, 1, -1, -1, -1},
1141 {-1, -1, 1, -1, -1, -1, -1, -1},
1142 { 0, 6, 5, 2, 3, 4, 1, 7},
1143 {-1, -1, -1, -1, -1, -1, -1, -1}},
1144 {{-1, -1, 1, -1, -1, 1, -1, -1},
1145 {-1, 2, 4, -1, 2, 4, -1, -1},
1146 {-1, 2, 3, 6, 5, 3, 2, -1},
1147 {-1, 6, 5, -1, 6, 5, -1, -1},
1148 {-1, -1, -1, 7, 7, -1, -1, -1},
1149 {-1, -1, -1, 7, -1, -1, -1, -1},
1150 { 1, -1, -1, 7, 7, -1, -1, 3},
1151 { 2, -1, -1, 7, -1, -1, 2, -1},
1152 {-1, 3, 4, 5, 6, 4, 1, -1},
1153 {-1, -1, -1, -1, -1, -1, -1, -1}},
1154 {{ 1, -1, -1, 2, 2, -1, -1, 2},
1155 { 1, 3, 7, 3, 7, 4, 2, -1},
1156 {-1, 1, 6, -1, -1, 6, 2, -1},
1157 { 6, -1, 7, 3, 7, -1, 6, -1},
1158 {-1, 4, 2, -1, -1, 1, 3, -1},
1159 {-1, -1, 2, 6, 1, -1, -1, -1},
1160 {-1, 4, 3, 3, 4, 4, 3, -1},
1161 {-1, -1, -1, -1, -1, -1, -1, -1},
1162 {-1, -1, -1, -1, -1, -1, -1, -1},
1163 {-1, -1, -1, -1, -1, -1, -1, -1}},
1164 {{-1, -1, -1, 5, 6, -1, -1, -1},
1165 {-1, -1, -1, 3, -1, -1, -1, -1},
1166 {-1, -1, -1, 1, 2, -1, -1, -1},
1167 {-1, -1, -1, 4, -1, -1, -1, -1},
1168 {-1, -1, -1, 5, 7, -1, -1, -1},
1169 {-1, -1, -1, 2, -1, -1, -1, -1},
1170 { 6, 5, 4, 3, 2, 1, 7, 5},
1171 {-1, -1, -1, -1, -1, -1, -1, -1},
1172 {-1, -1, -1, -1, -1, -1, -1, -1},
1173 {-1, -1, -1, -1, -1, -1, -1, -1}},
1174 {{-1, 0, -1, 1, -1, 2, -1, -1},
1175 {-1, 4, -1, 5, -1, 6, -1, -1},
1176 {-1, 7, -1, 0, -1, 2, -1, -1},
1177 {-1, 6, -1, 3, -1, 6, -1, -1},
1178 {-1, 1, -1, 1, -1, 2, -1, -1},
1179 {-1, 3, -1, 5, -1, 0, -1, -1},
1180 {-1, 2, -1, 4, -1, 6, -1, -1},
1181 {-1, 3, -1, 6, -1, 7, -1, -1},
1182 {-1, -1, -1, -1, -1, -1, -1, -1},
1183 {-1, -1, -1, -1, -1, -1, -1, -1}},
1184 {{ 1, 1, 2, 2, 3, 3, 4, 4},
1185 { 5, 5, 6, 7, 6, 5, 5, -1},
1186 { 6, 4, 3, 3, 2, 2, 1, 6},
1187 { 4, 6, 5, 7, 6, 3, 1, -1},
1188 {-1, -1, -1, -1, -1, -1, -1, -1},
1189 {-1, -1, -1, -1, -1, -1, -1, -1},
1190 {-1, -1, -1, -1, -1, -1, -1, -1},
1191 {-1, -1, -1, -1, -1, -1, -1, -1},
1192 {-1, -1, -1, -1, -1, -1, -1, -1},
1193 {-1, -1, -1, -1, -1, -1, -1, -1}},
1194 {{ 7, 4, -1, 1, 2, -1, 4, 7},
1195 { 5, 5, -1, 2, -1, 4, 4, -1},
1196 {-1, 5, -1, 7, 7, -1, 4, -1},
1197 { 1, 0, 6, 7, 6, 0, 2, -1},
1198 {-1, 2, -1, 5, 3, -1, 1, -1},
1199 { 1, 1, -1, -1, -1, 2, 2, -1},
1200 { 6, 1, 4, -1, -1, 4, 2, 6},
1201 { 5, 3, -1, -1, -1, 3, 5, -1},
1202 {-1, -1, -1, -1, -1, -1, -1, -1},
1203 {-1, -1, -1, -1, -1, -1, -1, -1}},
1204 {{ 1, 5, 1, 0, 0, 1, 5, 1},
1205 { 1, 2, 5, -1, 5, 2, 1, -1},
1206 { 3, 6, 1, 2, 2, 1, 6, 3},
1207 { 4, 3, 4, -1, 4, 3, 4, -1},
1208 { 3, 4, 6, 5, 5, 6, 4, 3},
1209 { 0, 2, 3, -1, 3, 2, 0, -1},
1210 { 2, 3, 1, 5, 5, 1, 3, 2},
1211 {-1, -1, -1, -1, -1, -1, -1, -1},
1212 {-1, -1, -1, -1, -1, -1, -1, -1},
1213 {-1, -1, -1, -1, -1, -1, -1, -1}},
1214 {{ 3, 0, 2, 7, 5, 7, 6, 5},
1215 { 6, -1, 1, -1, 2, -1, 1, -1},
1216 {-1, 6, 4, 0, 3, 4, 5, -1},
1217 {-1, 5, -1, 1, -1, 4, -1, -1},
1218 {-1, 7, 3, 5, 6, 5, 3, -1},
1219 { 1, -1, 2, -1, 4, -1, 2, -1},
1220 { 6, 4, 4, 6, 6, 5, 5, 1},
1221 {-1, -1, -1, -1, -1, -1, -1, -1},
1222 {-1, -1, -1, -1, -1, -1, -1, -1},
1223 {-1, -1, -1, -1, -1, -1, -1, -1}}
1226 /* the tile struct
1227 * type is the bubble number 0-7
1228 * fallx is the x axis movement for the falling bubble
1229 * fallvel is the initial upward velocity for the falling bubble
1230 * ingroup denotes a bubble that is part of a group to be removed
1231 * anchored denotes a bubble that is anchored to the ceiling
1233 struct tile {
1234 int type;
1235 int fallx;
1236 int fallvel;
1237 bool ingroup;
1238 bool anchored;
1239 bool delete;
1242 /* the highscore struct
1243 * level is the highscore level
1244 * score is the highscore score
1246 struct highscore {
1247 unsigned int level;
1248 unsigned int score;
1251 /* the game context struct
1252 * score is the current score
1253 * level is the current level
1254 * highlevel is the highest level beaten
1255 * highscores is the list of high scores
1256 * angle is the current cannon direction
1257 * shots is the number of shots fired since last compression
1258 * compress is the height of the compressor
1259 * onboardcnt is the number of unique bubbles on the playing board
1260 * onboard is the unique bubbles on the playing board
1261 * nextinq is the pointer to the next bubble in the firing queue
1262 * queue is the circular buffer of bubbles to be fired
1263 * elapsedlvl is level elapsed time in 1/100s of seconds
1264 * elapsedshot is the shot elapsed time in 1/100s of seconds
1265 * startedshot is when the current shot began
1266 * resume denotes whether to resume the currently loaded game
1267 * dirty denotes whether the high scores are out of sync with the saved file
1268 * playboard is the game playing board
1270 struct game_context {
1271 unsigned int score;
1272 unsigned int level;
1273 unsigned int highlevel;
1274 struct highscore highscores[NUM_SCORES];
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 bool resume;
1286 bool dirty;
1287 struct tile playboard[BB_HEIGHT][BB_WIDTH];
1290 static void bubbles_init(struct game_context* bb);
1291 static bool bubbles_nextlevel(struct game_context* bb);
1292 static void bubbles_getonboard(struct game_context* bb);
1293 static void bubbles_drawboard(struct game_context* bb);
1294 static int bubbles_fire(struct game_context* bb);
1295 static bool bubbles_collision(struct game_context* bb, int y, int x,
1296 int nearrow, int nearcol);
1297 static bool bubbles_ingroup(struct game_context* bb, int row, int col);
1298 static int bubbles_searchgroup(struct game_context* bb, int row, int col);
1299 static int bubbles_remove(struct game_context* bb);
1300 static void bubbles_anchored(struct game_context* bb, int row, int col);
1301 static int bubbles_fall(struct game_context* bb);
1302 static int bubbles_checklevel(struct game_context* bb);
1303 static int bubbles_recordscore(struct game_context* bb);
1304 static void bubbles_savescores(struct game_context* bb);
1305 static bool bubbles_loadgame(struct game_context* bb);
1306 static void bubbles_savegame(struct game_context* bb);
1307 static void bubbles_setcolors(void);
1308 static void bubbles_callback(void* param);
1309 static int bubbles_handlebuttons(struct game_context* bb, bool animblock,
1310 int timeout);
1311 static int bubbles(struct game_context* bb);
1313 /*****************************************************************************
1314 * bubbles_init() initializes bubbles data structures.
1315 ******************************************************************************/
1316 static void bubbles_init(struct game_context* bb) {
1317 /* seed the rand generator */
1318 rb->srand(*rb->current_tick);
1320 /* check for resumed game */
1321 if(bb->resume) {
1322 bb->resume = false;
1323 return;
1326 bb->score = 0;
1327 bubbles_nextlevel(bb);
1330 /*****************************************************************************
1331 * bubbles_nextlevel() sets up the game for the next level, returns false if
1332 * there are no more levels.
1333 ******************************************************************************/
1334 static bool bubbles_nextlevel(struct game_context* bb) {
1335 int i, j, pos;
1337 bb->level++;
1339 /* check if there are no more levels */
1340 if(bb->level > NUM_LEVELS) return false;
1342 /* set up the play board */
1343 rb->memset(bb->playboard, 0, sizeof(bb->playboard));
1344 for(i=0; i<BB_LEVEL_HEIGHT; i++) {
1345 for(j=0; j<BB_WIDTH; j++) {
1346 pos = (int)level[bb->level-1][i][j];
1347 if(pos >=0 && pos < NUM_BUBBLES) {
1348 bb->playboard[i][j].type = pos;
1349 } else {
1350 bb->playboard[i][j].type = -1;
1354 for(i=BB_LEVEL_HEIGHT; i<BB_HEIGHT; i++) {
1355 for(j=0; j<BB_WIDTH; j++) {
1356 bb->playboard[i][j].type = -1;
1360 /* fill first bubbles in shot queue */
1361 bubbles_getonboard(bb);
1362 for(i=0; i<NUM_QUEUE; i++) {
1363 bb->queue[i] = bb->onboard[rb->rand()%bb->onboardcnt];
1366 bb->angle = 0;
1367 bb->shots = 0;
1368 bb->compress = 0;
1369 bb->nextinq = 0;
1370 bb->elapsedlvl = 0;
1371 bb->elapsedshot = 0;
1373 return true;
1376 /*****************************************************************************
1377 * bubbles_getonboard() determines which bubble types are on the play board.
1378 ******************************************************************************/
1379 static void bubbles_getonboard(struct game_context* bb) {
1380 int i, j, k;
1381 bool found;
1383 bb->onboardcnt = 0;
1384 rb->memset(bb->onboard, -1, sizeof(bb->onboard));
1386 for(i=0; i<BB_HEIGHT; i++) {
1387 for(j=0; j<BB_WIDTH; j++) {
1388 if(bb->playboard[i][j].type >= 0) {
1389 found = false;
1391 for(k=0; k<bb->onboardcnt; k++) {
1392 if(bb->playboard[i][j].type == bb->onboard[k]) {
1393 found = true;
1394 break;
1398 if(!found) {
1399 bb->onboard[bb->onboardcnt] = bb->playboard[i][j].type;
1400 bb->onboardcnt++;
1403 if(bb->onboardcnt == NUM_BUBBLES) return;
1409 /*****************************************************************************
1410 * bubbles_drawboard() draws the game board to the buffer but does not update
1411 * the lcd.
1412 ******************************************************************************/
1413 static void bubbles_drawboard(struct game_context* bb) {
1414 int i, j;
1415 int w, h;
1416 int colmax, indent;
1417 int tipx, tipy;
1418 bool evenline = false;
1419 char *level = "Level";
1420 char *score = "Score";
1421 char *next = "Next";
1422 char *hurry = "HURRY!";
1423 char str[11];
1425 /* clear screen */
1426 rb->lcd_clear_display();
1428 /* draw background */
1429 #ifdef HAVE_LCD_COLOR
1430 rb->lcd_bitmap(bubbles_background, 0, 0, LCD_WIDTH, LCD_HEIGHT);
1431 #endif
1433 /* display play board */
1434 for(i=0; i<BB_HEIGHT; i++) {
1435 colmax = BB_WIDTH;
1436 if(evenline) {
1437 colmax--;
1438 indent = ROW_INDENT;
1439 } else {
1440 indent = 0;
1442 evenline = !evenline;
1444 for(j=0; j<colmax; j++) {
1445 if(bb->playboard[i][j].type >= 0 && !bb->playboard[i][j].delete) {
1446 rb->lcd_bitmap_part(bubbles_emblem,
1447 0, EMBLEM_HEIGHT*bb->playboard[i][j].type, EMBLEM_WIDTH,
1448 XOFS+indent+BUBBLE_WIDTH*j+(BUBBLE_WIDTH-EMBLEM_WIDTH)/2,
1449 ROW_HEIGHT*i+(BUBBLE_HEIGHT-EMBLEM_HEIGHT)/2+bb->compress*ROW_HEIGHT,
1450 EMBLEM_WIDTH, EMBLEM_HEIGHT);
1451 rb->lcd_set_drawmode(DRMODE_FG);
1452 rb->lcd_mono_bitmap((const unsigned char *)bubbles_bubble,
1453 XOFS+indent+BUBBLE_WIDTH*j,
1454 ROW_HEIGHT*i+bb->compress*ROW_HEIGHT,
1455 BUBBLE_WIDTH, BUBBLE_HEIGHT);
1456 rb->lcd_set_drawmode(DRMODE_SOLID);
1461 /* display bubble to be shot */
1462 rb->lcd_bitmap_part(bubbles_emblem,
1463 0, EMBLEM_HEIGHT*bb->queue[bb->nextinq], EMBLEM_WIDTH,
1464 SHOTX+(BUBBLE_WIDTH-EMBLEM_WIDTH)/2,
1465 SHOTY+(BUBBLE_HEIGHT-EMBLEM_HEIGHT)/2,
1466 EMBLEM_WIDTH, EMBLEM_HEIGHT);
1467 rb->lcd_set_drawmode(DRMODE_FG);
1468 rb->lcd_mono_bitmap((const unsigned char *)bubbles_bubble,
1469 SHOTX, SHOTY,
1470 BUBBLE_WIDTH, BUBBLE_HEIGHT);
1471 rb->lcd_set_drawmode(DRMODE_SOLID);
1473 /* display next bubble to be shot */
1474 rb->lcd_bitmap_part(bubbles_emblem,
1475 0, EMBLEM_HEIGHT*bb->queue[(bb->nextinq+1)%NUM_QUEUE], EMBLEM_WIDTH,
1476 XOFS/2-BUBBLE_WIDTH/2+(BUBBLE_WIDTH-EMBLEM_WIDTH)/2,
1477 SHOTY+(BUBBLE_HEIGHT-EMBLEM_HEIGHT)/2,
1478 EMBLEM_WIDTH, EMBLEM_HEIGHT);
1479 rb->lcd_set_drawmode(DRMODE_FG);
1480 rb->lcd_mono_bitmap((const unsigned char *)bubbles_bubble,
1481 XOFS/2-BUBBLE_WIDTH/2, SHOTY,
1482 BUBBLE_WIDTH, BUBBLE_HEIGHT);
1483 rb->lcd_set_drawmode(DRMODE_SOLID);
1485 /* draw bounding lines */
1486 #ifndef HAVE_LCD_COLOR
1487 rb->lcd_vline(XOFS-1, 0, LCD_HEIGHT);
1488 rb->lcd_vline(XOFS+BUBBLE_WIDTH*BB_WIDTH, 0, LCD_HEIGHT);
1489 #endif
1490 rb->lcd_hline(XOFS, XOFS+BUBBLE_WIDTH*BB_WIDTH-1, bb->compress*ROW_HEIGHT-1);
1491 rb->lcd_hline(XOFS, XOFS+BUBBLE_WIDTH*BB_WIDTH-1,
1492 ROW_HEIGHT*(BB_HEIGHT-2)+BUBBLE_HEIGHT);
1494 /* draw arrow */
1495 tipx = SHOTX+BUBBLE_WIDTH/2+(((sin_int(bb->angle)>>4)*BUBBLE_WIDTH*3/2)>>10);
1496 tipy = SHOTY+BUBBLE_HEIGHT/2-(((cos_int(bb->angle)>>4)*BUBBLE_HEIGHT*3/2)>>10);
1498 rb->lcd_drawline(SHOTX+BUBBLE_WIDTH/2+(((sin_int(bb->angle)>>4)*BUBBLE_WIDTH/2)>>10),
1499 SHOTY+BUBBLE_HEIGHT/2-(((cos_int(bb->angle)>>4)*BUBBLE_HEIGHT/2)>>10),
1500 tipx, tipy);
1501 xlcd_filltriangle(tipx, tipy,
1502 tipx+(((sin_int(bb->angle-135)>>4)*BUBBLE_WIDTH/3)>>10),
1503 tipy-(((cos_int(bb->angle-135)>>4)*BUBBLE_HEIGHT/3)>>10),
1504 tipx+(((sin_int(bb->angle+135)>>4)*BUBBLE_WIDTH/3)>>10),
1505 tipy-(((cos_int(bb->angle+135)>>4)*BUBBLE_HEIGHT/3)>>10));
1507 /* draw text */
1508 rb->lcd_getstringsize(level, &w, &h);
1509 rb->lcd_putsxy(XOFS/2-w/2, 2, level);
1511 rb->snprintf(str, 4, "%d", bb->level);
1512 rb->lcd_getstringsize(str, &w, &h);
1513 rb->lcd_putsxy(XOFS/2-w/2, 11, str);
1515 rb->lcd_getstringsize(score, &w, &h);
1516 rb->lcd_putsxy(XOFS/2-w/2, 29, score);
1518 rb->snprintf(str, 10, "%d", bb->score);
1519 rb->lcd_getstringsize(str, &w, &h);
1520 rb->lcd_putsxy(XOFS/2-w/2, 38, str);
1522 rb->lcd_getstringsize(next, &w, &h);
1523 rb->lcd_putsxy(XOFS/2-w/2, SHOTY-9, next);
1525 if(bb->elapsedshot >= (MAX_SHOTTIME*7)/10) {
1526 rb->lcd_getstringsize(hurry, &w, &h);
1527 rb->lcd_putsxy(LCD_WIDTH/2-w/2, LCD_HEIGHT/2-h/2, hurry);
1531 /*****************************************************************************
1532 * bubbles_fire() fires the current bubble, reloads the cannon, attaches
1533 * bubble to playboard, removes appropriate bubbles, and advances the
1534 * the compressor.
1535 ******************************************************************************/
1536 static int bubbles_fire(struct game_context* bb) {
1537 int bubblecur;
1538 long shotxinc, shotyinc;
1539 long shotxofs, shotyofs;
1540 int shotxdirec = 1;
1541 long tempxofs, tempyofs;
1542 int nearrow, nearcol;
1543 int lastrow = BB_HEIGHT-1;
1544 int lastcol = (BB_WIDTH-1)/2;
1545 int buttonres;
1546 long lasttick, currenttick;
1548 /* get current bubble */
1549 bubblecur = bb->queue[bb->nextinq];
1550 shotxinc = ((sin_int(bb->angle)>>4)*BUBBLE_WIDTH)/3;
1551 shotyinc = ((-1*(cos_int(bb->angle)>>4))*BUBBLE_HEIGHT)/3;
1552 shotxofs = shotyofs = 0;
1554 /* advance the queue */
1555 bb->queue[bb->nextinq] = bb->onboard[rb->rand()%bb->onboardcnt];
1556 bb->nextinq = (bb->nextinq+1)%NUM_QUEUE;
1557 bubbles_drawboard(bb);
1558 rb->lcd_update_rect(0, 0, XOFS, LCD_HEIGHT);
1560 /* move the bubble across the play board */
1561 lasttick = *rb->current_tick;
1563 while(true) {
1564 /* move the bubble one step */
1565 shotyofs += shotyinc;
1566 shotxofs += shotxinc*shotxdirec;
1568 /* check for bounce off sides */
1569 if(SHOTX+(shotxofs>>10) < XOFS) {
1570 shotxofs += 2*((XOFS<<10)-(((SHOTX)<<10)+shotxofs));
1571 shotxdirec *= -1;
1572 } else if(SHOTX+(shotxofs>>10) > XOFS+(BB_WIDTH-1)*BUBBLE_WIDTH) {
1573 shotxofs -= 2*((((SHOTX)<<10)+shotxofs)-
1574 ((XOFS<<10)+(((BB_WIDTH-1)*BUBBLE_WIDTH)<<10)));
1575 shotxdirec *= -1;
1578 tempxofs = shotxofs>>10;
1579 tempyofs = shotyofs>>10;
1581 /* display shot */
1582 bubbles_drawboard(bb);
1583 rb->lcd_bitmap_part(bubbles_emblem, 0, EMBLEM_HEIGHT*bubblecur, EMBLEM_WIDTH,
1584 SHOTX+tempxofs+(BUBBLE_WIDTH-EMBLEM_WIDTH)/2,
1585 SHOTY+tempyofs+(BUBBLE_HEIGHT-EMBLEM_HEIGHT)/2,
1586 EMBLEM_WIDTH, EMBLEM_HEIGHT);
1587 rb->lcd_set_drawmode(DRMODE_FG);
1588 rb->lcd_mono_bitmap((const unsigned char *)bubbles_bubble,
1589 SHOTX+tempxofs, SHOTY+tempyofs,
1590 BUBBLE_WIDTH, BUBBLE_HEIGHT);
1591 rb->lcd_set_drawmode(DRMODE_SOLID);
1592 rb->lcd_update_rect(XOFS, 0, BB_WIDTH*BUBBLE_WIDTH, LCD_HEIGHT);
1594 /* find nearest position */
1595 nearrow = ((SHOTY+tempyofs)-
1596 (bb->compress*ROW_HEIGHT)+
1597 (ROW_HEIGHT/2))/ROW_HEIGHT;
1598 if(nearrow >= BB_HEIGHT) nearrow = BB_HEIGHT-1;
1600 if(nearrow%2) { /* odd row */
1601 nearcol = ((SHOTX+tempxofs)-
1602 (XOFS+ROW_INDENT)+
1603 (BUBBLE_WIDTH/2))/BUBBLE_WIDTH;
1604 if(nearcol >= BB_WIDTH-1) nearcol = BB_WIDTH-2;
1605 } else { /* even row */
1606 nearcol = ((SHOTX+tempxofs)-XOFS+(BUBBLE_WIDTH/2))/BUBBLE_WIDTH;
1607 if(nearcol >= BB_WIDTH) nearcol = BB_WIDTH-1;
1609 if(nearcol < 0) nearcol = 0;
1611 /* if nearest position is occupied attach to last position */
1612 if(bb->playboard[nearrow][nearcol].type >= 0) {
1613 bb->playboard[lastrow][lastcol].type = bubblecur;
1614 break;
1617 /* save last position */
1618 lastrow = nearrow;
1619 lastcol = nearcol;
1621 /* if collision with neighbor then attach shot */
1622 if(bubbles_collision(bb, SHOTY+tempyofs, SHOTX+tempxofs,
1623 nearrow, nearcol)) {
1624 bb->playboard[nearrow][nearcol].type = bubblecur;
1625 break;
1628 /* if at top then attach shot to the ceiling */
1629 if(nearrow == 0 && SHOTY+tempyofs <= bb->compress*ROW_HEIGHT) {
1630 bb->playboard[nearrow][nearcol].type = bubblecur;
1631 break;
1634 /* handle button events */
1635 buttonres = bubbles_handlebuttons(bb, true, 0);
1636 if(buttonres != BB_NONE) return buttonres;
1638 /* framerate limiting */
1639 currenttick = *rb->current_tick;
1640 if(currenttick-lasttick < HZ/MAX_FPS) {
1641 rb->sleep((HZ/MAX_FPS)-(currenttick-lasttick));
1642 } else {
1643 rb->yield();
1645 lasttick = currenttick;
1648 bubbles_drawboard(bb);
1649 rb->lcd_update();
1651 /* clear appropriate bubbles from playing board */
1652 if(bubbles_ingroup(bb, lastrow, lastcol)) {
1653 buttonres = bubbles_remove(bb);
1654 if(buttonres != BB_NONE) return buttonres;
1657 /* update shots and compress amount */
1658 bb->shots++;
1659 if(bb->shots >= NUM_COMPRESS) {
1660 bb->shots = 0;
1661 bb->compress++;
1664 return BB_NONE;
1667 /*****************************************************************************
1668 * bubbles_collision() determines if a fired bubble has collided with another
1669 * bubble.
1670 ******************************************************************************/
1671 static bool bubbles_collision(struct game_context* bb, int y, int x,
1672 int nearrow, int nearcol) {
1673 int nx, ny;
1674 int adj = nearrow%2;
1676 /* check neighbors */
1677 if(nearcol-1 >= 0) {
1678 if(bb->playboard[nearrow][nearcol-1].type >= 0) {
1679 nx = XOFS+(nearrow%2 ? ROW_INDENT : 0)+BUBBLE_WIDTH*(nearcol-1);
1680 ny = ROW_HEIGHT*nearrow+bb->compress*ROW_HEIGHT;
1681 if((x-nx)*(x-nx)+(y-ny)*(y-ny) < MIN_DISTANCE) return true;
1685 if(nearcol-1+adj >= 0) {
1686 if(nearrow-1 >= 0) {
1687 if(bb->playboard[nearrow-1][nearcol-1+adj].type >= 0) {
1688 nx = XOFS+((nearrow-1)%2 ? ROW_INDENT : 0)+
1689 BUBBLE_WIDTH*(nearcol-1+adj);
1690 ny = ROW_HEIGHT*(nearrow-1)+bb->compress*ROW_HEIGHT;
1691 if((x-nx)*(x-nx)+(y-ny)*(y-ny) < MIN_DISTANCE) return true;
1695 if(nearrow+1 < BB_HEIGHT) {
1696 if(bb->playboard[nearrow+1][nearcol-1+adj].type >= 0) {
1697 nx = XOFS+((nearrow+1)%2 ? ROW_INDENT : 0)+
1698 BUBBLE_WIDTH*(nearcol-1+adj);
1699 ny = ROW_HEIGHT*(nearrow+1)+bb->compress*ROW_HEIGHT;
1700 if((x-nx)*(x-nx)+(y-ny)*(y-ny) < MIN_DISTANCE) return true;
1705 if(nearcol+adj >= 0) {
1706 if(nearrow-1 >= 0) {
1707 if(bb->playboard[nearrow-1][nearcol+adj].type >= 0) {
1708 nx = XOFS+((nearrow-1)%2 ? ROW_INDENT : 0)+
1709 BUBBLE_WIDTH*(nearcol+adj);
1710 ny = ROW_HEIGHT*(nearrow-1)+bb->compress*ROW_HEIGHT;
1711 if((x-nx)*(x-nx)+(y-ny)*(y-ny) < MIN_DISTANCE) return true;
1715 if(nearrow+1 < BB_HEIGHT) {
1716 if(bb->playboard[nearrow+1][nearcol+adj].type >= 0) {
1717 nx = XOFS+((nearrow+1)%2 ? ROW_INDENT : 0)+
1718 BUBBLE_WIDTH*(nearcol+adj);
1719 ny = ROW_HEIGHT*(nearrow+1)+bb->compress*ROW_HEIGHT;
1720 if((x-nx)*(x-nx)+(y-ny)*(y-ny) < MIN_DISTANCE) return true;
1725 if(nearcol+1 < BB_WIDTH-adj) {
1726 if(bb->playboard[nearrow][nearcol+1].type >= 0) {
1727 nx = XOFS+(nearrow%2 ? ROW_INDENT : 0)+BUBBLE_WIDTH*(nearcol+1);
1728 ny = ROW_HEIGHT*nearrow+bb->compress*ROW_HEIGHT;
1729 if((x-nx)*(x-nx)+(y-ny)*(y-ny) < MIN_DISTANCE) return true;
1733 return false;
1736 /*****************************************************************************
1737 * bubbles_ingroup() marks all bubbles that form the current group.
1738 ******************************************************************************/
1739 static bool bubbles_ingroup(struct game_context* bb, int row, int col) {
1740 int i, j;
1741 int count;
1743 count = bubbles_searchgroup(bb, row, col);
1745 /* unmark group if too small */
1746 if(count < 3) {
1747 for(i=0; i<BB_HEIGHT; i++) {
1748 for(j=0; j<BB_WIDTH; j++) {
1749 bb->playboard[i][j].ingroup = false;
1753 return false;
1756 return true;
1759 /*****************************************************************************
1760 * bubbles_searchgroup() return the size of the group of bubbles of the same
1761 * type that the current bubble belongs to.
1762 ******************************************************************************/
1763 static int bubbles_searchgroup(struct game_context* bb, int row, int col) {
1764 int i, adj;
1765 int myrow, mycol, mytype;
1766 int count = 0;
1768 struct coord {
1769 int row;
1770 int col;
1771 } search[(2*BB_WIDTH-1)*(BB_HEIGHT/2)];
1773 /* search initial bubble */
1774 bb->playboard[row][col].ingroup = true;
1775 search[count].row = row;
1776 search[count].col = col;
1777 count++;
1779 /* breadth-first search neighbors */
1780 for(i=0; i<count; i++) {
1781 myrow = search[i].row;
1782 mycol = search[i].col;
1783 mytype = bb->playboard[myrow][mycol].type;
1784 adj = myrow%2;
1786 if(mycol-1 >= 0) {
1787 if(bb->playboard[myrow][mycol-1].type == mytype &&
1788 !bb->playboard[myrow][mycol-1].ingroup) {
1789 bb->playboard[myrow][mycol-1].ingroup = true;
1790 search[count].row = myrow;
1791 search[count].col = mycol-1;
1792 count++;
1796 if(mycol-1+adj >= 0) {
1797 if(myrow-1 >= 0) {
1798 if(bb->playboard[myrow-1][mycol-1+adj].type == mytype &&
1799 !bb->playboard[myrow-1][mycol-1+adj].ingroup) {
1800 bb->playboard[myrow-1][mycol-1+adj].ingroup = true;
1801 search[count].row = myrow-1;
1802 search[count].col = mycol-1+adj;
1803 count++;
1807 if(myrow+1 < BB_HEIGHT) {
1808 if(bb->playboard[myrow+1][mycol-1+adj].type == mytype &&
1809 !bb->playboard[myrow+1][mycol-1+adj].ingroup) {
1810 bb->playboard[myrow+1][mycol-1+adj].ingroup = true;
1811 search[count].row = myrow+1;
1812 search[count].col = mycol-1+adj;
1813 count++;
1818 if(mycol+adj >= 0) {
1819 if(myrow-1 >= 0) {
1820 if(bb->playboard[myrow-1][mycol+adj].type == mytype &&
1821 !bb->playboard[myrow-1][mycol+adj].ingroup) {
1822 bb->playboard[myrow-1][mycol+adj].ingroup = true;
1823 search[count].row = myrow-1;
1824 search[count].col = mycol+adj;
1825 count++;
1829 if(myrow+1 < BB_HEIGHT) {
1830 if(bb->playboard[myrow+1][mycol+adj].type == mytype &&
1831 !bb->playboard[myrow+1][mycol+adj].ingroup) {
1832 bb->playboard[myrow+1][mycol+adj].ingroup = true;
1833 search[count].row = myrow+1;
1834 search[count].col = mycol+adj;
1835 count++;
1840 if(mycol+1 < BB_WIDTH-adj) {
1841 if(bb->playboard[myrow][mycol+1].type == mytype &&
1842 !bb->playboard[myrow][mycol+1].ingroup) {
1843 bb->playboard[myrow][mycol+1].ingroup = true;
1844 search[count].row = myrow;
1845 search[count].col = mycol+1;
1846 count++;
1851 return count;
1854 /*****************************************************************************
1855 * bubbles_remove() removes all bubbles in the current group and all
1856 * unanchored bubbles from the play board.
1857 ******************************************************************************/
1858 static int bubbles_remove(struct game_context* bb) {
1859 int i, j;
1860 int buttonres;
1862 /* determine all anchored bubbles */
1863 for(j=0; j<BB_WIDTH; j++) {
1864 if(bb->playboard[0][j].type >= 0 && !bb->playboard[0][j].ingroup) {
1865 bubbles_anchored(bb, 0, j);
1869 /* mark bubbles to be deleted */
1870 for(i=0; i<BB_HEIGHT; i++) {
1871 for(j=0; j<BB_WIDTH; j++) {
1872 if(bb->playboard[i][j].type >= 0 &&
1873 (!bb->playboard[i][j].anchored || bb->playboard[i][j].ingroup)) {
1874 bb->playboard[i][j].delete = true;
1879 /* animate falling bubbles */
1880 buttonres = bubbles_fall(bb);
1881 if(buttonres != BB_NONE) return buttonres;
1883 /* remove bubbles */
1884 for(i=0; i<BB_HEIGHT; i++) {
1885 for(j=0; j<BB_WIDTH; j++) {
1886 if(bb->playboard[i][j].delete) {
1887 bb->playboard[i][j].ingroup = false;
1888 bb->playboard[i][j].type = -1;
1889 bb->playboard[i][j].delete = false;
1890 } else {
1891 bb->playboard[i][j].anchored = false;
1896 bubbles_getonboard(bb);
1898 return BB_NONE;
1901 /*****************************************************************************
1902 * bubbles_anchored() marks all bubbles that are anchored in some way to the
1903 * current bubble.
1904 ******************************************************************************/
1905 static void bubbles_anchored(struct game_context* bb, int row, int col) {
1906 int i, adj;
1907 int myrow, mycol, mytype;
1908 int count = 0;
1910 struct coord {
1911 int row;
1912 int col;
1913 } search[(2*BB_WIDTH-1)*(BB_HEIGHT/2)];
1915 /* search initial bubble */
1916 bb->playboard[row][col].anchored = true;
1917 search[count].row = row;
1918 search[count].col = col;
1919 count++;
1921 /* breadth-first search neighbors */
1922 for(i=0; i<count; i++) {
1923 myrow = search[i].row;
1924 mycol = search[i].col;
1925 mytype = bb->playboard[myrow][mycol].type;
1926 adj = myrow%2;
1928 if(mycol-1 >= 0) {
1929 if(bb->playboard[myrow][mycol-1].type >= 0 &&
1930 !bb->playboard[myrow][mycol-1].ingroup &&
1931 !bb->playboard[myrow][mycol-1].anchored) {
1932 bb->playboard[myrow][mycol-1].anchored = true;
1933 search[count].row = myrow;
1934 search[count].col = mycol-1;
1935 count++;
1939 if(mycol-1+adj >= 0) {
1940 if(myrow-1 >= 0) {
1941 if(bb->playboard[myrow-1][mycol-1+adj].type >= 0 &&
1942 !bb->playboard[myrow-1][mycol-1+adj].ingroup &&
1943 !bb->playboard[myrow-1][mycol-1+adj].anchored) {
1944 bb->playboard[myrow-1][mycol-1+adj].anchored = true;
1945 search[count].row = myrow-1;
1946 search[count].col = mycol-1+adj;
1947 count++;
1951 if(myrow+1 < BB_HEIGHT) {
1952 if(bb->playboard[myrow+1][mycol-1+adj].type >= 0 &&
1953 !bb->playboard[myrow+1][mycol-1+adj].ingroup &&
1954 !bb->playboard[myrow+1][mycol-1+adj].anchored) {
1955 bb->playboard[myrow+1][mycol-1+adj].anchored = true;
1956 search[count].row = myrow+1;
1957 search[count].col = mycol-1+adj;
1958 count++;
1963 if(mycol+adj >= 0) {
1964 if(myrow-1 >= 0) {
1965 if(bb->playboard[myrow-1][mycol+adj].type >= 0 &&
1966 !bb->playboard[myrow-1][mycol+adj].ingroup &&
1967 !bb->playboard[myrow-1][mycol+adj].anchored) {
1968 bb->playboard[myrow-1][mycol+adj].anchored = true;
1969 search[count].row = myrow-1;
1970 search[count].col = mycol+adj;
1971 count++;
1975 if(myrow+1 < BB_HEIGHT) {
1976 if(bb->playboard[myrow+1][mycol+adj].type >= 0 &&
1977 !bb->playboard[myrow+1][mycol+adj].ingroup &&
1978 !bb->playboard[myrow+1][mycol+adj].anchored) {
1979 bb->playboard[myrow+1][mycol+adj].anchored = true;
1980 search[count].row = myrow+1;
1981 search[count].col = mycol+adj;
1982 count++;
1987 if(mycol+1 < BB_WIDTH-adj) {
1988 if(bb->playboard[myrow][mycol+1].type >= 0 &&
1989 !bb->playboard[myrow][mycol+1].ingroup &&
1990 !bb->playboard[myrow][mycol+1].anchored) {
1991 bb->playboard[myrow][mycol+1].anchored = true;
1992 search[count].row = myrow;
1993 search[count].col = mycol+1;
1994 count++;
2000 /*****************************************************************************
2001 * bubbles_fall() makes removed bubbles fall from the screen.
2002 ******************************************************************************/
2003 static int bubbles_fall(struct game_context* bb) {
2004 int i, j;
2005 int count;
2006 int indent;
2007 int xofs, yofs;
2008 int buttonres;
2009 bool onscreen;
2010 long lasttick, currenttick;
2012 /* give all falling bubbles an x axis movement */
2013 for(i=0; i<BB_HEIGHT; i++) {
2014 for(j=0; j<BB_WIDTH; j++) {
2015 if(bb->playboard[i][j].delete) {
2016 bb->playboard[i][j].fallx = rb->rand()%25 - 12;
2017 bb->playboard[i][j].fallvel = rb->rand()%5 + 6;
2022 /* draw bubbles falling off the screen
2023 * follows y=x^2-8x scaled to bubble size
2025 lasttick = *rb->current_tick;
2027 for(count=1; ;count++) {
2028 onscreen = false;
2029 bubbles_drawboard(bb);
2031 for(i=0; i<BB_HEIGHT; i++) {
2032 for(j=0; j<BB_WIDTH; j++) {
2033 if(bb->playboard[i][j].delete) {
2034 indent = (i%2 ? ROW_INDENT : 0);
2035 xofs = ((bb->playboard[i][j].fallx*count)*BUBBLE_WIDTH)/48;
2036 yofs = ((count*count - bb->playboard[i][j].fallvel*count)*
2037 BUBBLE_HEIGHT)/20;
2039 /* draw bubble if it is still on the screen */
2040 if(ROW_HEIGHT*i+bb->compress*ROW_HEIGHT+yofs
2041 <= LCD_HEIGHT) {
2042 onscreen = true;
2044 rb->lcd_bitmap_part(bubbles_emblem, 0,
2045 EMBLEM_HEIGHT*bb->playboard[i][j].type, EMBLEM_WIDTH,
2046 XOFS+indent+BUBBLE_WIDTH*j+
2047 (BUBBLE_WIDTH-EMBLEM_WIDTH)/2+xofs,
2048 ROW_HEIGHT*i+(BUBBLE_HEIGHT-EMBLEM_HEIGHT)/2+
2049 bb->compress*ROW_HEIGHT+yofs,
2050 EMBLEM_WIDTH, EMBLEM_HEIGHT);
2051 rb->lcd_set_drawmode(DRMODE_FG);
2052 rb->lcd_mono_bitmap(
2053 (const unsigned char *)bubbles_bubble,
2054 XOFS+indent+BUBBLE_WIDTH*j+xofs,
2055 ROW_HEIGHT*i+bb->compress*ROW_HEIGHT+yofs,
2056 BUBBLE_WIDTH, BUBBLE_HEIGHT);
2057 rb->lcd_set_drawmode(DRMODE_SOLID);
2063 rb->lcd_update();
2065 /* break out if all bubbles are off the screen */
2066 if(!onscreen) break;
2068 /* handle button events */
2069 buttonres = bubbles_handlebuttons(bb, true, 0);
2070 if(buttonres != BB_NONE) return buttonres;
2072 /* framerate limiting */
2073 currenttick = *rb->current_tick;
2074 if(currenttick-lasttick < HZ/MAX_FPS) {
2075 rb->sleep((HZ/MAX_FPS)-(currenttick-lasttick));
2076 } else {
2077 rb->yield();
2079 lasttick = currenttick;
2082 return BB_NONE;
2085 /*****************************************************************************
2086 * bubbles_checklevel() checks the state of the playboard for a win or loss.
2087 ******************************************************************************/
2088 static int bubbles_checklevel(struct game_context* bb) {
2089 int i, j;
2090 int points;
2091 char str[13];
2093 bubbles_drawboard(bb);
2094 rb->lcd_update();
2096 /* check for bubbles below cut off point */
2097 for(i=0; i<=bb->compress; i++) {
2098 for(j=0; j<BB_WIDTH; j++) {
2099 if(bb->playboard[BB_HEIGHT-1-i][j].type >= 0) return BB_LOSE;
2103 /* check for bubbles above cut off point */
2104 for(i=0; i<BB_HEIGHT-1-bb->compress; i++) {
2105 for(j=0; j<BB_WIDTH; j++) {
2106 if(bb->playboard[i][j].type >= 0) return BB_NONE;
2110 /* level complete, record score */
2111 points = 100 - bb->elapsedlvl/100;
2112 if(points > 0) {
2113 bb->score += points;
2114 } else {
2115 points = 0;
2118 rb->snprintf(str, 12, "%d points", points);
2119 rb->splash(HZ, str);
2121 /* advance to the next level */
2122 if(!bubbles_nextlevel(bb)) {
2123 return BB_WIN;
2126 bubbles_drawboard(bb);
2127 rb->lcd_update();
2128 rb->snprintf(str, 12, "Level %d", bb->level);
2129 rb->splash(HZ, str);
2130 bubbles_drawboard(bb);
2131 rb->lcd_update();
2133 return BB_NONE;
2136 /*****************************************************************************
2137 * bubbles_recordscore() inserts a high score into the high scores list and
2138 * returns the high score position.
2139 ******************************************************************************/
2140 static int bubbles_recordscore(struct game_context* bb) {
2141 int i;
2142 int position = 0;
2143 unsigned int currentscore, currentlevel;
2144 unsigned int tempscore, templevel;
2146 if(bb->score > 0) {
2147 currentlevel = bb->level-1;
2148 currentscore = bb->score;
2150 for(i=0; i<NUM_SCORES; i++) {
2151 if(currentscore >= bb->highscores[i].score) {
2152 if(!position) {
2153 position = i+1;
2154 bb->dirty = true;
2156 templevel = bb->highscores[i].level;
2157 tempscore = bb->highscores[i].score;
2158 bb->highscores[i].level = currentlevel;
2159 bb->highscores[i].score = currentscore;
2160 currentlevel = templevel;
2161 currentscore = tempscore;
2166 return position;
2169 /*****************************************************************************
2170 * bubbles_loadscores() loads the high scores saved file.
2171 ******************************************************************************/
2172 static void bubbles_loadscores(struct game_context* bb) {
2173 int fd;
2175 bb->dirty = false;
2177 /* clear high scores */
2178 bb->highlevel = 0;
2179 rb->memset(bb->highscores, 0, sizeof(bb->highscores));
2181 /* open scores file */
2182 fd = rb->open(SCORE_FILE, O_RDONLY);
2183 if(fd < 0) return;
2185 /* read in high scores */
2186 rb->read(fd, &bb->highlevel, sizeof(bb->highlevel));
2187 if(rb->read(fd, bb->highscores, sizeof(bb->highscores)) <= 0) {
2188 /* scores are bad, reset */
2189 rb->memset(bb->highscores, 0, sizeof(bb->highscores));
2192 if( bb->highlevel >= NUM_LEVELS )
2193 bb->highlevel = NUM_LEVELS - 1;
2195 rb->close(fd);
2198 /*****************************************************************************
2199 * bubbles_savescores() saves the high scores saved file.
2200 ******************************************************************************/
2201 static void bubbles_savescores(struct game_context* bb) {
2202 int fd;
2204 /* write out the high scores to the save file */
2205 fd = rb->open(SCORE_FILE, O_WRONLY|O_CREAT);
2206 rb->write(fd, &bb->highlevel, sizeof(bb->highlevel));
2207 rb->write(fd, bb->highscores, sizeof(bb->highscores));
2208 rb->close(fd);
2209 bb->dirty = false;
2212 /*****************************************************************************
2213 * bubbles_loadgame() loads the saved game and returns load success.
2214 ******************************************************************************/
2215 static bool bubbles_loadgame(struct game_context* bb) {
2216 int fd;
2217 bool loaded = false;
2219 /* open game file */
2220 fd = rb->open(SAVE_FILE, O_RDONLY);
2221 if(fd < 0) return loaded;
2223 /* read in saved game */
2224 while(true) {
2225 if(rb->read(fd, &bb->score, sizeof(bb->score)) <= 0) break;
2226 if(rb->read(fd, &bb->level, sizeof(bb->level)) <= 0) break;
2227 if(rb->read(fd, &bb->angle, sizeof(bb->angle)) <= 0) break;
2228 if(rb->read(fd, &bb->shots, sizeof(bb->shots)) <= 0) break;
2229 if(rb->read(fd, &bb->compress, sizeof(bb->compress)) <= 0) break;
2230 if(rb->read(fd, &bb->onboardcnt, sizeof(bb->onboardcnt)) <= 0) break;
2231 if(rb->read(fd, bb->onboard, sizeof(bb->onboard)) <= 0) break;
2232 if(rb->read(fd, &bb->nextinq, sizeof(bb->nextinq)) <= 0) break;
2233 if(rb->read(fd, bb->queue, sizeof(bb->queue)) <= 0) break;
2234 if(rb->read(fd, &bb->elapsedlvl, sizeof(bb->elapsedlvl)) <= 0) break;
2235 if(rb->read(fd, bb->playboard, sizeof(bb->playboard)) <= 0) break;
2236 bb->resume = true;
2237 loaded = true;
2238 break;
2241 rb->close(fd);
2243 /* delete saved file */
2244 rb->remove(SAVE_FILE);
2245 return loaded;
2248 /*****************************************************************************
2249 * bubbles_savegame() saves the current game state.
2250 ******************************************************************************/
2251 static void bubbles_savegame(struct game_context* bb) {
2252 int fd;
2254 /* write out the game state to the save file */
2255 fd = rb->open(SAVE_FILE, O_WRONLY|O_CREAT);
2256 rb->write(fd, &bb->score, sizeof(bb->score));
2257 rb->write(fd, &bb->level, sizeof(bb->level));
2258 rb->write(fd, &bb->angle, sizeof(bb->angle));
2259 rb->write(fd, &bb->shots, sizeof(bb->shots));
2260 rb->write(fd, &bb->compress, sizeof(bb->compress));
2261 rb->write(fd, &bb->onboardcnt, sizeof(bb->onboardcnt));
2262 rb->write(fd, bb->onboard, sizeof(bb->onboard));
2263 rb->write(fd, &bb->nextinq, sizeof(bb->nextinq));
2264 rb->write(fd, bb->queue, sizeof(bb->queue));
2265 rb->write(fd, &bb->elapsedlvl, sizeof(bb->elapsedlvl));
2266 rb->write(fd, bb->playboard, sizeof(bb->playboard));
2267 rb->close(fd);
2269 bb->resume = true;
2272 /*****************************************************************************
2273 * bubbles_setcolors() set the foreground and background colors.
2274 ******************************************************************************/
2275 static inline void bubbles_setcolors(void) {
2276 #ifdef HAVE_LCD_COLOR
2277 rb->lcd_set_background(LCD_RGBPACK(181,181,222));
2278 rb->lcd_set_foreground(LCD_BLACK);
2279 #endif
2282 /*****************************************************************************
2283 * bubbles_callback() is the default event handler callback which is called
2284 * on usb connect and shutdown.
2285 ******************************************************************************/
2286 static void bubbles_callback(void* param) {
2287 struct game_context* bb = (struct game_context*) param;
2288 if(bb->dirty) {
2289 rb->splash(HZ/2, "Saving high scores...");
2290 bubbles_savescores(bb);
2294 /*****************************************************************************
2295 * bubbles_handlebuttons() handles button events during a game.
2296 ******************************************************************************/
2297 static int bubbles_handlebuttons(struct game_context* bb, bool animblock,
2298 int timeout) {
2299 int button;
2300 int buttonres;
2301 long start;
2302 const struct button_mapping *plugin_contexts[]
2303 #if CONFIG_KEYPAD != SANSA_E200_PAD
2304 = {generic_left_right_fire,generic_actions};
2305 #else
2306 = {generic_directions,generic_actions};
2307 #endif
2309 if (timeout < 0)
2310 timeout = 0;
2311 button = pluginlib_getaction(rb,timeout,plugin_contexts,2);
2312 #ifdef HAS_BUTTON_HOLD
2313 if (rb->button_hold())
2314 button = BUBBLES_START;
2315 #endif
2317 switch(button){
2318 case BUBBLES_LEFT_REP:
2319 if(bb->angle > MIN_ANGLE) bb->angle -= ANGLE_STEP_REP;
2320 case BUBBLES_LEFT: /* change angle to the left */
2321 if(bb->angle > MIN_ANGLE) bb->angle -= ANGLE_STEP;
2322 break;
2324 case BUBBLES_RIGHT_REP:
2325 if(bb->angle < MAX_ANGLE) bb->angle += ANGLE_STEP_REP;
2326 case BUBBLES_RIGHT: /* change angle to the right */
2327 if(bb->angle < MAX_ANGLE) bb->angle += ANGLE_STEP;
2328 break;
2330 case BUBBLES_SELECT: /* fire the shot */
2331 if(!animblock) {
2332 bb->elapsedlvl += bb->elapsedshot;
2333 bb->elapsedshot = 0;
2334 buttonres = bubbles_fire(bb);
2335 if(buttonres != BB_NONE) return buttonres;
2336 buttonres = bubbles_checklevel(bb);
2337 if(buttonres != BB_NONE) return buttonres;
2338 bb->startedshot = *rb->current_tick;
2340 break;
2342 case BUBBLES_START: /* pause the game */
2343 start = *rb->current_tick;
2344 rb->splash(1, "Paused");
2345 while(pluginlib_getaction(rb,TIMEOUT_BLOCK,plugin_contexts,2)
2346 != (BUBBLES_START));
2347 bb->startedshot += *rb->current_tick-start;
2348 bubbles_drawboard(bb);
2349 rb->lcd_update();
2350 break;
2352 case BUBBLES_RESUME: /* save and end the game */
2353 if(!animblock) {
2354 rb->splash(HZ/2, "Saving game...");
2355 bubbles_savegame(bb);
2356 return BB_END;
2358 break;
2359 case BUBBLES_QUIT: /* end the game */
2360 return BB_END;
2362 case ACTION_UNKNOWN:
2363 case ACTION_NONE: /* no button pressed */
2364 break;
2366 default:
2367 if(rb->default_event_handler_ex(button, bubbles_callback,
2368 (void*) bb) == SYS_USB_CONNECTED)
2369 return BB_USB;
2370 break;
2373 return BB_NONE;
2376 /*****************************************************************************
2377 * bubbles() is the main game subroutine, it returns the final game status.
2378 ******************************************************************************/
2379 static int bubbles(struct game_context* bb) {
2380 int i;
2381 int w, h;
2382 int button;
2383 int buttonres;
2384 unsigned int startlevel = 0;
2385 char *title = "Bubbles";
2386 bool startgame = false;
2387 bool showscores = false;
2388 long timeout;
2389 const struct button_mapping *plugin_contexts[]
2390 = {generic_actions,generic_directions};
2392 bubbles_setcolors();
2394 /* don't resume by default */
2395 bb->resume = false;
2397 /********************
2398 * menu *
2399 ********************/
2400 while(!startgame){
2401 char str[30];
2402 rb->lcd_clear_display();
2404 if(!showscores) {
2405 /* welcome screen to display key bindings */
2406 rb->lcd_getstringsize(title, &w, &h);
2407 rb->lcd_putsxy((LCD_WIDTH-w)/2, 0, title);
2408 #if (CONFIG_KEYPAD == IRIVER_H100_PAD) || (CONFIG_KEYPAD == IRIVER_H300_PAD)
2409 rb->lcd_puts(0, 2, "ON to start/pause");
2410 rb->lcd_puts(0, 3, "MODE to save/resume");
2411 rb->lcd_puts(0, 4, "OFF to exit");
2412 rb->lcd_puts(0, 5, "SELECT to fire");
2413 rb->lcd_puts(0, 6, " and show high scores");
2414 rb->lcd_puts(0, 7, "LEFT/RIGHT to aim");
2415 rb->lcd_puts(0, 8, "UP/DOWN to change level");
2416 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || (CONFIG_KEYPAD == IPOD_3G_PAD) || \
2417 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
2418 rb->lcd_puts(0, 2, "PLAY to start/pause");
2419 rb->lcd_puts(0, 3, "MENU to save/resume");
2420 rb->lcd_puts(0, 4, "MENU+SELECT to exit");
2421 rb->lcd_puts(0, 5, "SELECT to fire");
2422 rb->lcd_puts(0, 6, " and show high scores");
2423 rb->lcd_puts(0, 7, "SCROLL to aim");
2424 rb->lcd_puts(0, 8, " and to change level");
2425 #elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
2426 rb->lcd_puts(0, 2, "PLAY to start/pause");
2427 rb->lcd_puts(0, 3, "REC to save/resume");
2428 rb->lcd_puts(0, 4, "POWER to exit");
2429 rb->lcd_puts(0, 5, "SELECT to fire");
2430 rb->lcd_puts(0, 6, " and show high scores");
2431 rb->lcd_puts(0, 7, "LEFT/RIGHT to aim");
2432 rb->lcd_puts(0, 8, "UP/DOWN to change level");
2433 #elif CONFIG_KEYPAD == GIGABEAT_PAD
2434 rb->lcd_puts(0, 2, "POWER to start/pause");
2435 rb->lcd_puts(0, 3, "MENU to save/resume");
2436 rb->lcd_puts(0, 4, "A to exit");
2437 rb->lcd_puts(0, 5, "SELECT to fire");
2438 rb->lcd_puts(0, 6, " and show high scores");
2439 rb->lcd_puts(0, 7, "LEFT/RIGHT to aim");
2440 rb->lcd_puts(0, 8, "UP/DOWN to change level");
2441 #elif CONFIG_KEYPAD == RECORDER_PAD
2442 rb->lcd_puts_scroll(0, 2, "ON to start/pause, "
2443 "F1 to save/resume, "
2444 "OFF to exit, "
2445 "PLAY to fire and show high scores, "
2446 "LEFT/RIGHT to aim, "
2447 "UP/DOWN to change level.");
2448 #elif CONFIG_KEYPAD == ONDIO_PAD
2449 rb->lcd_puts_scroll(0, 2, "MODE to start/pause, "
2450 "DOWN to save/resume, "
2451 "OFF to exit, "
2452 "UP to fire and show high scores, "
2453 "LEFT/RIGHT to aim and to change level.");
2454 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
2455 rb->lcd_puts(0, 2, "PLAY to start/pause");
2456 rb->lcd_puts(0, 3, "FF to save/resume");
2457 rb->lcd_puts(0, 4, "POWER to exit");
2458 rb->lcd_puts(0, 5, "REW/UP to fire");
2459 rb->lcd_puts(0, 6, " and show high scores");
2460 rb->lcd_puts(0, 7, "LEFT/RIGHT to aim");
2461 rb->lcd_puts(0, 8, "UP/DOWN to change level");
2462 #elif CONFIG_KEYPAD == SANSA_E200_PAD
2463 rb->lcd_puts(0, 2, "PLAY to start/pause");
2464 rb->lcd_puts(0, 3, "SUBMENU to save/resume");
2465 rb->lcd_puts(0, 4, "POWER to exit");
2466 rb->lcd_puts(0, 5, "SELECT to fire");
2467 rb->lcd_puts(0, 6, " and show high scores");
2468 rb->lcd_puts(0, 7, "SCROLL to aim");
2469 rb->lcd_puts(0, 8, " and change level");
2470 #elif CONFIG_KEYPAD == SANSA_C200_PAD
2471 rb->lcd_puts(0, 2, "PLAY to start/pause");
2472 rb->lcd_puts(0, 3, "SUBMENU to save/resume");
2473 rb->lcd_puts(0, 4, "POWER to exit");
2474 rb->lcd_puts_scroll(0, 5, "SELECT to fire and show high scores, "
2475 "LEFT/RIGHT to aim and change level");
2476 #endif
2477 #if LCD_WIDTH >= 138
2478 rb->snprintf(str, 28, "Start on level %d of %d", startlevel+1,
2479 bb->highlevel+1);
2480 #else
2481 rb->snprintf(str, 28, "Start on lvl %d/%d", startlevel+1,
2482 bb->highlevel+1);
2483 #endif
2484 rb->lcd_puts(0, MIN(TEXT_LINES-3,10), str);
2485 rb->lcd_puts(0, MIN(TEXT_LINES-2,12), "High Score:");
2486 rb->snprintf(str, 30, "%d, Lvl %d",
2487 bb->highscores[0].score, bb->highscores[0].level);
2488 rb->lcd_puts(2, MIN(TEXT_LINES-1,13), str);
2489 } else {
2490 /* show high scores */
2491 rb->snprintf(str, 12, "High Scores");
2492 rb->lcd_getstringsize(str, &w, &h);
2493 rb->lcd_putsxy((LCD_WIDTH-w)/2, 0, str);
2495 for(i=0; i<NUM_SCORES; i++) {
2496 rb->snprintf(str, 30, "#%02d: %d, Lvl %d", i+1,
2497 bb->highscores[i].score, bb->highscores[i].level);
2498 rb->lcd_puts(0, i+2, str);
2502 rb->lcd_update();
2504 /* handle menu button presses */
2505 button = pluginlib_getaction(rb,TIMEOUT_BLOCK,plugin_contexts,2);
2506 switch(button){
2507 case BUBBLES_START: /* start playing */
2508 bb->level = startlevel;
2509 startgame = true;
2510 break;
2511 case BUBBLES_QUIT: /* quit program */
2512 if(showscores) {
2513 showscores = false;
2514 break;
2516 return BB_QUIT;
2518 case BUBBLES_RESUME: /* resume game */
2519 if(!bubbles_loadgame(bb)) {
2520 rb->splash(HZ*2, "Nothing to resume");
2521 } else {
2522 startgame = true;
2524 break;
2526 case BUBBLES_SELECT: /* toggle high scores */
2527 showscores = !showscores;
2528 break;
2530 case BUBBLES_LVLINC: /* increase starting level */
2531 case BUBBLES_LVLINC_REP:
2532 if(startlevel >= bb->highlevel) {
2533 startlevel = 0;
2534 } else {
2535 startlevel++;
2537 break;
2539 case BUBBLES_LVLDEC: /* decrease starting level */
2540 case BUBBLES_LVLDEC_REP:
2541 if(startlevel <= 0) {
2542 startlevel = bb->highlevel;
2543 } else {
2544 startlevel--;
2546 break;
2548 default:
2549 if(rb->default_event_handler_ex(button, bubbles_callback,
2550 (void*) bb) == SYS_USB_CONNECTED)
2551 return BB_USB;
2552 break;
2556 /********************
2557 * init *
2558 ********************/
2559 bubbles_init(bb);
2560 bubbles_drawboard(bb);
2561 rb->lcd_update();
2563 /**********************
2564 * play *
2565 **********************/
2566 bb->startedshot = *rb->current_tick;
2568 while(true) {
2569 /* refresh the board */
2570 bubbles_drawboard(bb);
2571 rb->lcd_update();
2573 /* manange idle framerate */
2574 bb->elapsedshot = *rb->current_tick-bb->startedshot;
2576 if(MAX_SHOTTIME-bb->elapsedshot < HZ/2) {
2577 timeout = MAX_SHOTTIME-bb->elapsedshot;
2578 } else {
2579 timeout = HZ/2;
2582 /* handle button events */
2583 buttonres = bubbles_handlebuttons(bb, false, timeout);
2584 if(buttonres != BB_NONE) return buttonres;
2586 /* handle timing */
2587 bb->elapsedshot = *rb->current_tick-bb->startedshot;
2589 if(bb->elapsedshot > MAX_SHOTTIME) {
2590 bb->elapsedlvl += bb->elapsedshot;
2591 bb->elapsedshot = 0;
2592 buttonres = bubbles_fire(bb);
2593 if(buttonres != BB_NONE) return buttonres;
2594 buttonres = bubbles_checklevel(bb);
2595 if(buttonres != BB_NONE) return buttonres;
2596 bb->startedshot = *rb->current_tick;
2601 /*****************************************************************************
2602 * plugin entry point.
2603 ******************************************************************************/
2604 enum plugin_status plugin_start(struct plugin_api* api, void* parameter) {
2605 struct game_context bb;
2606 bool exit = false;
2607 int position;
2609 /* plugin init */
2610 (void)parameter;
2611 rb = api;
2612 /* end of plugin init */
2614 /* more init */
2615 xlcd_init(rb);
2617 /* load files */
2618 rb->splash(0, "Loading...");
2619 bubbles_loadscores(&bb);
2620 rb->lcd_clear_display();
2622 /* start app */
2623 #if LCD_DEPTH > 1
2624 rb->lcd_set_backdrop(NULL);
2625 #endif
2626 rb->lcd_setfont(FONT_SYSFIXED);
2628 while(!exit) {
2629 switch(bubbles(&bb)){
2630 char str[19];
2631 case BB_WIN:
2632 rb->splash(HZ*2, "You Win!");
2633 /* record high level */
2634 if( NUM_LEVELS-1 > bb.highlevel) {
2635 bb.highlevel = NUM_LEVELS-1;
2636 bb.dirty = true;
2639 /* record high score */
2640 if((position = bubbles_recordscore(&bb))) {
2641 rb->snprintf(str, 19, "New high score #%d!", position);
2642 rb->splash(HZ*2, str);
2644 break;
2646 case BB_LOSE:
2647 rb->splash(HZ*2, "Game Over");
2648 /* fall through to BB_END */
2650 case BB_END:
2651 if(!bb.resume) {
2652 /* record high level */
2653 if(bb.level-1 > bb.highlevel) {
2654 bb.highlevel = bb.level-1;
2655 bb.dirty = true;
2658 /* record high score */
2659 if((position = bubbles_recordscore(&bb))) {
2660 rb->snprintf(str, 19, "New high score #%d!", position);
2661 rb->splash(HZ*2, str);
2664 break;
2666 case BB_USB:
2667 rb->lcd_setfont(FONT_UI);
2668 return PLUGIN_USB_CONNECTED;
2670 case BB_QUIT:
2671 if(bb.dirty) {
2672 rb->splash(HZ/2, "Saving high scores...");
2673 bubbles_savescores(&bb);
2675 exit = true;
2676 break;
2678 default:
2679 break;
2683 rb->lcd_setfont(FONT_UI);
2684 return PLUGIN_OK;
2687 #endif