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