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