Fix some quotation marks. Thanks to Alexander Levin for pointing it out.
[Rockbox.git] / apps / plugins / bubbles.c
bloba5dbf6d42b9f4e2620b6bd6039c04e3cd8335496
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2005 Adam Boot
12 * Color graphics from Frozen Bubble (http://www.frozen-bubble.org/)
14 * All files in this archive are subject to the GNU General Public License.
15 * See the file COPYING in the source tree root for full license agreement.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
22 #include "plugin.h"
24 #ifdef HAVE_LCD_BITMAP
26 #include "xlcd.h"
27 #include "pluginlib_actions.h"
28 #include "fixedpoint.h"
30 PLUGIN_HEADER
32 /* files */
33 #define SCORE_FILE PLUGIN_GAMES_DIR "/bubbles.score"
34 #define SAVE_FILE PLUGIN_GAMES_DIR "/bubbles.save"
36 /* final game return status */
37 #define BB_NONE 5
38 #define BB_WIN 4
39 #define BB_END 3
40 #define BB_USB 2
41 #define BB_QUIT 1
42 #define BB_LOSE 0
44 /* play board dimension */
45 #define BB_HEIGHT 12
46 #define BB_WIDTH 8
47 #define BB_LEVEL_HEIGHT 10
49 /* various amounts */
50 #define NUM_SCORES 10
51 #define NUM_LEVELS 100
52 #define NUM_QUEUE 2
53 #define NUM_BUBBLES 8
54 #define MIN_ANGLE -76
55 #define MAX_ANGLE 76
56 #define NUM_COMPRESS 9
57 #define MAX_SHOTTIME 1000
59 /* keyboard layouts */
60 #if CONFIG_KEYPAD != SANSA_E200_PAD
61 /* sansa uses the wheel instead of left/right */
62 #define BUBBLES_LEFT PLA_LEFT
63 #define BUBBLES_LEFT_REP PLA_LEFT_REPEAT
64 #define BUBBLES_RIGHT PLA_RIGHT
65 #define BUBBLES_RIGHT_REP PLA_RIGHT_REPEAT
66 #define ANGLE_STEP 4
67 #define ANGLE_STEP_REP 4
68 #else
69 #define BUBBLES_LEFT PLA_UP
70 #define BUBBLES_LEFT_REP PLA_UP_REPEAT
71 #define BUBBLES_RIGHT PLA_DOWN
72 #define BUBBLES_RIGHT_REP PLA_DOWN_REPEAT
73 #define ANGLE_STEP 2
74 #define ANGLE_STEP_REP 4
75 #endif
77 #define BUBBLES_QUIT PLA_QUIT
78 #define BUBBLES_START PLA_START
79 #define BUBBLES_SELECT PLA_FIRE
80 #define BUBBLES_RESUME PLA_MENU
82 #if CONFIG_KEYPAD != ONDIO_PAD
84 #define BUBBLES_LVLINC PLA_UP
85 #define BUBBLES_LVLINC_REP PLA_UP_REPEAT
86 #define BUBBLES_LVLDEC PLA_DOWN
87 #define BUBBLES_LVLDEC_REP PLA_DOWN_REPEAT
89 #else /* ondio keys */
91 #define BUBBLES_LVLINC PLA_RIGHT
92 #define BUBBLES_LVLINC_REP PLA_RIGHT_REPEAT
93 #define BUBBLES_LVLDEC PLA_LEFT
94 #define BUBBLES_LVLDEC_REP PLA_LEFT_REPEAT
96 #endif
98 /* external bitmaps */
99 #ifdef HAVE_LCD_COLOR
100 #include "bubbles_background.h"
101 #endif
102 #include "bubbles_bubble.h"
103 #include "bubbles_emblem.h"
105 #define BUBBLE_WIDTH BMPWIDTH_bubbles_bubble
106 #define BUBBLE_HEIGHT BMPHEIGHT_bubbles_bubble
107 #define EMBLEM_WIDTH BMPWIDTH_bubbles_emblem
108 #define EMBLEM_HEIGHT (BMPHEIGHT_bubbles_emblem/8)
110 /* bubbles will consume height of ROW_HEIGHT*(BB_HEIGHT-1)+BUBBLE_HEIGHT*3/2 */
111 /* 22x22 bubbles (iPod Video) */
112 #if (LCD_HEIGHT == 240) && (LCD_WIDTH == 320)
113 #define XOFS 72
114 #define ROW_HEIGHT 18
115 #define ROW_INDENT 11
116 #define MAX_FPS 40
118 /* 22x22 bubbles (Gigabeat) */
119 #elif (LCD_HEIGHT == 320) && (LCD_WIDTH == 240)
120 #define XOFS 64
121 #define ROW_HEIGHT 18
122 #define ROW_INDENT 11
123 #define MAX_FPS 30
125 /* 16x16 bubbles (H300, iPod Color) */
126 #elif (LCD_HEIGHT == 176) && (LCD_WIDTH == 220)
127 #define XOFS 46
128 #define ROW_HEIGHT 14
129 #define ROW_INDENT 8
130 #define MAX_FPS 30
132 /* 16x16 bubbles (Sansa E200) */
133 #elif (LCD_HEIGHT == 220) && (LCD_WIDTH == 176)
134 #define XOFS 48
135 #define ROW_HEIGHT 14
136 #define ROW_INDENT 8
137 #define MAX_FPS 30
139 /* 12x12 bubbles (iPod Nano) */
140 #elif (LCD_HEIGHT == 132) && (LCD_WIDTH == 176)
141 #define XOFS 40
142 #define ROW_HEIGHT 10
143 #define ROW_INDENT 6
144 #define MAX_FPS 40
146 /* 12x12 bubbles (H100, H10, iAudio X5, iPod 3G, iPod 4G grayscale) */
147 #elif (LCD_HEIGHT == 128) && ((LCD_WIDTH == 160) || (LCD_WIDTH == 128))
148 #define XOFS 33
149 #define ROW_HEIGHT 10
150 #define ROW_INDENT 6
151 #define MAX_FPS 30
153 /* 10x10 bubbles (iPod Mini) */
154 #elif (LCD_HEIGHT == 110) && (LCD_WIDTH == 138)
155 #define XOFS 33
156 #define ROW_HEIGHT 8
157 #define ROW_INDENT 5
158 #define MAX_FPS 30
160 /* 9x9 bubbles (iAudio M3) */
161 #elif (LCD_HEIGHT == 96) && (LCD_WIDTH == 128)
162 #define XOFS 45
163 #define ROW_HEIGHT 7
164 #define ROW_INDENT 4
165 #define MAX_FPS 30
167 /* 8x8 bubbles (Sansa C200) */
168 #elif (LCD_HEIGHT == 80) && (LCD_WIDTH == 132)
169 #define XOFS 45
170 #define ROW_HEIGHT 6
171 #define ROW_INDENT 4
172 #define MAX_FPS 30
174 /* 8x7 bubbles (Archos recorder, Ondio) */
175 #elif (LCD_HEIGHT == 64) && (LCD_WIDTH == 112)
176 #define XOFS 33
177 #define ROW_HEIGHT 5
178 #define ROW_INDENT 4
179 #define MAX_FPS 20
181 #else
182 #error BUBBLES: Unsupported LCD type
183 #endif
185 #define TEXT_LINES (LCD_HEIGHT/8)
187 /* shot position */
188 #define SHOTX XOFS+ROW_INDENT+BUBBLE_WIDTH*3
189 #define SHOTY ROW_HEIGHT*(BB_HEIGHT-1)+BUBBLE_HEIGHT/2
191 /* collision distance squared */
192 #define MIN_DISTANCE ((BUBBLE_WIDTH*8)/10)*((BUBBLE_HEIGHT*8)/10)
194 /* global rockbox api */
195 static struct plugin_api* rb;
197 /* levels */
198 char level[NUM_LEVELS][BB_LEVEL_HEIGHT][BB_WIDTH] = {
199 {{ 6, 6, 4, 4, 2, 2, 3, 3},
200 { 6, 6, 4, 4, 2, 2, 3, -1},
201 { 2, 2, 3, 3, 6, 6, 4, 4},
202 { 2, 3, 3, 6, 6, 4, 4, -1},
203 {-1, -1, -1, -1, -1, -1, -1, -1},
204 {-1, -1, -1, -1, -1, -1, -1, -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, 7, 7, 7, 7, 7, 7, -1},
210 {-1, 1, 1, 1, 1, 1, -1, -1},
211 {-1, -1, 2, 2, 2, 2, -1, -1},
212 {-1, -1, -1, 2, -1, -1, -1, -1},
213 {-1, -1, -1, 2, 2, -1, -1, -1},
214 {-1, -1, -1, 5, -1, -1, -1, -1},
215 {-1, -1, -1, 5, 5, -1, -1, -1},
216 {-1, -1, -1, -1, -1, -1, -1, -1},
217 {-1, -1, -1, -1, -1, -1, -1, -1},
218 {-1, -1, -1, -1, -1, -1, -1, -1}},
219 {{-1, -1, 7, -1, -1, 7, -1, -1},
220 {-1, -1, 7, 1, 7, -1, -1, -1},
221 {-1, -1, -1, 1, 2, -1, -1, -1},
222 {-1, -1, 1, 2, 1, -1, -1, -1},
223 {-1, -1, -1, 2, 5, -1, -1, -1},
224 {-1, -1, 3, 5, 3, -1, -1, -1},
225 {-1, -1, -1, 5, 3, -1, -1, -1},
226 {-1, -1, -1, 3, -1, -1, -1, -1},
227 {-1, -1, -1, -1, -1, -1, -1, -1},
228 {-1, -1, -1, -1, -1, -1, -1, -1}},
229 {{-1, -1, -1, 0, 0, -1, -1, -1},
230 {-1, -1, 5, 0, 1, -1, -1, -1},
231 {-1, -1, 3, 5, 1, 6, -1, -1},
232 {-1, 4, 3, -1, 6, 7, -1, -1},
233 {-1, 7, 4, -1, -1, 7, 4, -1},
234 { 6, 7, -1, -1, -1, 4, 3, -1},
235 { 1, 6, -1, -1, -1, -1, 3, 5},
236 { 1, -1, -1, -1, -1, -1, 5, -1},
237 {-1, -1, -1, -1, -1, -1, -1, -1},
238 {-1, -1, -1, -1, -1, -1, -1, -1}},
239 {{-1, -1, 0, 0, 0, 0, -1, -1},
240 {-1, 0, 1, 1, 1, 0, -1, -1},
241 {-1, 0, 1, 0, 0, 1, 0, -1},
242 {-1, 0, 1, 1, 1, 0, -1, -1},
243 {-1, -1, 0, 0, 0, 0, -1, -1},
244 {-1, -1, 7, -1, 7, -1, -1, -1},
245 {-1, -1, 7, 7, 7, 7, -1, -1},
246 {-1, -1, -1, -1, -1, -1, -1, -1},
247 {-1, -1, -1, -1, -1, -1, -1, -1},
248 {-1, -1, -1, -1, -1, -1, -1, -1}},
249 {{-1, 4, 4, 4, 6, 6, 6, -1},
250 { 4, -1, -1, -1, -1, -1, 6, -1},
251 {-1, 4, -1, -1, -1, -1, 6, -1},
252 { 4, 2, 3, 1, 2, 3, 6, -1},
253 {-1, 3, 1, 2, 3, 1, 2, -1},
254 {-1, -1, -1, -1, -1, -1, -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, -1, -1, -1, -1, -1, -1, -1}},
259 {{-1, 4, 4, 4, 6, 6, 6, -1},
260 { 4, -1, -1, -1, -1, -1, 6, -1},
261 {-1, 4, -1, -1, -1, -1, 6, -1},
262 { 4, 2, 3, 1, 2, 3, 6, -1},
263 {-1, 3, 1, 2, 3, 1, 2, -1},
264 {-1, 2, 3, 1, 2, 3, -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, -1, -1, -1, -1, -1, -1, -1}},
269 {{-1, 0, 0, -1, -1, 2, 2, -1},
270 {-1, 5, -1, -1, -1, 3, -1, -1},
271 {-1, 0, -1, -1, -1, 6, -1, -1},
272 {-1, 3, -1, -1, -1, 0, -1, -1},
273 {-1, 4, -1, -1, -1, 5, -1, -1},
274 {-1, 2, -1, -1, -1, 3, -1, -1},
275 {-1, 2, -1, -1, -1, 1, -1, -1},
276 {-1, 3, -1, -1, -1, 4, -1, -1},
277 {-1, -1, -1, -1, -1, -1, -1, -1},
278 {-1, -1, -1, -1, -1, -1, -1, -1}},
279 {{ 3, -1, -1, -1, -1, -1, -1, 3},
280 { 6, 3, 2, 4, 6, 3, 2, -1},
281 { 4, -1, -1, -1, -1, -1, -1, 4},
282 { 2, 4, 6, 3, 2, 4, 6, -1},
283 {-1, -1, -1, 6, -1, -1, -1, -1},
284 {-1, -1, -1, 3, -1, -1, -1, -1},
285 {-1, -1, -1, -1, -1, -1, -1, -1},
286 {-1, -1, -1, -1, -1, -1, -1, -1},
287 {-1, -1, -1, -1, -1, -1, -1, -1},
288 {-1, -1, -1, -1, -1, -1, -1, -1}},
289 {{-1, 2, -1, 1, -1, 1, -1, 2},
290 { 1, 2, -1, 2, 1, -1, 1, -1},
291 { 1, -1, 1, -1, 2, -1, 2, -1},
292 { 2, 1, -1, 1, 2, -1, 2, -1},
293 {-1, 2, -1, 2, -1, 2, -1, 2},
294 { 1, 2, -1, 2, 1, -1, 1, -1},
295 { 1, -1, 1, -1, 2, -1, 1, -1},
296 { 2, 2, -1, 1, 1, -1, 2, -1},
297 {-1, 2, -1, 1, -1, 1, -1, 1},
298 {-1, -1, -1, -1, -1, -1, -1, -1}},
299 {{-1, 7, 7, -1, -1, 5, 5, -1},
300 { 1, -1, -1, -1, -1, -1, 4, -1},
301 { 2, 1, -1, -1, -1, -1, 4, 3},
302 { 2, -1, -1, -1, -1, -1, 3, -1},
303 { 1, 2, -1, -1, -1, -1, 3, 4},
304 { 1, -1, -1, -1, -1, -1, 4, -1},
305 { 7, 1, -1, -1, -1, -1, 4, 5},
306 { 7, 7, -1, -1, -1, 5, 5, -1},
307 {-1, -1, -1, -1, -1, -1, -1, -1},
308 {-1, -1, -1, -1, -1, -1, -1, -1}},
309 {{ 7, 7, -1, -1, -1, -1, 5, 5},
310 { 1, 5, -1, -1, -1, 7, 4, -1},
311 { 2, 1, -1, -1, -1, -1, 4, 3},
312 { 2, -1, -1, -1, -1, -1, 3, -1},
313 { 1, 5, -1, -1, -1, -1, 7, 4},
314 { 1, -1, -1, -1, -1, -1, 4, -1},
315 { 7, 1, -1, -1, -1, -1, 4, 5},
316 { 7, 5, -1, -1, -1, 7, 5, -1},
317 {-1, -1, -1, -1, -1, -1, -1, -1},
318 {-1, -1, -1, -1, -1, -1, -1, -1}},
319 {{-1, -1, -1, 0, 0, -1, -1, -1},
320 {-1, -1, 5, 0, 1, -1, -1, -1},
321 {-1, -1, 3, 5, 1, 6, -1, -1},
322 {-1, 4, 3, 2, 6, 2, -1, -1},
323 {-1, 7, 4, 7, 2, 2, 4, -1},
324 { 6, 7, 7, 3, 3, 4, 3, -1},
325 { 1, 6, 1, 1, 1, 3, 3, 5},
326 { 1, 1, -1, -1, -1, -1, 5, -1},
327 {-1, -1, -1, -1, -1, -1, -1, -1},
328 {-1, -1, -1, -1, -1, -1, -1, -1}},
329 {{-1, -1, 0, -1, -1, 0, -1, -1},
330 {-1, 3, 3, -1, 3, 3, -1, -1},
331 {-1, 0, 2, 0, 0, 2, 0, -1},
332 {-1, 3, 3, -1, 3, 3, -1, -1},
333 {-1, -1, 0, -1, -1, 0, -1, -1},
334 {-1, -1, -1, -1, -1, -1, -1, -1},
335 {-1, -1, -1, -1, -1, -1, -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, 2, 2, 2, -1, -1, -1},
341 {-1, -1, 3, 3, 3, 3, -1, -1},
342 {-1, 4, 4, 4, 4, 4, -1, -1},
343 {-1, 5, 5, 5, 5, 5, 5, -1},
344 {-1, -1, -1, 6, -1, -1, -1, -1},
345 {-1, -1, -1, 7, 7, -1, -1, -1},
346 {-1, -1, -1, 0, -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, -1, 2, 5, -1, -1, -1},
350 {-1, 4, 3, -1, -1, -1, -1, -1},
351 { 6, 7, -1, 5, 2, -1, -1, -1},
352 {-1, -1, -1, -1, 3, 4, -1, -1},
353 {-1, -1, -1, 2, 5, -1, 7, 6},
354 {-1, 4, 3, -1, -1, -1, -1, -1},
355 { 6, 7, -1, 5, 2, -1, -1, -1},
356 {-1, -1, -1, -1, 3, 4, -1, -1},
357 {-1, -1, -1, -1, -1, -1, 7, 6},
358 {-1, -1, -1, -1, -1, -1, -1, -1}},
359 {{-1, -1, -1, 5, 5, -1, -1, -1},
360 {-1, -1, -1, 3, -1, -1, -1, -1},
361 {-1, -1, -1, 1, -1, -1, -1, -1},
362 {-1, -1, -1, 7, -1, -1, -1, -1},
363 {-1, -1, -1, 2, -1, -1, -1, -1},
364 {-1, -1, -1, 4, -1, -1, -1, -1},
365 {-1, -1, -1, 5, -1, -1, -1, -1},
366 {-1, -1, -1, 3, -1, -1, -1, -1},
367 {-1, -1, -1, -1, -1, -1, -1, -1},
368 {-1, -1, -1, -1, -1, -1, -1, -1}},
369 {{-1, -1, -1, 0, 1, -1, -1, -1},
370 {-1, -1, 0, 2, 7, 7, -1, -1},
371 {-1, -1, -1, 0, 1, 7, -1, -1},
372 {-1, 0, 0, 0, 0, -1, -1, -1},
373 {-1, 0, 0, 0, 1, 1, -1, -1},
374 { 0, 0, 0, 1, 1, 1, -1, -1},
375 {-1, 0, 0, 1, 1, 1, -1, -1},
376 {-1, 0, 0, 0, 7, 7, -1, -1},
377 {-1, -1, 7, 7, -1, -1, -1, -1},
378 {-1, -1, -1, -1, -1, -1, -1, -1}},
379 {{-1, 1, -1, -1, -1, -1, -1, -1},
380 { 1, -1, -1, -1, -1, -1, -1, -1},
381 {-1, 2, 3, 4, 7, 6, 5, -1},
382 {-1, -1, -1, -1, -1, -1, 1, -1},
383 {-1, -1, -1, -1, -1, -1, 1, -1},
384 {-1, 2, 3, 4, 7, 6, -1, -1},
385 {-1, 1, -1, -1, -1, -1, -1, -1},
386 { 1, -1, -1, -1, -1, -1, -1, -1},
387 {-1, 2, 3, 4, 7, 6, 5, -1},
388 {-1, -1, -1, -1, -1, -1, -1, -1}},
389 {{-1, 6, -1, -1, -1, -1, -1, -1},
390 { 5, -1, -1, -1, -1, -1, -1, -1},
391 { 2, 3, 4, 7, 6, 5, 2, 3},
392 {-1, -1, -1, -1, -1, -1, 4, -1},
393 {-1, -1, -1, -1, -1, -1, 7, -1},
394 {-1, 4, 3, 2, 5, 6, -1, -1},
395 {-1, 7, -1, -1, -1, -1, -1, -1},
396 { 6, -1, -1, -1, -1, -1, -1, -1},
397 { 5, 2, 3, 4, 7, 6, 5, -1},
398 {-1, -1, -1, -1, -1, -1, -1, -1}},
399 {{ 3, 2, 1, 0, 0, 1, 2, 3},
400 { 3, 2, 1, 0, 1, 2, 3, -1},
401 { 4, 3, 2, 1, 1, 2, 3, 4},
402 { 4, 3, 2, 1, 2, 3, 4, -1},
403 { 5, 4, 3, 2, 2, 3, 4, 5},
404 { 5, 4, 3, 2, 3, 4, 5, -1},
405 { 6, 5, 4, 3, 3, 4, 5, 6},
406 { 6, 5, 4, 3, 4, 5, 6, -1},
407 { 7, 6, 5, 4, 4, 5, 6, 7},
408 {-1, -1, -1, -1, -1, -1, -1, -1}},
409 {{-1, -1, -1, 5, 5, -1, -1, -1},
410 {-1, -1, -1, 3, -1, -1, -1, -1},
411 {-1, -1, -1, 2, 4, -1, -1, -1},
412 {-1, -1, -1, 6, -1, -1, -1, -1},
413 {-1, -1, -1, 2, 4, -1, -1, -1},
414 {-1, 2, -1, 5, -1, 4, -1, -1},
415 { 1, 0, 1, 0, 1, 0, 1, 0},
416 { 3, -1, 3, -1, 2, -1, 6, -1},
417 {-1, -1, -1, -1, -1, -1, -1, -1},
418 {-1, -1, -1, -1, -1, -1, -1, -1}},
419 {{-1, -1, -1, -1, 1, -1, -1, -1},
420 { 7, 4, 3, 5, -1, -1, -1, -1},
421 { 6, -1, -1, 1, -1, -1, -1, -1},
422 {-1, -1, -1, 5, 3, 4, 7, -1},
423 { 6, -1, -1, -1, 1, -1, -1, 6},
424 { 7, 4, 3, 5, -1, -1, -1, -1},
425 {-1, -1, -1, 1, -1, -1, -1, 6},
426 {-1, -1, -1, 5, 3, 4, 7, -1},
427 {-1, -1, -1, -1, -1, -1, -1, -1},
428 {-1, -1, -1, -1, -1, -1, -1, -1}},
429 {{-1, -1, -1, -1, 7, 3, 6, -1},
430 {-1, -1, 3, 7, 3, 6, 3, -1},
431 {-1, -1, 5, 7, 3, 6, 3, -1},
432 {-1, 6, 7, 3, 6, 7, -1, -1},
433 {-1, 7, 7, 3, 6, 1, -1, -1},
434 { 3, 7, 3, 6, 3, -1, -1, -1},
435 { 5, 6, 2, 7, 1, -1, -1, -1},
436 {-1, -1, -1, -1, -1, -1, -1, -1},
437 {-1, -1, -1, -1, -1, -1, -1, -1},
438 {-1, -1, -1, -1, -1, -1, -1, -1}},
439 {{ 5, -1, -1, -1, -1, -1, -1, 5},
440 { 5, -1, 6, 6, 6, -1, 5, -1},
441 {-1, 5, 4, -1, -1, 4, 5, -1},
442 {-1, 3, -1, -1, -1, 3, -1, -1},
443 {-1, 6, 0, -1, -1, 0, 6, -1},
444 {-1, 3, -1, -1, -1, 3, -1, -1},
445 {-1, -1, 4, -1, -1, 4, -1, -1},
446 {-1, -1, 6, 6, 6, -1, -1, -1},
447 {-1, -1, -1, -1, -1, -1, -1, -1},
448 {-1, -1, -1, -1, -1, -1, -1, -1}},
449 {{-1, 7, 0, -1, -1, 0, 7, -1},
450 { 7, -1, 0, -1, 0, -1, 7, -1},
451 { 7, 1, -1, 0, 0, -1, 1, 7},
452 { 7, 1, 2, 0, 2, 1, 7, -1},
453 { 7, 6, 3, 2, 2, 3, 6, 7},
454 { 7, -1, 3, 2, 3, -1, 7, -1},
455 {-1, 7, 7, 3, 3, 7, 7, -1},
456 {-1, -1, -1, 3, -1, -1, -1, -1},
457 {-1, -1, -1, -1, -1, -1, -1, -1},
458 {-1, -1, -1, -1, -1, -1, -1, -1}},
459 {{-1, 3, -1, 1, -1, 7, -1, 6},
460 { 5, -1, 7, -1, 7, -1, 6, -1},
461 { 6, -1, 0, -1, 5, -1, 3, -1},
462 {-1, 2, -1, 1, -1, 5, -1, -1},
463 {-1, 4, -1, 3, -1, 4, -1, -1},
464 { 2, -1, 3, -1, 2, -1, -1, -1},
465 {-1, -1, 4, -1, 6, -1, -1, -1},
466 {-1, -1, -1, 5, -1, -1, -1, -1},
467 {-1, -1, -1, -1, -1, -1, -1, -1},
468 {-1, -1, -1, -1, -1, -1, -1, -1}},
469 {{-1, -1, -1, -1, 1, -1, -1, -1},
470 {-1, -1, -1, -1, 3, -1, -1, -1},
471 { 6, 1, 3, 1, 2, 1, 4, 1},
472 {-1, -1, -1, -1, 6, -1, -1, -1},
473 {-1, -1, -1, 4, 1, -1, -1, -1},
474 {-1, -1, 1, -1, 3, -1, -1, -1},
475 {-1, -1, -1, 2, 1, -1, -1, -1},
476 {-1, -1, -1, -1, 4, -1, -1, -1},
477 {-1, -1, -1, 6, 1, -1, -1, -1},
478 {-1, -1, -1, 6, -1, -1, -1, -1}},
479 {{-1, -1, -1, 5, 4, -1, -1, -1},
480 {-1, -1, 4, 1, 0, -1, -1, -1},
481 {-1, -1, -1, 2, 3, -1, -1, -1},
482 {-1, 1, 4, -1, 2, 2, -1, -1},
483 {-1, 3, 1, 2, 5, 1, 4, -1},
484 {-1, 4, 2, -1, 0, 4, -1, -1},
485 {-1, -1, -1, -1, -1, -1, -1, -1},
486 {-1, -1, -1, -1, -1, -1, -1, -1},
487 {-1, -1, -1, -1, -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, 2, -1, -1, 1, -1, 5, -1},
492 { 5, -1, -1, 1, -1, -1, 0, -1},
493 {-1, 6, -1, -1, 1, -1, 4, -1},
494 {-1, 0, -1, 1, -1, 5, -1, -1},
495 {-1, -1, 5, 5, 0, 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, 6, 3, -1, -1, -1},
500 {-1, -1, 3, 2, 6, -1, -1, -1},
501 {-1, -1, 2, 6, 3, 2, -1, -1},
502 {-1, 6, 3, 2, 6, 3, -1, -1},
503 {-1, 3, 2, 6, 3, 2, 6, -1},
504 { 2, 6, 3, 2, 6, 3, 2, -1},
505 { 6, 3, 2, 6, 3, 2, 6, 3},
506 {-1, -1, -1, -1, -1, -1, -1, -1},
507 {-1, -1, -1, -1, -1, -1, -1, -1},
508 {-1, -1, -1, -1, -1, -1, -1, -1}},
509 {{ 6, 6, 6, 6, 6, 6, 6, 6},
510 { 4, -1, -1, -1, -1, -1, -1, -1},
511 {-1, 3, 2, 5, 7, 6, 4, 3},
512 {-1, 5, -1, -1, -1, -1, -1, -1},
513 {-1, -1, 7, 6, 4, 3, 2, 5},
514 {-1, -1, 4, -1, -1, -1, -1, -1},
515 {-1, -1, -1, 3, 2, 5, 7, 6},
516 {-1, -1, -1, -1, -1, -1, -1, -1},
517 {-1, -1, -1, -1, -1, -1, -1, -1},
518 {-1, -1, -1, -1, -1, -1, -1, -1}},
519 {{ 1, -1, 7, -1, -1, 6, -1, 2},
520 { 6, -1, 1, -1, 6, 1, 3, -1},
521 {-1, 4, -1, 7, 2, -1, 7, -1},
522 { 2, 7, -1, -1, -1, 4, -1, -1},
523 { 6, -1, 3, 5, 0, 2, -1, 7},
524 { 1, -1, -1, -1, -1, -1, 1, -1},
525 {-1, 1, 4, 5, 7, 5, 1, -1},
526 {-1, -1, -1, -1, -1, -1, -1, -1},
527 {-1, -1, -1, -1, -1, -1, -1, -1},
528 {-1, -1, -1, -1, -1, -1, -1, -1}},
529 {{ 6, 6, 6, -1, -1, 6, 6, 6},
530 {-1, -1, 6, -1, 6, -1, -1, -1},
531 {-1, -1, 2, 3, 3, 2, -1, -1},
532 {-1, 3, -1, 5, -1, 3, -1, -1},
533 {-1, -1, 5, 3, 3, 5, -1, -1},
534 {-1, -1, 6, 1, 6, -1, -1, -1},
535 {-1, 4, 2, -1, -1, 2, 4, -1},
536 {-1, -1, -1, -1, -1, -1, -1, -1},
537 {-1, -1, -1, -1, -1, -1, -1, -1},
538 {-1, -1, -1, -1, -1, -1, -1, -1}},
539 {{-1, -1, -1, 5, 5, -1, -1, -1},
540 {-1, -1, 5, -1, -1, -1, -1, -1},
541 {-1, 3, 4, 6, 6, -1, -1, 5},
542 { 3, 3, 4, 6, 5, -1, 5, -1},
543 { 3, 2, 3, 6, 6, 5, 5, -1},
544 { 3, 3, 4, 6, 5, -1, 5, -1},
545 {-1, 3, 4, 6, 6, -1, -1, 5},
546 {-1, -1, 5, -1, -1, -1, -1, -1},
547 {-1, -1, -1, 5, 5, -1, -1, -1},
548 {-1, -1, -1, -1, -1, -1, -1, -1}},
549 {{ 1, -1, -1, -1, -1, -1, -1, 1},
550 { 1, -1, 2, 2, 2, -1, 1, -1},
551 {-1, 1, 2, 3, 3, 2, 1, -1},
552 { 6, 2, 3, -1, 3, 2, 6, -1},
553 { 6, 2, 3, -1, -1, 3, 2, 6},
554 { 6, 2, 3, -1, 3, 2, 6, -1},
555 { 3, 3, 3, 7, 7, 3, 3, 3},
556 { 0, 5, 0, 2, 0, 5, 0, -1},
557 {-1, -1, -1, -1, -1, -1, -1, -1},
558 {-1, -1, -1, -1, -1, -1, -1, -1}},
559 {{-1, -1, 7, 7, 7, -1, -1, -1},
560 {-1, 7, 2, 2, 7, -1, -1, -1},
561 {-1, 7, 5, 5, 5, 7, -1, -1},
562 { 7, 7, 7, 7, 7, 7, -1, -1},
563 {-1, -1, 6, -1, 6, -1, -1, -1},
564 {-1, 6, -1, -1, 6, -1, -1, -1},
565 {-1, 6, 4, 4, -1, 6, 4, 4},
566 {-1, -1, -1, -1, -1, -1, -1, -1},
567 {-1, -1, -1, -1, -1, -1, -1, -1},
568 {-1, -1, -1, -1, -1, -1, -1, -1}},
569 {{-1, 3, 3, -1, 3, 3, 3, -1},
570 { 3, 7, 5, 4, 6, 5, 3, -1},
571 { 1, 3, 3, 3, -1, 3, 3, 1},
572 { 2, 1, 2, 1, 2, 1, 2, -1},
573 { 1, 3, 3, -1, 3, 3, 3, 1},
574 { 3, 5, 6, 4, 5, 7, 3, -1},
575 { 2, 3, 3, 3, -1, 3, 3, 2},
576 { 1, 1, 2, 2, 2, 1, 1, -1},
577 {-1, -1, -1, -1, -1, -1, -1, -1},
578 {-1, -1, -1, -1, -1, -1, -1, -1}},
579 {{-1, 6, 5, -1, -1, -1, -1, -1},
580 { 3, 1, 3, -1, -1, -1, -1, -1},
581 {-1, 5, 6, -1, -1, -1, -1, -1},
582 {-1, -1, 5, 3, -1, -1, -1, -1},
583 {-1, -1, 6, 1, 6, -1, -1, -1},
584 {-1, -1, 3, 5, -1, -1, -1, -1},
585 {-1, -1, -1, -1, 3, 6, -1, -1},
586 {-1, -1, -1, 5, 6, 5, -1, -1},
587 {-1, -1, -1, -1, 6, 3, -1, -1},
588 {-1, -1, -1, -1, -1, -1, -1, -1}},
589 {{ 6, 3, 7, 4, 5, 1, 6, 3},
590 { 5, 1, 6, 3, 7, 4, 5, -1},
591 { 6, 3, 7, 4, 5, 1, 6, 3},
592 {-1, -1, -1, -1, -1, -1, -1, -1},
593 {-1, -1, -1, -1, -1, -1, -1, -1},
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, 4, 4},
600 {-1, -1, 7, 7, 7, 4, 4, -1},
601 {-1, -1, -1, -1, -1, -1, 4, 4},
602 {-1, 1, -1, -1, -1, 7, -1, -1},
603 {-1, 1, 1, -1, -1, 7, -1, -1},
604 { 3, 3, 3, -1, 7, -1, -1, -1},
605 { 3, -1, 2, 3, 3, 3, -1, 3},
606 {-1, 2, -1, 3, -1, 3, 3, -1},
607 {-1, 2, -1, -1, -1, -1, -1, -1},
608 {-1, -1, -1, -1, -1, -1, -1, -1}},
609 {{-1, -1, 4, -1, -1, -1, -1, -1},
610 {-1, 7, 4, -1, -1, -1, -1, -1},
611 {-1, -1, 7, 4, -1, -1, -1, -1},
612 {-1, 4, 7, 4, -1, -1, -1, -1},
613 { 1, 1, 1, 1, 1, 1, 1, -1},
614 { 1, 2, 1, 2, 1, 1, -1, -1},
615 { 2, 2, 2, 2, 2, 2, 2, 2},
616 {-1, -1, -1, -1, -1, -1, -1, -1},
617 {-1, -1, -1, -1, -1, -1, -1, -1},
618 {-1, -1, -1, -1, -1, -1, -1, -1}},
619 {{ 0, -1, -1, -1, -1, -1, -1, 6},
620 { 6, 1, 4, 3, 7, 5, 0, -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 {-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 {-1, -1, -1, -1, -1, -1, -1, -1}},
629 {{ 3, 3, 4, 6, 6, 4, 3, 3},
630 { 0, 3, 4, 6, 4, 3, 1, -1},
631 { 5, 1, 3, 4, 4, 3, 0, 1},
632 { 0, 1, 3, 4, 3, 1, 0, -1},
633 { 2, 1, 6, 3, 3, 0, 0, 1},
634 { 0, 3, 4, 3, 6, 1, 5, -1},
635 { 6, 1, 2, 6, 4, 0, 0, 2},
636 {-1, -1, -1, -1, -1, -1, -1, -1},
637 {-1, -1, -1, -1, -1, -1, -1, -1},
638 {-1, -1, -1, -1, -1, -1, -1, -1}},
639 {{ 6, 6, -1, -1, -1, -1, 4, 4},
640 { 4, 0, -1, -1, -1, 3, 6, -1},
641 { 0, 6, -1, -1, -1, -1, 4, 2},
642 { 7, -1, -1, -1, -1, -1, 7, -1},
643 { 4, 4, -1, -1, -1, -1, 5, 6},
644 { 6, 4, 7, 7, 5, 6, 4, -1},
645 {-1, 7, 6, 4, 6, 4, 7, -1},
646 {-1, 0, -1, 7, -1, 7, -1, -1},
647 {-1, -1, -1, -1, -1, -1, -1, -1},
648 {-1, -1, -1, -1, -1, -1, -1, -1}},
649 {{-1, 5, -1, -1, -1, -1, 4, -1},
650 {-1, 5, -1, -1, -1, 4, -1, -1},
651 {-1, -1, 5, 6, 6, 4, -1, -1},
652 {-1, -1, 2, -1, 2, -1, -1, -1},
653 { 0, 0, 6, -1, -1, 6, 1, 1},
654 {-1, -1, 2, -1, 2, -1, -1, -1},
655 {-1, -1, 7, 6, 6, 3, -1, -1},
656 {-1, 7, -1, -1, -1, 3, -1, -1},
657 {-1, 7, -1, -1, -1, -1, 3, -1},
658 {-1, -1, -1, -1, -1, -1, -1, -1}},
659 {{-1, 6, -1, -1, -1, -1, 2, -1},
660 { 1, 7, 1, 1, 1, 3, 1, -1},
661 {-1, -1, 4, 1, 1, 4, -1, -1},
662 {-1, 1, 3, 1, 7, 1, -1, -1},
663 {-1, -1, -1, 2, 6, -1, -1, -1},
664 {-1, -1, 1, 5, 1, -1, -1, -1},
665 {-1, -1, -1, -1, -1, -1, -1, -1},
666 {-1, -1, -1, -1, -1, -1, -1, -1},
667 {-1, -1, -1, -1, -1, -1, -1, -1},
668 {-1, -1, -1, -1, -1, -1, -1, -1}},
669 {{ 7, 7, 7, 7, 7, 7, 7, 7},
670 { 7, -1, -1, -1, -1, -1, 7, -1},
671 { 7, -1, -1, 2, 0, 5, 2, 2},
672 { 7, -1, -1, -1, 0, 3, 6, -1},
673 { 7, -1, -1, -1, -1, -1, 4, 0},
674 { 5, 5, -1, -1, -1, -1, -1, -1},
675 { 4, 3, 6, 2, -1, -1, -1, -1},
676 { 0, 2, 0, 4, -1, -1, -1, -1},
677 {-1, -1, -1, -1, -1, -1, -1, -1},
678 {-1, -1, -1, -1, -1, -1, -1, -1}},
679 {{-1, -1, 1, -1, -1, 1, -1, -1},
680 {-1, 4, -1, -1, 5, -1, -1, -1},
681 {-1, 7, -1, -1, 1, 1, 1, -1},
682 { 6, -1, -1, -1, -1, 7, -1, -1},
683 { 1, 1, 1, 1, -1, 4, -1, -1},
684 {-1, -1, 5, -1, -1, -1, -1, -1},
685 {-1, -1, 0, -1, -1, -1, -1, -1},
686 {-1, 3, -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, 7, 7, -1, -1, 7, 7, -1},
690 { 6, -1, 4, -1, 4, -1, 6, -1},
691 { 5, -1, -1, 3, 3, -1, -1, 5},
692 { 6, -1, -1, -1, -1, -1, 6, -1},
693 {-1, 7, -1, -1, -1, -1, 7, -1},
694 {-1, 4, -1, -1, -1, 4, -1, -1},
695 {-1, -1, 3, -1, -1, 3, -1, -1},
696 {-1, -1, 2, -1, 2, -1, -1, -1},
697 {-1, -1, -1, 5, 5, -1, -1, -1},
698 {-1, -1, -1, -1, -1, -1, -1, -1}},
699 {{-1, 0, 0, -1, -1, 0, 0, -1},
700 { 7, 4, 6, 6, 6, 4, 3, -1},
701 { 5, 6, 6, 6, 2, 6, 6, 3},
702 { 7, 4, 6, 6, 6, 4, 3, -1},
703 {-1, 0, 0, -1, -1, 0, 0, -1},
704 {-1, -1, -1, -1, -1, -1, -1, -1},
705 {-1, -1, -1, -1, -1, -1, -1, -1},
706 {-1, -1, -1, -1, -1, -1, -1, -1},
707 {-1, -1, -1, -1, -1, -1, -1, -1},
708 {-1, -1, -1, -1, -1, -1, -1, -1}},
709 {{-1, -1, -1, -1, -1, 7, 7, 7},
710 {-1, -1, -1, -1, 2, 7, 7, -1},
711 {-1, 0, 7, 7, 7, -1, 7, 7},
712 { 6, 7, 7, 7, -1, -1, -1, -1},
713 { 6, -1, -1, -1, 7, 7, 7, 7},
714 { 6, -1, -1, -1, -1, -1, -1, -1},
715 { 4, 2, 2, 2, 4, -1, 3, -1},
716 { 4, 4, 4, 4, 3, 3, 3, -1},
717 {-1, -1, -1, -1, -1, -1, -1, -1},
718 {-1, -1, -1, -1, -1, -1, -1, -1}},
719 {{ 4, -1, -1, 7, -1, 6, -1, 7},
720 { 7, 6, 7, -1, -1, 7, 4, -1},
721 {-1, -1, 7, -1, -1, 7, -1, -1},
722 {-1, 0, 0, 0, 0, 0, 3, -1},
723 {-1, -1, 0, 2, 2, 0, 6, 4},
724 {-1, -1, 0, 0, 0, 1, 3, -1},
725 {-1, -1, -1, 0, 0, -1, 3, 4},
726 {-1, -1, -1, 6, -1, 5, 6, -1},
727 {-1, -1, -1, -1, -1, -1, 1, 0},
728 {-1, -1, -1, -1, -1, -1, -1, -1}},
729 {{-1, 5, -1, -1, -1, -1, 5, -1},
730 { 0, -1, -1, 0, -1, -1, 0, -1},
731 { 0, 0, 0, 2, 2, 0, 0, 0},
732 { 0, -1, -1, 0, -1, -1, 0, -1},
733 {-1, 7, -1, 3, -1, -1, 7, -1},
734 {-1, -1, 3, 6, -1, -1, -1, -1},
735 {-1, -1, -1, 6, -1, -1, -1, -1},
736 {-1, 3, 6, -1, -1, -1, -1, -1},
737 {-1, 3, -1, -1, -1, -1, -1, -1},
738 {-1, -1, -1, -1, -1, -1, -1, -1}},
739 {{-1, -1, -1, 6, 5, -1, -1, -1},
740 {-1, -1, 2, 6, 3, -1, -1, -1},
741 {-1, -1, 5, 4, 7, 1, -1, -1},
742 {-1, 6, 2, 2, 3, 4, -1, -1},
743 {-1, -1, 3, 7, 3, 6, -1, -1},
744 {-1, -1, 1, 3, 2, -1, -1, -1},
745 {-1, -1, -1, 4, 5, -1, -1, -1},
746 {-1, -1, -1, 4, -1, -1, -1, -1},
747 {-1, -1, -1, -1, -1, -1, -1, -1},
748 {-1, -1, -1, -1, -1, -1, -1, -1}},
749 {{ 7, 7, -1, 2, 2, -1, 6, 6},
750 { 6, -1, -1, 6, -1, -1, 3, -1},
751 { 2, -1, -1, 1, -1, -1, 2, -1},
752 { 5, -1, -1, 3, -1, -1, 2, -1},
753 { 1, -1, -1, 2, -1, -1, 1, -1},
754 { 5, -1, -1, 2, -1, -1, 2, -1},
755 { 6, -1, -1, 1, -1, -1, 7, -1},
756 { 5, -1, -1, 5, -1, -1, 4, -1},
757 {-1, -1, -1, -1, -1, -1, -1, -1},
758 {-1, -1, -1, -1, -1, -1, -1, -1}},
759 {{-1, -1, -1, 6, 6, -1, -1, -1},
760 {-1, 0, 4, 4, 4, 0, -1, -1},
761 {-1, -1, -1, 6, 6, -1, -1, -1},
762 {-1, -1, 2, 7, 2, -1, -1, -1},
763 {-1, -1, -1, 6, 6, -1, -1, -1},
764 {-1, 0, 5, 5, 5, 0, -1, -1},
765 {-1, -1, -1, 3, 3, -1, -1, -1},
766 {-1, -1, -1, -1, -1, -1, -1, -1},
767 {-1, -1, -1, -1, -1, -1, -1, -1},
768 {-1, -1, -1, -1, -1, -1, -1, -1}},
769 {{-1, -1, 4, 1, 3, -1, -1, -1},
770 {-1, 1, -1, -1, 1, -1, -1, -1},
771 {-1, -1, 4, 1, 3, 4, 1, -1},
772 {-1, 1, 3, 4, -1, -1, 4, -1},
773 {-1, 3, -1, -1, 3, 4, 1, -1},
774 {-1, 1, 3, 4, 1, 3, -1, -1},
775 {-1, -1, 4, 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, -1, -1, -1, -1, -1, -1}},
779 {{-1, 6, 4, -1, 3, 2, 5, -1},
780 { 0, -1, -1, -1, -1, -1, 1, -1},
781 {-1, 2, 3, 5, -1, 4, 6, -1},
782 { 0, -1, -1, -1, -1, -1, 1, -1},
783 {-1, 4, 6, -1, 2, 5, 3, -1},
784 { 0, -1, -1, -1, -1, -1, 1, -1},
785 {-1, 5, 2, 3, -1, 4, 6, -1},
786 {-1, -1, -1, -1, -1, -1, -1, -1},
787 {-1, -1, -1, -1, -1, -1, -1, -1},
788 {-1, -1, -1, -1, -1, -1, -1, -1}},
789 {{-1, -1, -1, 6, 6, -1, -1, -1},
790 {-1, -1, 7, 6, 4, -1, -1, -1},
791 {-1, 2, 1, 7, 4, 1, 3, -1},
792 { 2, 1, 1, 1, 1, 1, 3, -1},
793 {-1, 2, 2, 2, 3, 3, 3, -1},
794 {-1, -1, -1, 5, -1, -1, -1, -1},
795 {-1, -1, -1, 2, 3, -1, -1, -1},
796 {-1, -1, -1, 5, -1, -1, -1, -1},
797 {-1, -1, 2, 2, 3, 3, -1, -1},
798 {-1, -1, -1, -1, -1, -1, -1, -1}},
799 {{ 4, -1, 5, -1, -1, 3, -1, 6},
800 { 2, -1, 3, -1, 2, -1, 4, -1},
801 { 4, -1, -1, 1, 0, -1, -1, 6},
802 { 6, -1, 2, 3, 5, -1, 4, -1},
803 { 4, -1, -1, 0, 1, -1, -1, 6},
804 { 2, -1, 5, -1, 3, -1, 4, -1},
805 { 4, -1, 3, -1, -1, 2, -1, 6},
806 { 6, -1, -1, -1, -1, -1, 4, -1},
807 {-1, -1, -1, -1, -1, -1, -1, -1},
808 {-1, -1, -1, -1, -1, -1, -1, -1}},
809 {{ 2, 6, 0, 5, 5, 1, 3, 4},
810 { 1, -1, -1, 2, -1, -1, 0, -1},
811 { 4, -1, -1, 3, 6, -1, -1, 2},
812 {-1, -1, -1, 0, -1, -1, -1, -1},
813 {-1, -1, -1, 1, 4, -1, -1, -1},
814 {-1, -1, -1, 2, -1, -1, -1, -1},
815 {-1, -1, -1, 6, 3, -1, -1, -1},
816 {-1, -1, -1, 5, -1, -1, -1, -1},
817 {-1, -1, -1, 4, 1, -1, -1, -1},
818 {-1, -1, -1, -1, -1, -1, -1, -1}},
819 {{-1, -1, -1, -1, 5, 1, 1, 3},
820 { 0, 5, 1, 0, 5, 3, 3, -1},
821 { 5, 1, 0, 5, 1, 0, 5, 1},
822 { 0, 5, 1, 0, 5, 1, 6, -1},
823 {-1, -1, -1, -1, 1, 6, 5, 1},
824 {-1, -1, -1, -1, 5, 1, 6, -1},
825 {-1, -1, -1, -1, 1, 0, 5, 1},
826 {-1, -1, -1, -1, 5, 1, 0, -1},
827 {-1, -1, -1, -1, -1, -1, -1, -1},
828 {-1, -1, -1, -1, -1, -1, -1, -1}},
829 {{-1, 0, 7, 3, -1, -1, 2, 2},
830 {-1, 0, 7, 3, -1, -1, 2, -1},
831 {-1, 0, 7, 3, -1, -1, 2, 2},
832 {-1, 0, 7, 3, -1, 3, 1, -1},
833 {-1, 0, 7, 3, -1, 6, 4, 5},
834 {-1, 0, 7, 3, -1, 7, 0, -1},
835 {-1, 0, 7, 3, -1, 2, 3, 4},
836 {-1, 0, 7, 3, -1, 5, 6, -1},
837 {-1, -1, -1, -1, -1, 7, 0, 1},
838 {-1, -1, -1, -1, -1, -1, -1, -1}},
839 {{-1, -1, -1, 7, 7, 7, 7, -1},
840 { 3, 4, 5, -1, -1, -1, 7, -1},
841 { 2, -1, -1, -1, -1, -1, -1, 3},
842 { 7, -1, -1, -1, -1, -1, 4, -1},
843 { 7, -1, -1, -1, 3, 4, 5, 6},
844 { 7, -1, -1, 2, 0, 1, 2, -1},
845 { 6, -1, -1, -1, 3, 4, 5, 6},
846 { 0, 1, -1, -1, -1, -1, -1, -1},
847 { 2, 3, 4, -1, -1, -1, -1, -1},
848 { 5, 6, 0, -1, -1, -1, -1, -1}},
849 {{-1, 7, -1, -1, -1, -1, 2, -1},
850 { 1, 1, -1, -1, -1, 3, 3, -1},
851 {-1, 2, -1, -1, -1, -1, 4, -1},
852 { 3, 3, -1, -1, -1, 5, 5, -1},
853 {-1, 4, -1, -1, -1, -1, 6, -1},
854 { 5, 5, -1, -1, -1, 1, 1, -1},
855 {-1, 6, -1, -1, -1, -1, 7, -1},
856 {-1, -1, -1, -1, -1, -1, -1, -1},
857 {-1, -1, -1, -1, -1, -1, -1, -1},
858 {-1, -1, -1, -1, -1, -1, -1, -1}},
859 {{-1, 4, -1, -1, -1, -1, 4, -1},
860 { 2, -1, -1, 1, -1, -1, 2, -1},
861 { 5, -1, -1, 0, 0, -1, -1, 5},
862 { 5, -1, -1, 1, -1, -1, 6, -1},
863 {-1, 4, 2, 7, 7, 5, 4, -1},
864 {-1, -1, -1, 6, -1, -1, -1, -1},
865 {-1, -1, -1, 3, 3, -1, -1, -1},
866 {-1, -1, -1, 7, -1, -1, -1, -1},
867 {-1, -1, -1, -1, -1, -1, -1, -1},
868 {-1, -1, -1, -1, -1, -1, -1, -1}},
869 {{-1, 1, -1, -1, 2, 3, 4, -1},
870 { 2, -1, -1, 3, 0, 4, -1, -1},
871 { 4, -1, -1, 2, 3, 1, -1, -1},
872 { 3, -1, 4, 3, 0, -1, -1, -1},
873 { 4, -1, -1, 2, 5, 1, -1, -1},
874 { 3, -1, 4, 5, 0, 4, -1, -1},
875 {-1, -1, -1, -1, -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, -1, -1, -1, -1}},
879 {{ 2, -1, -1, 1, 1, -1, -1, 2},
880 { 2, -1, 3, 3, 3, -1, 2, -1},
881 {-1, 2, -1, 4, 4, -1, 2, -1},
882 {-1, 7, 7, 0, 7, 7, -1, -1},
883 {-1, -1, -1, 4, 4, -1, -1, -1},
884 {-1, -1, 5, 7, 5, -1, -1, -1},
885 { 6, 3, 2, 6, 4, 2, 3, 6},
886 { 5, -1, -1, -1, -1, -1, 1, -1},
887 {-1, -1, -1, -1, -1, -1, -1, -1},
888 {-1, -1, -1, -1, -1, -1, -1, -1}},
889 {{ 4, 2, 3, 5, 7, 1, 3, 6},
890 { 1, -1, -1, 1, -1, -1, 1, -1},
891 { 3, 0, 1, 3, 2, 4, 3, 5},
892 { 4, -1, -1, 4, -1, -1, 4, -1},
893 {-1, 5, -1, -1, 5, -1, -1, 5},
894 { 0, 3, 2, 0, 4, 5, 0, -1},
895 {-1, 6, -1, -1, 6, -1, -1, 6},
896 { 7, -1, -1, 7, -1, -1, 7, -1},
897 {-1, -1, -1, -1, -1, -1, -1, -1},
898 {-1, -1, -1, -1, -1, -1, -1, -1}},
899 {{-1, 5, 4, -1, 1, 1, -1, -1},
900 { 5, -1, 4, 1, -1, 1, -1, -1},
901 { 0, -1, -1, -1, -1, -1, 0, -1},
902 { 0, 6, 4, -1, -1, 4, 2, -1},
903 {-1, 4, 3, 5, 2, 6, 3, 6},
904 {-1, 2, 6, -1, -1, 5, 4, -1},
905 {-1, -1, -1, -1, -1, -1, -1, -1},
906 {-1, -1, -1, -1, -1, -1, -1, -1},
907 {-1, -1, -1, -1, -1, -1, -1, -1},
908 {-1, -1, -1, -1, -1, -1, -1, -1}},
909 {{-1, -1, -1, 6, 6, -1, -1, -1},
910 {-1, -1, 5, 5, 4, -1, -1, -1},
911 {-1, -1, 1, 6, 6, 4, -1, -1},
912 {-1, 1, 7, 2, 5, 3, -1, -1},
913 {-1, 2, 7, 2, 1, 5, 3, -1},
914 { 2, 1, 3, 1, 4, 2, 7, -1},
915 {-1, 3, 1, 3, 4, 2, 7, -1},
916 {-1, 3, 5, 5, 6, 6, -1, -1},
917 {-1, -1, -1, -1, -1, -1, -1, -1},
918 {-1, -1, -1, -1, -1, -1, -1, -1}},
919 {{-1, -1, 7, 3, -1, -1, -1, -1},
920 {-1, 1, 7, 6, -1, -1, -1, -1},
921 {-1, 3, 7, 5, 1, 5, -1, -1},
922 { 7, 7, 0, 2, 4, 0, 4, -1},
923 { 7, 1, 4, 6, 5, 6, 5, 7},
924 { 1, 7, 7, 1, 7, 7, 1, -1},
925 {-1, -1, -1, -1, -1, -1, -1, -1},
926 {-1, -1, -1, -1, -1, -1, -1, -1},
927 {-1, -1, -1, -1, -1, -1, -1, -1},
928 {-1, -1, -1, -1, -1, -1, -1, -1}},
929 {{-1, -1, 1, -1, -1, 1, -1, -1},
930 {-1, 5, 6, 1, 5, 6, -1, -1},
931 {-1, 1, 1, 2, 2, 1, 1, -1},
932 { 4, 7, 1, 0, 1, 7, 4, -1},
933 {-1, 3, 7, 5, 7, 5, 3, -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 {{ 4, -1, -1, -1, 5, -1, -1, 4},
940 { 6, 6, 7, 6, -1, 4, 5, -1},
941 { 4, 2, 7, 5, 2, 2, 6, 4},
942 {-1, -1, 4, 1, -1, 5, 2, -1},
943 {-1, 5, 2, 7, 7, -1, 7, 4},
944 { 4, 6, 5, 4, -1, 4, 2, -1},
945 {-1, -1, -1, 4, -1, 4, 1, -1},
946 { 0, 0, 0, 5, -1, -1, -1, -1},
947 {-1, -1, -1, -1, 0, 0, 0, 0},
948 {-1, -1, -1, -1, -1, -1, -1, -1}},
949 {{ 1, -1, -1, -1, 0, 0, -1, -1},
950 { 2, -1, -1, 0, 1, 0, -1, -1},
951 { 3, -1, -1, 0, 2, 2, 0, -1},
952 { 4, -1, 0, 1, 1, 1, 0, -1},
953 { 5, -1, -1, 0, 4, 4, 0, -1},
954 { 6, -1, -1, 4, 4, 4, -1, -1},
955 { 7, -1, -1, -1, 4, 4, -1, -1},
956 {-1, -1, -1, 0, 1, 0, -1, -1},
957 {-1, -1, -1, 0, 1, 1, 0, -1},
958 {-1, -1, -1, -1, -1, -1, -1, -1}},
959 {{-1, -1, 3, -1, -1, 1, 7, -1},
960 {-1, 7, 4, -1, -1, 4, 3, -1},
961 { 1, -1, -1, 0, 2, 0, -1, -1},
962 { 5, 4, -1, 3, -1, -1, -1, -1},
963 { 4, -1, 3, 6, 1, 1, 6, -1},
964 {-1, 1, -1, -1, 4, -1, 1, -1},
965 {-1, 7, 5, -1, -1, -1, 3, -1},
966 {-1, -1, 3, -1, -1, -1, -1, -1},
967 {-1, -1, -1, -1, -1, -1, -1, -1},
968 {-1, -1, -1, -1, -1, -1, -1, -1}},
969 {{ 1, -1, -1, -1, 1, -1, -1, -1},
970 { 2, -1, -1, -1, 2, -1, -1, -1},
971 {-1, 3, -1, -1, 3, 3, -1, -1},
972 {-1, 4, -1, 4, -1, 4, -1, -1},
973 {-1, 5, -1, -1, 5, 5, -1, -1},
974 { 6, -1, -1, 7, 1, 7, -1, -1},
975 { 7, -1, -1, -1, 6, 6, -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, 6, -1, 2, 5, 1},
980 { 5, -1, 4, -1, 4, -1, 4, -1},
981 { 6, -1, -1, 3, -1, -1, -1, 3},
982 { 4, 2, 0, -1, -1, -1, 5, -1},
983 {-1, -1, -1, 6, -1, 3, 6, -1},
984 {-1, -1, 5, -1, 5, -1, -1, -1},
985 {-1, -1, -1, 3, -1, 4, 2, 5},
986 {-1, -1, -1, -1, -1, -1, -1, -1},
987 {-1, -1, -1, -1, -1, -1, -1, -1},
988 {-1, -1, -1, -1, -1, -1, -1, -1}},
989 {{ 6, -1, -1, -1, 4, -1, -1, 3},
990 { 0, 3, -1, -1, 6, -1, 0, -1},
991 {-1, -1, 7, -1, 1, -1, 3, -1},
992 { 7, -1, 4, 7, -1, 2, -1, -1},
993 { 5, 2, 3, 2, 1, 6, -1, 3},
994 {-1, -1, 0, 4, 3, 5, 4, -1},
995 {-1, 7, 6, -1, -1, 0, -1, -1},
996 { 4, 3, -1, -1, -1, 4, 2, -1},
997 { 0, -1, -1, -1, -1, -1, 6, -1},
998 {-1, -1, -1, -1, -1, -1, -1, -1}},
999 {{ 6, 1, 2, 5, 1, 6, 3, 0},
1000 {-1, -1, -1, -1, -1, -1, 4, -1},
1001 { 0, 5, 2, 7, 1, 6, 2, -1},
1002 { 3, -1, -1, -1, -1, -1, -1, -1},
1003 { 6, 7, 6, 4, 0, 5, 2, 6},
1004 {-1, -1, -1, -1, -1, -1, 1, -1},
1005 { 6, 1, 4, 0, 6, 2, 3, -1},
1006 { 0, -1, -1, -1, -1, -1, -1, -1},
1007 {-1, 0, 4, 5, 3, 7, 6, 0},
1008 {-1, -1, -1, -1, -1, -1, -1, -1}},
1009 {{-1, -1, -1, 0, 1, -1, -1, -1},
1010 {-1, -1, 0, 7, 0, -1, -1, -1},
1011 {-1, -1, 1, 2, 2, 0, -1, -1},
1012 {-1, 0, 7, 0, 7, 0, -1, -1},
1013 {-1, 6, -1, 7, 7, -1, 6, -1},
1014 { 4, 1, 6, 6, 6, 4, 1, -1},
1015 {-1, 5, -1, 7, 7, -1, 5, -1},
1016 {-1, -1, -1, -1, -1, -1, -1, -1},
1017 {-1, -1, -1, -1, -1, -1, -1, -1},
1018 {-1, -1, -1, -1, -1, -1, -1, -1}},
1019 {{-1, -1, -1, 5, 6, -1, -1, -1},
1020 {-1, -1, 3, 3, 3, -1, -1, -1},
1021 {-1, -1, 7, 5, 3, 7, -1, -1},
1022 {-1, 3, -1, 6, -1, 3, -1, -1},
1023 { 2, -1, -1, 3, 7, -1, -1, 1},
1024 { 2, 2, -1, 3, -1, 1, 1, -1},
1025 {-1, 0, 2, 5, 6, 1, 0, -1},
1026 {-1, -1, -1, 3, -1, -1, -1, -1},
1027 {-1, -1, -1, 3, 7, -1, -1, -1},
1028 {-1, -1, -1, -1, -1, -1, -1, -1}},
1029 {{-1, 6, -1, -1, -1, -1, 2, -1},
1030 {-1, 2, 6, 0, 6, 0, -1, -1},
1031 {-1, 0, -1, -1, -1, -1, -1, -1},
1032 { 6, -1, -1, -1, -1, -1, -1, -1},
1033 {-1, 3, 3, 2, 0, 6, 0, 0},
1034 {-1, 6, -1, -1, -1, -1, 0, -1},
1035 {-1, -1, -1, 6, 0, 2, 6, -1},
1036 {-1, 2, 0, -1, -1, -1, -1, -1},
1037 {-1, -1, -1, -1, -1, -1, -1, -1},
1038 {-1, -1, -1, -1, -1, -1, -1, -1}},
1039 {{ 0, 7, -1, -1, -1, -1, -1, -1},
1040 { 1, 5, -1, -1, -1, -1, -1, -1},
1041 { 7, 2, 5, -1, -1, -1, -1, -1},
1042 { 6, 3, 4, -1, -1, -1, -1, -1},
1043 { 5, 5, 4, 4, -1, -1, -1, -1},
1044 { 3, 3, 5, 3, -1, -1, -1, -1},
1045 { 1, 2, 2, 5, 3, -1, -1, -1},
1046 { 1, 0, 0, 7, 6, -1, -1, -1},
1047 { 3, 3, 5, 5, 7, 6, -1, -1},
1048 {-1, -1, -1, -1, -1, -1, -1, -1}},
1049 {{-1, -1, 2, 6, 6, 2, -1, -1},
1050 {-1, 2, 1, 1, 0, 2, -1, -1},
1051 {-1, 2, 3, 2, 2, 0, 2, -1},
1052 { 2, 3, 2, 5, 2, 7, 2, -1},
1053 { 2, 4, 2, 5, 2, 7, 2, 0},
1054 { 2, 4, 2, 6, 6, 2, 0, -1},
1055 {-1, 2, 5, 2, 2, 2, 7, 2},
1056 {-1, 2, 5, 6, 6, 7, 2, -1},
1057 {-1, -1, 2, 2, 2, 2, 2, -1},
1058 {-1, -1, -1, -1, -1, -1, -1, -1}},
1059 {{-1, -1, 0, -1, -1, 0, -1, -1},
1060 { 1, 0, 0, 1, 0, 0, 1, -1},
1061 { 1, 7, 7, 5, 5, 7, 7, 1},
1062 { 3, 2, -1, 2, -1, 2, 3, -1},
1063 { 3, 7, -1, 6, 6, -1, 7, 3},
1064 { 7, -1, -1, 6, -1, -1, 7, -1},
1065 { 4, 4, 5, -1, -1, 5, 4, 4},
1066 {-1, -1, -1, -1, -1, -1, -1, -1},
1067 {-1, -1, -1, -1, -1, -1, -1, -1},
1068 {-1, -1, -1, -1, -1, -1, -1, -1}},
1069 {{-1, 6, 3, -1, -1, 3, 6, -1},
1070 { 6, -1, 2, -1, 2, -1, 6, -1},
1071 { 2, -1, 0, 1, 1, 0, -1, 2},
1072 { 5, 0, -1, 7, -1, 0, 5, -1},
1073 {-1, 5, -1, 6, 6, -1, 5, -1},
1074 { 7, 1, 4, -1, 4, 1, 7, -1},
1075 { 7, -1, 4, -1, -1, 4, -1, 7},
1076 { 2, 0, -1, -1, -1, 0, 2, -1},
1077 {-1, 2, -1, -1, -1, -1, 2, -1},
1078 {-1, -1, -1, -1, -1, -1, -1, -1}},
1079 {{ 6, 1, -1, -1, -1, -1, 4, 0},
1080 { 2, 7, 5, 5, 5, 7, 3, -1},
1081 { 6, 1, -1, -1, -1, -1, 4, 0},
1082 { 2, 5, 7, 7, 7, 5, 3, -1},
1083 { 6, 1, -1, -1, -1, -1, 4, 0},
1084 { 2, 0, 6, 6, 6, 0, 3, -1},
1085 { 6, 1, -1, -1, -1, -1, 4, 0},
1086 {-1, -1, -1, -1, -1, -1, -1, -1},
1087 {-1, -1, -1, -1, -1, -1, -1, -1},
1088 {-1, -1, -1, -1, -1, -1, -1, -1}},
1089 {{ 5, -1, -1, 1, 1, -1, -1, 5},
1090 { 5, -1, 4, -1, 4, -1, 5, -1},
1091 {-1, 2, 4, -1, -1, 4, 2, -1},
1092 { 7, 2, -1, -1, -1, 2, 7, -1},
1093 { 0, -1, 0, 4, 4, 0, -1, 0},
1094 { 7, 2, -1, -1, -1, 2, 7, -1},
1095 {-1, 2, 3, -1, -1, 3, 2, -1},
1096 { 5, -1, 3, -1, 3, -1, 5, -1},
1097 { 5, -1, -1, 6, 6, -1, -1, 5},
1098 {-1, -1, -1, -1, -1, -1, -1, -1}},
1099 {{ 2, 2, -1, -1, -1, -1, 5, 5},
1100 { 5, -1, -1, -1, -1, -1, 2, -1},
1101 { 5, -1, -1, -1, -1, -1, -1, 2},
1102 { 1, -1, 1, 5, 1, -1, 3, -1},
1103 { 5, 2, 5, 3, 1, 2, 5, 2},
1104 { 2, 0, 5, -1, 2, 0, 5, -1},
1105 {-1, 3, 7, -1, -1, 3, 7, -1},
1106 {-1, -1, 2, 0, 5, -1, -1, -1},
1107 {-1, -1, -1, -1, -1, -1, -1, -1},
1108 {-1, -1, -1, -1, -1, -1, -1, -1}},
1109 {{ 0, 6, 5, 2, 3, 4, 1, 7},
1110 {-1, -1, -1, -1, 1, -1, -1, -1},
1111 {-1, -1, -1, 1, 1, -1, -1, -1},
1112 {-1, -1, 1, -1, -1, -1, -1, -1},
1113 { 7, 1, 4, 3, 2, 5, 6, 0},
1114 {-1, -1, -1, -1, 1, -1, -1, -1},
1115 {-1, -1, -1, 1, 1, -1, -1, -1},
1116 {-1, -1, 1, -1, -1, -1, -1, -1},
1117 { 0, 6, 5, 2, 3, 4, 1, 7},
1118 {-1, -1, -1, -1, -1, -1, -1, -1}},
1119 {{-1, -1, 1, -1, -1, 1, -1, -1},
1120 {-1, 2, 4, -1, 2, 4, -1, -1},
1121 {-1, 2, 3, 6, 5, 3, 2, -1},
1122 {-1, 6, 5, -1, 6, 5, -1, -1},
1123 {-1, -1, -1, 7, 7, -1, -1, -1},
1124 {-1, -1, -1, 7, -1, -1, -1, -1},
1125 { 1, -1, -1, 7, 7, -1, -1, 3},
1126 { 2, -1, -1, 7, -1, -1, 2, -1},
1127 {-1, 3, 4, 5, 6, 4, 1, -1},
1128 {-1, -1, -1, -1, -1, -1, -1, -1}},
1129 {{ 1, -1, -1, 2, 2, -1, -1, 2},
1130 { 1, 3, 7, 3, 7, 4, 2, -1},
1131 {-1, 1, 6, -1, -1, 6, 2, -1},
1132 { 6, -1, 7, 3, 7, -1, 6, -1},
1133 {-1, 4, 2, -1, -1, 1, 3, -1},
1134 {-1, -1, 2, 6, 1, -1, -1, -1},
1135 {-1, 4, 3, 3, 4, 4, 3, -1},
1136 {-1, -1, -1, -1, -1, -1, -1, -1},
1137 {-1, -1, -1, -1, -1, -1, -1, -1},
1138 {-1, -1, -1, -1, -1, -1, -1, -1}},
1139 {{-1, -1, -1, 5, 6, -1, -1, -1},
1140 {-1, -1, -1, 3, -1, -1, -1, -1},
1141 {-1, -1, -1, 1, 2, -1, -1, -1},
1142 {-1, -1, -1, 4, -1, -1, -1, -1},
1143 {-1, -1, -1, 5, 7, -1, -1, -1},
1144 {-1, -1, -1, 2, -1, -1, -1, -1},
1145 { 6, 5, 4, 3, 2, 1, 7, 5},
1146 {-1, -1, -1, -1, -1, -1, -1, -1},
1147 {-1, -1, -1, -1, -1, -1, -1, -1},
1148 {-1, -1, -1, -1, -1, -1, -1, -1}},
1149 {{-1, 0, -1, 1, -1, 2, -1, -1},
1150 {-1, 4, -1, 5, -1, 6, -1, -1},
1151 {-1, 7, -1, 0, -1, 2, -1, -1},
1152 {-1, 6, -1, 3, -1, 6, -1, -1},
1153 {-1, 1, -1, 1, -1, 2, -1, -1},
1154 {-1, 3, -1, 5, -1, 0, -1, -1},
1155 {-1, 2, -1, 4, -1, 6, -1, -1},
1156 {-1, 3, -1, 6, -1, 7, -1, -1},
1157 {-1, -1, -1, -1, -1, -1, -1, -1},
1158 {-1, -1, -1, -1, -1, -1, -1, -1}},
1159 {{ 1, 1, 2, 2, 3, 3, 4, 4},
1160 { 5, 5, 6, 7, 6, 5, 5, -1},
1161 { 6, 4, 3, 3, 2, 2, 1, 6},
1162 { 4, 6, 5, 7, 6, 3, 1, -1},
1163 {-1, -1, -1, -1, -1, -1, -1, -1},
1164 {-1, -1, -1, -1, -1, -1, -1, -1},
1165 {-1, -1, -1, -1, -1, -1, -1, -1},
1166 {-1, -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 {{ 7, 4, -1, 1, 2, -1, 4, 7},
1170 { 5, 5, -1, 2, -1, 4, 4, -1},
1171 {-1, 5, -1, 7, 7, -1, 4, -1},
1172 { 1, 0, 6, 7, 6, 0, 2, -1},
1173 {-1, 2, -1, 5, 3, -1, 1, -1},
1174 { 1, 1, -1, -1, -1, 2, 2, -1},
1175 { 6, 1, 4, -1, -1, 4, 2, 6},
1176 { 5, 3, -1, -1, -1, 3, 5, -1},
1177 {-1, -1, -1, -1, -1, -1, -1, -1},
1178 {-1, -1, -1, -1, -1, -1, -1, -1}},
1179 {{ 1, 5, 1, 0, 0, 1, 5, 1},
1180 { 1, 2, 5, -1, 5, 2, 1, -1},
1181 { 3, 6, 1, 2, 2, 1, 6, 3},
1182 { 4, 3, 4, -1, 4, 3, 4, -1},
1183 { 3, 4, 6, 5, 5, 6, 4, 3},
1184 { 0, 2, 3, -1, 3, 2, 0, -1},
1185 { 2, 3, 1, 5, 5, 1, 3, 2},
1186 {-1, -1, -1, -1, -1, -1, -1, -1},
1187 {-1, -1, -1, -1, -1, -1, -1, -1},
1188 {-1, -1, -1, -1, -1, -1, -1, -1}},
1189 {{ 3, 0, 2, 7, 5, 7, 6, 5},
1190 { 6, -1, 1, -1, 2, -1, 1, -1},
1191 {-1, 6, 4, 0, 3, 4, 5, -1},
1192 {-1, 5, -1, 1, -1, 4, -1, -1},
1193 {-1, 7, 3, 5, 6, 5, 3, -1},
1194 { 1, -1, 2, -1, 4, -1, 2, -1},
1195 { 6, 4, 4, 6, 6, 5, 5, 1},
1196 {-1, -1, -1, -1, -1, -1, -1, -1},
1197 {-1, -1, -1, -1, -1, -1, -1, -1},
1198 {-1, -1, -1, -1, -1, -1, -1, -1}}
1201 /* the tile struct
1202 * type is the bubble number 0-7
1203 * fallx is the x axis movement for the falling bubble
1204 * fallvel is the initial upward velocity for the falling bubble
1205 * ingroup denotes a bubble that is part of a group to be removed
1206 * anchored denotes a bubble that is anchored to the ceiling
1208 struct tile {
1209 int type;
1210 int fallx;
1211 int fallvel;
1212 bool ingroup;
1213 bool anchored;
1214 bool delete;
1217 /* the highscore struct
1218 * level is the highscore level
1219 * score is the highscore score
1221 struct highscore {
1222 unsigned int level;
1223 unsigned int score;
1226 /* the game context struct
1227 * score is the current score
1228 * level is the current level
1229 * highlevel is the highest level beaten
1230 * highscores is the list of high scores
1231 * angle is the current cannon direction
1232 * shots is the number of shots fired since last compression
1233 * compress is the height of the compressor
1234 * onboardcnt is the number of unique bubbles on the playing board
1235 * onboard is the unique bubbles on the playing board
1236 * nextinq is the pointer to the next bubble in the firing queue
1237 * queue is the circular buffer of bubbles to be fired
1238 * elapsedlvl is level elapsed time in 1/100s of seconds
1239 * elapsedshot is the shot elapsed time in 1/100s of seconds
1240 * startedshot is when the current shot began
1241 * resume denotes whether to resume the currently loaded game
1242 * dirty denotes whether the high scores are out of sync with the saved file
1243 * playboard is the game playing board
1245 struct game_context {
1246 unsigned int score;
1247 unsigned int level;
1248 unsigned int highlevel;
1249 struct highscore highscores[NUM_SCORES];
1250 int angle;
1251 int shots;
1252 int compress;
1253 int onboardcnt;
1254 int onboard[NUM_BUBBLES];
1255 int nextinq;
1256 int queue[NUM_QUEUE];
1257 long elapsedlvl;
1258 long elapsedshot;
1259 long startedshot;
1260 bool resume;
1261 bool dirty;
1262 struct tile playboard[BB_HEIGHT][BB_WIDTH];
1265 static void bubbles_init(struct game_context* bb);
1266 static bool bubbles_nextlevel(struct game_context* bb);
1267 static void bubbles_getonboard(struct game_context* bb);
1268 static void bubbles_drawboard(struct game_context* bb);
1269 static int bubbles_fire(struct game_context* bb);
1270 static bool bubbles_collision(struct game_context* bb, int y, int x,
1271 int nearrow, int nearcol);
1272 static bool bubbles_ingroup(struct game_context* bb, int row, int col);
1273 static int bubbles_searchgroup(struct game_context* bb, int row, int col);
1274 static int bubbles_remove(struct game_context* bb);
1275 static void bubbles_anchored(struct game_context* bb, int row, int col);
1276 static int bubbles_fall(struct game_context* bb);
1277 static int bubbles_checklevel(struct game_context* bb);
1278 static int bubbles_recordscore(struct game_context* bb);
1279 static void bubbles_savescores(struct game_context* bb);
1280 static bool bubbles_loadgame(struct game_context* bb);
1281 static void bubbles_savegame(struct game_context* bb);
1282 static void bubbles_setcolors(void);
1283 static void bubbles_callback(void* param);
1284 static int bubbles_handlebuttons(struct game_context* bb, bool animblock,
1285 int timeout);
1286 static int bubbles(struct game_context* bb);
1288 /*****************************************************************************
1289 * bubbles_init() initializes bubbles data structures.
1290 ******************************************************************************/
1291 static void bubbles_init(struct game_context* bb) {
1292 /* seed the rand generator */
1293 rb->srand(*rb->current_tick);
1295 /* check for resumed game */
1296 if(bb->resume) {
1297 bb->resume = false;
1298 return;
1301 bb->score = 0;
1302 bubbles_nextlevel(bb);
1305 /*****************************************************************************
1306 * bubbles_nextlevel() sets up the game for the next level, returns false if
1307 * there are no more levels.
1308 ******************************************************************************/
1309 static bool bubbles_nextlevel(struct game_context* bb) {
1310 int i, j, pos;
1312 bb->level++;
1314 /* check if there are no more levels */
1315 if(bb->level > NUM_LEVELS) return false;
1317 /* set up the play board */
1318 rb->memset(bb->playboard, 0, sizeof(bb->playboard));
1319 for(i=0; i<BB_LEVEL_HEIGHT; i++) {
1320 for(j=0; j<BB_WIDTH; j++) {
1321 pos = (int)level[bb->level-1][i][j];
1322 if(pos >=0 && pos < NUM_BUBBLES) {
1323 bb->playboard[i][j].type = pos;
1324 } else {
1325 bb->playboard[i][j].type = -1;
1329 for(i=BB_LEVEL_HEIGHT; i<BB_HEIGHT; i++) {
1330 for(j=0; j<BB_WIDTH; j++) {
1331 bb->playboard[i][j].type = -1;
1335 /* fill first bubbles in shot queue */
1336 bubbles_getonboard(bb);
1337 for(i=0; i<NUM_QUEUE; i++) {
1338 bb->queue[i] = bb->onboard[rb->rand()%bb->onboardcnt];
1341 bb->angle = 0;
1342 bb->shots = 0;
1343 bb->compress = 0;
1344 bb->nextinq = 0;
1345 bb->elapsedlvl = 0;
1346 bb->elapsedshot = 0;
1348 return true;
1351 /*****************************************************************************
1352 * bubbles_getonboard() determines which bubble types are on the play board.
1353 ******************************************************************************/
1354 static void bubbles_getonboard(struct game_context* bb) {
1355 int i, j, k;
1356 bool found;
1358 bb->onboardcnt = 0;
1359 rb->memset(bb->onboard, -1, sizeof(bb->onboard));
1361 for(i=0; i<BB_HEIGHT; i++) {
1362 for(j=0; j<BB_WIDTH; j++) {
1363 if(bb->playboard[i][j].type >= 0) {
1364 found = false;
1366 for(k=0; k<bb->onboardcnt; k++) {
1367 if(bb->playboard[i][j].type == bb->onboard[k]) {
1368 found = true;
1369 break;
1373 if(!found) {
1374 bb->onboard[bb->onboardcnt] = bb->playboard[i][j].type;
1375 bb->onboardcnt++;
1378 if(bb->onboardcnt == NUM_BUBBLES) return;
1384 /*****************************************************************************
1385 * bubbles_drawboard() draws the game board to the buffer but does not update
1386 * the lcd.
1387 ******************************************************************************/
1388 static void bubbles_drawboard(struct game_context* bb) {
1389 int i, j;
1390 int w, h;
1391 int colmax, indent;
1392 int tipx, tipy;
1393 bool evenline = false;
1394 char *level = "Level";
1395 char *score = "Score";
1396 char *next = "Next";
1397 char *hurry = "HURRY!";
1398 char str[11];
1400 /* clear screen */
1401 rb->lcd_clear_display();
1403 /* draw background */
1404 #ifdef HAVE_LCD_COLOR
1405 rb->lcd_bitmap(bubbles_background, 0, 0, LCD_WIDTH, LCD_HEIGHT);
1406 #endif
1408 /* display play board */
1409 for(i=0; i<BB_HEIGHT; i++) {
1410 colmax = BB_WIDTH;
1411 if(evenline) {
1412 colmax--;
1413 indent = ROW_INDENT;
1414 } else {
1415 indent = 0;
1417 evenline = !evenline;
1419 for(j=0; j<colmax; j++) {
1420 if(bb->playboard[i][j].type >= 0 && !bb->playboard[i][j].delete) {
1421 rb->lcd_bitmap_part(bubbles_emblem,
1422 0, EMBLEM_HEIGHT*bb->playboard[i][j].type, EMBLEM_WIDTH,
1423 XOFS+indent+BUBBLE_WIDTH*j+(BUBBLE_WIDTH-EMBLEM_WIDTH)/2,
1424 ROW_HEIGHT*i+(BUBBLE_HEIGHT-EMBLEM_HEIGHT)/2+bb->compress*ROW_HEIGHT,
1425 EMBLEM_WIDTH, EMBLEM_HEIGHT);
1426 rb->lcd_set_drawmode(DRMODE_FG);
1427 rb->lcd_mono_bitmap((const unsigned char *)bubbles_bubble,
1428 XOFS+indent+BUBBLE_WIDTH*j,
1429 ROW_HEIGHT*i+bb->compress*ROW_HEIGHT,
1430 BUBBLE_WIDTH, BUBBLE_HEIGHT);
1431 rb->lcd_set_drawmode(DRMODE_SOLID);
1436 /* display bubble to be shot */
1437 rb->lcd_bitmap_part(bubbles_emblem,
1438 0, EMBLEM_HEIGHT*bb->queue[bb->nextinq], EMBLEM_WIDTH,
1439 SHOTX+(BUBBLE_WIDTH-EMBLEM_WIDTH)/2,
1440 SHOTY+(BUBBLE_HEIGHT-EMBLEM_HEIGHT)/2,
1441 EMBLEM_WIDTH, EMBLEM_HEIGHT);
1442 rb->lcd_set_drawmode(DRMODE_FG);
1443 rb->lcd_mono_bitmap((const unsigned char *)bubbles_bubble,
1444 SHOTX, SHOTY,
1445 BUBBLE_WIDTH, BUBBLE_HEIGHT);
1446 rb->lcd_set_drawmode(DRMODE_SOLID);
1448 /* display next bubble to be shot */
1449 rb->lcd_bitmap_part(bubbles_emblem,
1450 0, EMBLEM_HEIGHT*bb->queue[(bb->nextinq+1)%NUM_QUEUE], EMBLEM_WIDTH,
1451 XOFS/2-BUBBLE_WIDTH/2+(BUBBLE_WIDTH-EMBLEM_WIDTH)/2,
1452 SHOTY+(BUBBLE_HEIGHT-EMBLEM_HEIGHT)/2,
1453 EMBLEM_WIDTH, EMBLEM_HEIGHT);
1454 rb->lcd_set_drawmode(DRMODE_FG);
1455 rb->lcd_mono_bitmap((const unsigned char *)bubbles_bubble,
1456 XOFS/2-BUBBLE_WIDTH/2, SHOTY,
1457 BUBBLE_WIDTH, BUBBLE_HEIGHT);
1458 rb->lcd_set_drawmode(DRMODE_SOLID);
1460 /* draw bounding lines */
1461 #ifndef HAVE_LCD_COLOR
1462 rb->lcd_vline(XOFS-1, 0, LCD_HEIGHT);
1463 rb->lcd_vline(XOFS+BUBBLE_WIDTH*BB_WIDTH, 0, LCD_HEIGHT);
1464 #endif
1465 rb->lcd_hline(XOFS, XOFS+BUBBLE_WIDTH*BB_WIDTH-1, bb->compress*ROW_HEIGHT-1);
1466 rb->lcd_hline(XOFS, XOFS+BUBBLE_WIDTH*BB_WIDTH-1,
1467 ROW_HEIGHT*(BB_HEIGHT-2)+BUBBLE_HEIGHT);
1469 /* draw arrow */
1470 tipx = SHOTX+BUBBLE_WIDTH/2+(((sin_int(bb->angle)>>4)*BUBBLE_WIDTH*3/2)>>10);
1471 tipy = SHOTY+BUBBLE_HEIGHT/2-(((cos_int(bb->angle)>>4)*BUBBLE_HEIGHT*3/2)>>10);
1473 rb->lcd_drawline(SHOTX+BUBBLE_WIDTH/2+(((sin_int(bb->angle)>>4)*BUBBLE_WIDTH/2)>>10),
1474 SHOTY+BUBBLE_HEIGHT/2-(((cos_int(bb->angle)>>4)*BUBBLE_HEIGHT/2)>>10),
1475 tipx, tipy);
1476 xlcd_filltriangle(tipx, tipy,
1477 tipx+(((sin_int(bb->angle-135)>>4)*BUBBLE_WIDTH/3)>>10),
1478 tipy-(((cos_int(bb->angle-135)>>4)*BUBBLE_HEIGHT/3)>>10),
1479 tipx+(((sin_int(bb->angle+135)>>4)*BUBBLE_WIDTH/3)>>10),
1480 tipy-(((cos_int(bb->angle+135)>>4)*BUBBLE_HEIGHT/3)>>10));
1482 /* draw text */
1483 rb->lcd_getstringsize(level, &w, &h);
1484 rb->lcd_putsxy(XOFS/2-w/2, 2, level);
1486 rb->snprintf(str, 4, "%d", bb->level);
1487 rb->lcd_getstringsize(str, &w, &h);
1488 rb->lcd_putsxy(XOFS/2-w/2, 11, str);
1490 rb->lcd_getstringsize(score, &w, &h);
1491 rb->lcd_putsxy(XOFS/2-w/2, 29, score);
1493 rb->snprintf(str, 10, "%d", bb->score);
1494 rb->lcd_getstringsize(str, &w, &h);
1495 rb->lcd_putsxy(XOFS/2-w/2, 38, str);
1497 rb->lcd_getstringsize(next, &w, &h);
1498 rb->lcd_putsxy(XOFS/2-w/2, SHOTY-9, next);
1500 if(bb->elapsedshot >= (MAX_SHOTTIME*7)/10) {
1501 rb->lcd_getstringsize(hurry, &w, &h);
1502 rb->lcd_putsxy(LCD_WIDTH/2-w/2, LCD_HEIGHT/2-h/2, hurry);
1506 /*****************************************************************************
1507 * bubbles_fire() fires the current bubble, reloads the cannon, attaches
1508 * bubble to playboard, removes appropriate bubbles, and advances the
1509 * the compressor.
1510 ******************************************************************************/
1511 static int bubbles_fire(struct game_context* bb) {
1512 int bubblecur;
1513 long shotxinc, shotyinc;
1514 long shotxofs, shotyofs;
1515 int shotxdirec = 1;
1516 long tempxofs, tempyofs;
1517 int nearrow, nearcol;
1518 int lastrow = BB_HEIGHT-1;
1519 int lastcol = (BB_WIDTH-1)/2;
1520 int buttonres;
1521 long lasttick, currenttick;
1523 /* get current bubble */
1524 bubblecur = bb->queue[bb->nextinq];
1525 shotxinc = ((sin_int(bb->angle)>>4)*BUBBLE_WIDTH)/3;
1526 shotyinc = ((-1*(cos_int(bb->angle)>>4))*BUBBLE_HEIGHT)/3;
1527 shotxofs = shotyofs = 0;
1529 /* advance the queue */
1530 bb->queue[bb->nextinq] = bb->onboard[rb->rand()%bb->onboardcnt];
1531 bb->nextinq = (bb->nextinq+1)%NUM_QUEUE;
1532 bubbles_drawboard(bb);
1533 rb->lcd_update_rect(0, 0, XOFS, LCD_HEIGHT);
1535 /* move the bubble across the play board */
1536 lasttick = *rb->current_tick;
1538 while(true) {
1539 /* move the bubble one step */
1540 shotyofs += shotyinc;
1541 shotxofs += shotxinc*shotxdirec;
1543 /* check for bounce off sides */
1544 if(SHOTX+(shotxofs>>10) < XOFS) {
1545 shotxofs += 2*((XOFS<<10)-(((SHOTX)<<10)+shotxofs));
1546 shotxdirec *= -1;
1547 } else if(SHOTX+(shotxofs>>10) > XOFS+(BB_WIDTH-1)*BUBBLE_WIDTH) {
1548 shotxofs -= 2*((((SHOTX)<<10)+shotxofs)-
1549 ((XOFS<<10)+(((BB_WIDTH-1)*BUBBLE_WIDTH)<<10)));
1550 shotxdirec *= -1;
1553 tempxofs = shotxofs>>10;
1554 tempyofs = shotyofs>>10;
1556 /* display shot */
1557 bubbles_drawboard(bb);
1558 rb->lcd_bitmap_part(bubbles_emblem, 0, EMBLEM_HEIGHT*bubblecur, EMBLEM_WIDTH,
1559 SHOTX+tempxofs+(BUBBLE_WIDTH-EMBLEM_WIDTH)/2,
1560 SHOTY+tempyofs+(BUBBLE_HEIGHT-EMBLEM_HEIGHT)/2,
1561 EMBLEM_WIDTH, EMBLEM_HEIGHT);
1562 rb->lcd_set_drawmode(DRMODE_FG);
1563 rb->lcd_mono_bitmap((const unsigned char *)bubbles_bubble,
1564 SHOTX+tempxofs, SHOTY+tempyofs,
1565 BUBBLE_WIDTH, BUBBLE_HEIGHT);
1566 rb->lcd_set_drawmode(DRMODE_SOLID);
1567 rb->lcd_update_rect(XOFS, 0, BB_WIDTH*BUBBLE_WIDTH, LCD_HEIGHT);
1569 /* find nearest position */
1570 nearrow = ((SHOTY+tempyofs)-
1571 (bb->compress*ROW_HEIGHT)+
1572 (ROW_HEIGHT/2))/ROW_HEIGHT;
1573 if(nearrow >= BB_HEIGHT) nearrow = BB_HEIGHT-1;
1575 if(nearrow%2) { /* odd row */
1576 nearcol = ((SHOTX+tempxofs)-
1577 (XOFS+ROW_INDENT)+
1578 (BUBBLE_WIDTH/2))/BUBBLE_WIDTH;
1579 if(nearcol >= BB_WIDTH-1) nearcol = BB_WIDTH-2;
1580 } else { /* even row */
1581 nearcol = ((SHOTX+tempxofs)-XOFS+(BUBBLE_WIDTH/2))/BUBBLE_WIDTH;
1582 if(nearcol >= BB_WIDTH) nearcol = BB_WIDTH-1;
1584 if(nearcol < 0) nearcol = 0;
1586 /* if nearest position is occupied attach to last position */
1587 if(bb->playboard[nearrow][nearcol].type >= 0) {
1588 bb->playboard[lastrow][lastcol].type = bubblecur;
1589 break;
1592 /* save last position */
1593 lastrow = nearrow;
1594 lastcol = nearcol;
1596 /* if collision with neighbor then attach shot */
1597 if(bubbles_collision(bb, SHOTY+tempyofs, SHOTX+tempxofs,
1598 nearrow, nearcol)) {
1599 bb->playboard[nearrow][nearcol].type = bubblecur;
1600 break;
1603 /* if at top then attach shot to the ceiling */
1604 if(nearrow == 0 && SHOTY+tempyofs <= bb->compress*ROW_HEIGHT) {
1605 bb->playboard[nearrow][nearcol].type = bubblecur;
1606 break;
1609 /* handle button events */
1610 buttonres = bubbles_handlebuttons(bb, true, 0);
1611 if(buttonres != BB_NONE) return buttonres;
1613 /* framerate limiting */
1614 currenttick = *rb->current_tick;
1615 if(currenttick-lasttick < HZ/MAX_FPS) {
1616 rb->sleep((HZ/MAX_FPS)-(currenttick-lasttick));
1617 } else {
1618 rb->yield();
1620 lasttick = currenttick;
1623 bubbles_drawboard(bb);
1624 rb->lcd_update();
1626 /* clear appropriate bubbles from playing board */
1627 if(bubbles_ingroup(bb, lastrow, lastcol)) {
1628 buttonres = bubbles_remove(bb);
1629 if(buttonres != BB_NONE) return buttonres;
1632 /* update shots and compress amount */
1633 bb->shots++;
1634 if(bb->shots >= NUM_COMPRESS) {
1635 bb->shots = 0;
1636 bb->compress++;
1639 return BB_NONE;
1642 /*****************************************************************************
1643 * bubbles_collision() determines if a fired bubble has collided with another
1644 * bubble.
1645 ******************************************************************************/
1646 static bool bubbles_collision(struct game_context* bb, int y, int x,
1647 int nearrow, int nearcol) {
1648 int nx, ny;
1649 int adj = nearrow%2;
1651 /* check neighbors */
1652 if(nearcol-1 >= 0) {
1653 if(bb->playboard[nearrow][nearcol-1].type >= 0) {
1654 nx = XOFS+(nearrow%2 ? ROW_INDENT : 0)+BUBBLE_WIDTH*(nearcol-1);
1655 ny = ROW_HEIGHT*nearrow+bb->compress*ROW_HEIGHT;
1656 if((x-nx)*(x-nx)+(y-ny)*(y-ny) < MIN_DISTANCE) return true;
1660 if(nearcol-1+adj >= 0) {
1661 if(nearrow-1 >= 0) {
1662 if(bb->playboard[nearrow-1][nearcol-1+adj].type >= 0) {
1663 nx = XOFS+((nearrow-1)%2 ? ROW_INDENT : 0)+
1664 BUBBLE_WIDTH*(nearcol-1+adj);
1665 ny = ROW_HEIGHT*(nearrow-1)+bb->compress*ROW_HEIGHT;
1666 if((x-nx)*(x-nx)+(y-ny)*(y-ny) < MIN_DISTANCE) return true;
1670 if(nearrow+1 < BB_HEIGHT) {
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;
1680 if(nearcol+adj >= 0) {
1681 if(nearrow-1 >= 0) {
1682 if(bb->playboard[nearrow-1][nearcol+adj].type >= 0) {
1683 nx = XOFS+((nearrow-1)%2 ? ROW_INDENT : 0)+
1684 BUBBLE_WIDTH*(nearcol+adj);
1685 ny = ROW_HEIGHT*(nearrow-1)+bb->compress*ROW_HEIGHT;
1686 if((x-nx)*(x-nx)+(y-ny)*(y-ny) < MIN_DISTANCE) return true;
1690 if(nearrow+1 < BB_HEIGHT) {
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;
1700 if(nearcol+1 < BB_WIDTH-adj) {
1701 if(bb->playboard[nearrow][nearcol+1].type >= 0) {
1702 nx = XOFS+(nearrow%2 ? ROW_INDENT : 0)+BUBBLE_WIDTH*(nearcol+1);
1703 ny = ROW_HEIGHT*nearrow+bb->compress*ROW_HEIGHT;
1704 if((x-nx)*(x-nx)+(y-ny)*(y-ny) < MIN_DISTANCE) return true;
1708 return false;
1711 /*****************************************************************************
1712 * bubbles_ingroup() marks all bubbles that form the current group.
1713 ******************************************************************************/
1714 static bool bubbles_ingroup(struct game_context* bb, int row, int col) {
1715 int i, j;
1716 int count;
1718 count = bubbles_searchgroup(bb, row, col);
1720 /* unmark group if too small */
1721 if(count < 3) {
1722 for(i=0; i<BB_HEIGHT; i++) {
1723 for(j=0; j<BB_WIDTH; j++) {
1724 bb->playboard[i][j].ingroup = false;
1728 return false;
1731 return true;
1734 /*****************************************************************************
1735 * bubbles_searchgroup() return the size of the group of bubbles of the same
1736 * type that the current bubble belongs to.
1737 ******************************************************************************/
1738 static int bubbles_searchgroup(struct game_context* bb, int row, int col) {
1739 int i, adj;
1740 int myrow, mycol, mytype;
1741 int count = 0;
1743 struct coord {
1744 int row;
1745 int col;
1746 } search[(2*BB_WIDTH-1)*(BB_HEIGHT/2)];
1748 /* search initial bubble */
1749 bb->playboard[row][col].ingroup = true;
1750 search[count].row = row;
1751 search[count].col = col;
1752 count++;
1754 /* breadth-first search neighbors */
1755 for(i=0; i<count; i++) {
1756 myrow = search[i].row;
1757 mycol = search[i].col;
1758 mytype = bb->playboard[myrow][mycol].type;
1759 adj = myrow%2;
1761 if(mycol-1 >= 0) {
1762 if(bb->playboard[myrow][mycol-1].type == mytype &&
1763 !bb->playboard[myrow][mycol-1].ingroup) {
1764 bb->playboard[myrow][mycol-1].ingroup = true;
1765 search[count].row = myrow;
1766 search[count].col = mycol-1;
1767 count++;
1771 if(mycol-1+adj >= 0) {
1772 if(myrow-1 >= 0) {
1773 if(bb->playboard[myrow-1][mycol-1+adj].type == mytype &&
1774 !bb->playboard[myrow-1][mycol-1+adj].ingroup) {
1775 bb->playboard[myrow-1][mycol-1+adj].ingroup = true;
1776 search[count].row = myrow-1;
1777 search[count].col = mycol-1+adj;
1778 count++;
1782 if(myrow+1 < BB_HEIGHT) {
1783 if(bb->playboard[myrow+1][mycol-1+adj].type == mytype &&
1784 !bb->playboard[myrow+1][mycol-1+adj].ingroup) {
1785 bb->playboard[myrow+1][mycol-1+adj].ingroup = true;
1786 search[count].row = myrow+1;
1787 search[count].col = mycol-1+adj;
1788 count++;
1793 if(mycol+adj >= 0) {
1794 if(myrow-1 >= 0) {
1795 if(bb->playboard[myrow-1][mycol+adj].type == mytype &&
1796 !bb->playboard[myrow-1][mycol+adj].ingroup) {
1797 bb->playboard[myrow-1][mycol+adj].ingroup = true;
1798 search[count].row = myrow-1;
1799 search[count].col = mycol+adj;
1800 count++;
1804 if(myrow+1 < BB_HEIGHT) {
1805 if(bb->playboard[myrow+1][mycol+adj].type == mytype &&
1806 !bb->playboard[myrow+1][mycol+adj].ingroup) {
1807 bb->playboard[myrow+1][mycol+adj].ingroup = true;
1808 search[count].row = myrow+1;
1809 search[count].col = mycol+adj;
1810 count++;
1815 if(mycol+1 < BB_WIDTH-adj) {
1816 if(bb->playboard[myrow][mycol+1].type == mytype &&
1817 !bb->playboard[myrow][mycol+1].ingroup) {
1818 bb->playboard[myrow][mycol+1].ingroup = true;
1819 search[count].row = myrow;
1820 search[count].col = mycol+1;
1821 count++;
1826 return count;
1829 /*****************************************************************************
1830 * bubbles_remove() removes all bubbles in the current group and all
1831 * unanchored bubbles from the play board.
1832 ******************************************************************************/
1833 static int bubbles_remove(struct game_context* bb) {
1834 int i, j;
1835 int buttonres;
1837 /* determine all anchored bubbles */
1838 for(j=0; j<BB_WIDTH; j++) {
1839 if(bb->playboard[0][j].type >= 0 && !bb->playboard[0][j].ingroup) {
1840 bubbles_anchored(bb, 0, j);
1844 /* mark bubbles to be deleted */
1845 for(i=0; i<BB_HEIGHT; i++) {
1846 for(j=0; j<BB_WIDTH; j++) {
1847 if(bb->playboard[i][j].type >= 0 &&
1848 (!bb->playboard[i][j].anchored || bb->playboard[i][j].ingroup)) {
1849 bb->playboard[i][j].delete = true;
1854 /* animate falling bubbles */
1855 buttonres = bubbles_fall(bb);
1856 if(buttonres != BB_NONE) return buttonres;
1858 /* remove bubbles */
1859 for(i=0; i<BB_HEIGHT; i++) {
1860 for(j=0; j<BB_WIDTH; j++) {
1861 if(bb->playboard[i][j].delete) {
1862 bb->playboard[i][j].ingroup = false;
1863 bb->playboard[i][j].type = -1;
1864 bb->playboard[i][j].delete = false;
1865 } else {
1866 bb->playboard[i][j].anchored = false;
1871 bubbles_getonboard(bb);
1873 return BB_NONE;
1876 /*****************************************************************************
1877 * bubbles_anchored() marks all bubbles that are anchored in some way to the
1878 * current bubble.
1879 ******************************************************************************/
1880 static void bubbles_anchored(struct game_context* bb, int row, int col) {
1881 int i, adj;
1882 int myrow, mycol, mytype;
1883 int count = 0;
1885 struct coord {
1886 int row;
1887 int col;
1888 } search[(2*BB_WIDTH-1)*(BB_HEIGHT/2)];
1890 /* search initial bubble */
1891 bb->playboard[row][col].anchored = true;
1892 search[count].row = row;
1893 search[count].col = col;
1894 count++;
1896 /* breadth-first search neighbors */
1897 for(i=0; i<count; i++) {
1898 myrow = search[i].row;
1899 mycol = search[i].col;
1900 mytype = bb->playboard[myrow][mycol].type;
1901 adj = myrow%2;
1903 if(mycol-1 >= 0) {
1904 if(bb->playboard[myrow][mycol-1].type >= 0 &&
1905 !bb->playboard[myrow][mycol-1].ingroup &&
1906 !bb->playboard[myrow][mycol-1].anchored) {
1907 bb->playboard[myrow][mycol-1].anchored = true;
1908 search[count].row = myrow;
1909 search[count].col = mycol-1;
1910 count++;
1914 if(mycol-1+adj >= 0) {
1915 if(myrow-1 >= 0) {
1916 if(bb->playboard[myrow-1][mycol-1+adj].type >= 0 &&
1917 !bb->playboard[myrow-1][mycol-1+adj].ingroup &&
1918 !bb->playboard[myrow-1][mycol-1+adj].anchored) {
1919 bb->playboard[myrow-1][mycol-1+adj].anchored = true;
1920 search[count].row = myrow-1;
1921 search[count].col = mycol-1+adj;
1922 count++;
1926 if(myrow+1 < BB_HEIGHT) {
1927 if(bb->playboard[myrow+1][mycol-1+adj].type >= 0 &&
1928 !bb->playboard[myrow+1][mycol-1+adj].ingroup &&
1929 !bb->playboard[myrow+1][mycol-1+adj].anchored) {
1930 bb->playboard[myrow+1][mycol-1+adj].anchored = true;
1931 search[count].row = myrow+1;
1932 search[count].col = mycol-1+adj;
1933 count++;
1938 if(mycol+adj >= 0) {
1939 if(myrow-1 >= 0) {
1940 if(bb->playboard[myrow-1][mycol+adj].type >= 0 &&
1941 !bb->playboard[myrow-1][mycol+adj].ingroup &&
1942 !bb->playboard[myrow-1][mycol+adj].anchored) {
1943 bb->playboard[myrow-1][mycol+adj].anchored = true;
1944 search[count].row = myrow-1;
1945 search[count].col = mycol+adj;
1946 count++;
1950 if(myrow+1 < BB_HEIGHT) {
1951 if(bb->playboard[myrow+1][mycol+adj].type >= 0 &&
1952 !bb->playboard[myrow+1][mycol+adj].ingroup &&
1953 !bb->playboard[myrow+1][mycol+adj].anchored) {
1954 bb->playboard[myrow+1][mycol+adj].anchored = true;
1955 search[count].row = myrow+1;
1956 search[count].col = mycol+adj;
1957 count++;
1962 if(mycol+1 < BB_WIDTH-adj) {
1963 if(bb->playboard[myrow][mycol+1].type >= 0 &&
1964 !bb->playboard[myrow][mycol+1].ingroup &&
1965 !bb->playboard[myrow][mycol+1].anchored) {
1966 bb->playboard[myrow][mycol+1].anchored = true;
1967 search[count].row = myrow;
1968 search[count].col = mycol+1;
1969 count++;
1975 /*****************************************************************************
1976 * bubbles_fall() makes removed bubbles fall from the screen.
1977 ******************************************************************************/
1978 static int bubbles_fall(struct game_context* bb) {
1979 int i, j;
1980 int count;
1981 int indent;
1982 int xofs, yofs;
1983 int buttonres;
1984 bool onscreen;
1985 long lasttick, currenttick;
1987 /* give all falling bubbles an x axis movement */
1988 for(i=0; i<BB_HEIGHT; i++) {
1989 for(j=0; j<BB_WIDTH; j++) {
1990 if(bb->playboard[i][j].delete) {
1991 bb->playboard[i][j].fallx = rb->rand()%25 - 12;
1992 bb->playboard[i][j].fallvel = rb->rand()%5 + 6;
1997 /* draw bubbles falling off the screen
1998 * follows y=x^2-8x scaled to bubble size
2000 lasttick = *rb->current_tick;
2002 for(count=1; ;count++) {
2003 onscreen = false;
2004 bubbles_drawboard(bb);
2006 for(i=0; i<BB_HEIGHT; i++) {
2007 for(j=0; j<BB_WIDTH; j++) {
2008 if(bb->playboard[i][j].delete) {
2009 indent = (i%2 ? ROW_INDENT : 0);
2010 xofs = ((bb->playboard[i][j].fallx*count)*BUBBLE_WIDTH)/48;
2011 yofs = ((count*count - bb->playboard[i][j].fallvel*count)*
2012 BUBBLE_HEIGHT)/20;
2014 /* draw bubble if it is still on the screen */
2015 if(ROW_HEIGHT*i+bb->compress*ROW_HEIGHT+yofs
2016 <= LCD_HEIGHT) {
2017 onscreen = true;
2019 rb->lcd_bitmap_part(bubbles_emblem, 0,
2020 EMBLEM_HEIGHT*bb->playboard[i][j].type, EMBLEM_WIDTH,
2021 XOFS+indent+BUBBLE_WIDTH*j+
2022 (BUBBLE_WIDTH-EMBLEM_WIDTH)/2+xofs,
2023 ROW_HEIGHT*i+(BUBBLE_HEIGHT-EMBLEM_HEIGHT)/2+
2024 bb->compress*ROW_HEIGHT+yofs,
2025 EMBLEM_WIDTH, EMBLEM_HEIGHT);
2026 rb->lcd_set_drawmode(DRMODE_FG);
2027 rb->lcd_mono_bitmap(
2028 (const unsigned char *)bubbles_bubble,
2029 XOFS+indent+BUBBLE_WIDTH*j+xofs,
2030 ROW_HEIGHT*i+bb->compress*ROW_HEIGHT+yofs,
2031 BUBBLE_WIDTH, BUBBLE_HEIGHT);
2032 rb->lcd_set_drawmode(DRMODE_SOLID);
2038 rb->lcd_update();
2040 /* break out if all bubbles are off the screen */
2041 if(!onscreen) break;
2043 /* handle button events */
2044 buttonres = bubbles_handlebuttons(bb, true, 0);
2045 if(buttonres != BB_NONE) return buttonres;
2047 /* framerate limiting */
2048 currenttick = *rb->current_tick;
2049 if(currenttick-lasttick < HZ/MAX_FPS) {
2050 rb->sleep((HZ/MAX_FPS)-(currenttick-lasttick));
2051 } else {
2052 rb->yield();
2054 lasttick = currenttick;
2057 return BB_NONE;
2060 /*****************************************************************************
2061 * bubbles_checklevel() checks the state of the playboard for a win or loss.
2062 ******************************************************************************/
2063 static int bubbles_checklevel(struct game_context* bb) {
2064 int i, j;
2065 int points;
2066 char str[13];
2068 bubbles_drawboard(bb);
2069 rb->lcd_update();
2071 /* check for bubbles below cut off point */
2072 for(i=0; i<=bb->compress; i++) {
2073 for(j=0; j<BB_WIDTH; j++) {
2074 if(bb->playboard[BB_HEIGHT-1-i][j].type >= 0) return BB_LOSE;
2078 /* check for bubbles above cut off point */
2079 for(i=0; i<BB_HEIGHT-1-bb->compress; i++) {
2080 for(j=0; j<BB_WIDTH; j++) {
2081 if(bb->playboard[i][j].type >= 0) return BB_NONE;
2085 /* level complete, record score */
2086 points = 100 - bb->elapsedlvl/100;
2087 if(points > 0) {
2088 bb->score += points;
2089 } else {
2090 points = 0;
2093 rb->snprintf(str, 12, "%d points", points);
2094 rb->splash(HZ, str);
2096 /* advance to the next level */
2097 if(!bubbles_nextlevel(bb)) {
2098 return BB_WIN;
2101 bubbles_drawboard(bb);
2102 rb->lcd_update();
2103 rb->snprintf(str, 12, "Level %d", bb->level);
2104 rb->splash(HZ, str);
2105 bubbles_drawboard(bb);
2106 rb->lcd_update();
2108 return BB_NONE;
2111 /*****************************************************************************
2112 * bubbles_recordscore() inserts a high score into the high scores list and
2113 * returns the high score position.
2114 ******************************************************************************/
2115 static int bubbles_recordscore(struct game_context* bb) {
2116 int i;
2117 int position = 0;
2118 unsigned int currentscore, currentlevel;
2119 unsigned int tempscore, templevel;
2121 if(bb->score > 0) {
2122 currentlevel = bb->level-1;
2123 currentscore = bb->score;
2125 for(i=0; i<NUM_SCORES; i++) {
2126 if(currentscore >= bb->highscores[i].score) {
2127 if(!position) {
2128 position = i+1;
2129 bb->dirty = true;
2131 templevel = bb->highscores[i].level;
2132 tempscore = bb->highscores[i].score;
2133 bb->highscores[i].level = currentlevel;
2134 bb->highscores[i].score = currentscore;
2135 currentlevel = templevel;
2136 currentscore = tempscore;
2141 return position;
2144 /*****************************************************************************
2145 * bubbles_loadscores() loads the high scores saved file.
2146 ******************************************************************************/
2147 static void bubbles_loadscores(struct game_context* bb) {
2148 int fd;
2150 bb->dirty = false;
2152 /* clear high scores */
2153 bb->highlevel = 0;
2154 rb->memset(bb->highscores, 0, sizeof(bb->highscores));
2156 /* open scores file */
2157 fd = rb->open(SCORE_FILE, O_RDONLY);
2158 if(fd < 0) return;
2160 /* read in high scores */
2161 rb->read(fd, &bb->highlevel, sizeof(bb->highlevel));
2162 if(rb->read(fd, bb->highscores, sizeof(bb->highscores)) <= 0) {
2163 /* scores are bad, reset */
2164 rb->memset(bb->highscores, 0, sizeof(bb->highscores));
2167 if( bb->highlevel >= NUM_LEVELS )
2168 bb->highlevel = NUM_LEVELS - 1;
2170 rb->close(fd);
2173 /*****************************************************************************
2174 * bubbles_savescores() saves the high scores saved file.
2175 ******************************************************************************/
2176 static void bubbles_savescores(struct game_context* bb) {
2177 int fd;
2179 /* write out the high scores to the save file */
2180 fd = rb->open(SCORE_FILE, O_WRONLY|O_CREAT);
2181 rb->write(fd, &bb->highlevel, sizeof(bb->highlevel));
2182 rb->write(fd, bb->highscores, sizeof(bb->highscores));
2183 rb->close(fd);
2184 bb->dirty = false;
2187 /*****************************************************************************
2188 * bubbles_loadgame() loads the saved game and returns load success.
2189 ******************************************************************************/
2190 static bool bubbles_loadgame(struct game_context* bb) {
2191 int fd;
2192 bool loaded = false;
2194 /* open game file */
2195 fd = rb->open(SAVE_FILE, O_RDONLY);
2196 if(fd < 0) return loaded;
2198 /* read in saved game */
2199 while(true) {
2200 if(rb->read(fd, &bb->score, sizeof(bb->score)) <= 0) break;
2201 if(rb->read(fd, &bb->level, sizeof(bb->level)) <= 0) break;
2202 if(rb->read(fd, &bb->angle, sizeof(bb->angle)) <= 0) break;
2203 if(rb->read(fd, &bb->shots, sizeof(bb->shots)) <= 0) break;
2204 if(rb->read(fd, &bb->compress, sizeof(bb->compress)) <= 0) break;
2205 if(rb->read(fd, &bb->onboardcnt, sizeof(bb->onboardcnt)) <= 0) break;
2206 if(rb->read(fd, bb->onboard, sizeof(bb->onboard)) <= 0) break;
2207 if(rb->read(fd, &bb->nextinq, sizeof(bb->nextinq)) <= 0) break;
2208 if(rb->read(fd, bb->queue, sizeof(bb->queue)) <= 0) break;
2209 if(rb->read(fd, &bb->elapsedlvl, sizeof(bb->elapsedlvl)) <= 0) break;
2210 if(rb->read(fd, bb->playboard, sizeof(bb->playboard)) <= 0) break;
2211 bb->resume = true;
2212 loaded = true;
2213 break;
2216 rb->close(fd);
2218 /* delete saved file */
2219 rb->remove(SAVE_FILE);
2220 return loaded;
2223 /*****************************************************************************
2224 * bubbles_savegame() saves the current game state.
2225 ******************************************************************************/
2226 static void bubbles_savegame(struct game_context* bb) {
2227 int fd;
2229 /* write out the game state to the save file */
2230 fd = rb->open(SAVE_FILE, O_WRONLY|O_CREAT);
2231 rb->write(fd, &bb->score, sizeof(bb->score));
2232 rb->write(fd, &bb->level, sizeof(bb->level));
2233 rb->write(fd, &bb->angle, sizeof(bb->angle));
2234 rb->write(fd, &bb->shots, sizeof(bb->shots));
2235 rb->write(fd, &bb->compress, sizeof(bb->compress));
2236 rb->write(fd, &bb->onboardcnt, sizeof(bb->onboardcnt));
2237 rb->write(fd, bb->onboard, sizeof(bb->onboard));
2238 rb->write(fd, &bb->nextinq, sizeof(bb->nextinq));
2239 rb->write(fd, bb->queue, sizeof(bb->queue));
2240 rb->write(fd, &bb->elapsedlvl, sizeof(bb->elapsedlvl));
2241 rb->write(fd, bb->playboard, sizeof(bb->playboard));
2242 rb->close(fd);
2244 bb->resume = true;
2247 /*****************************************************************************
2248 * bubbles_setcolors() set the foreground and background colors.
2249 ******************************************************************************/
2250 static inline void bubbles_setcolors(void) {
2251 #ifdef HAVE_LCD_COLOR
2252 rb->lcd_set_background(LCD_RGBPACK(181,181,222));
2253 rb->lcd_set_foreground(LCD_BLACK);
2254 #endif
2257 /*****************************************************************************
2258 * bubbles_callback() is the default event handler callback which is called
2259 * on usb connect and shutdown.
2260 ******************************************************************************/
2261 static void bubbles_callback(void* param) {
2262 struct game_context* bb = (struct game_context*) param;
2263 if(bb->dirty) {
2264 rb->splash(HZ/2, "Saving high scores...");
2265 bubbles_savescores(bb);
2269 /*****************************************************************************
2270 * bubbles_handlebuttons() handles button events during a game.
2271 ******************************************************************************/
2272 static int bubbles_handlebuttons(struct game_context* bb, bool animblock,
2273 int timeout) {
2274 int button;
2275 int buttonres;
2276 long start;
2277 const struct button_mapping *plugin_contexts[]
2278 #if CONFIG_KEYPAD != SANSA_E200_PAD
2279 = {generic_left_right_fire,generic_actions};
2280 #else
2281 = {generic_directions,generic_actions};
2282 #endif
2284 if (timeout < 0)
2285 timeout = 0;
2286 button = pluginlib_getaction(rb,timeout,plugin_contexts,2);
2287 #if defined(HAS_BUTTON_HOLD) && !defined(HAVE_REMOTE_LCD_AS_MAIN)
2288 /* FIXME: Should probably check remote hold here */
2289 if (rb->button_hold())
2290 button = BUBBLES_START;
2291 #endif
2293 switch(button){
2294 case BUBBLES_LEFT_REP:
2295 if(bb->angle > MIN_ANGLE) bb->angle -= ANGLE_STEP_REP;
2296 case BUBBLES_LEFT: /* change angle to the left */
2297 if(bb->angle > MIN_ANGLE) bb->angle -= ANGLE_STEP;
2298 break;
2300 case BUBBLES_RIGHT_REP:
2301 if(bb->angle < MAX_ANGLE) bb->angle += ANGLE_STEP_REP;
2302 case BUBBLES_RIGHT: /* change angle to the right */
2303 if(bb->angle < MAX_ANGLE) bb->angle += ANGLE_STEP;
2304 break;
2306 case BUBBLES_SELECT: /* fire the shot */
2307 if(!animblock) {
2308 bb->elapsedlvl += bb->elapsedshot;
2309 bb->elapsedshot = 0;
2310 buttonres = bubbles_fire(bb);
2311 if(buttonres != BB_NONE) return buttonres;
2312 buttonres = bubbles_checklevel(bb);
2313 if(buttonres != BB_NONE) return buttonres;
2314 bb->startedshot = *rb->current_tick;
2316 break;
2318 case BUBBLES_START: /* pause the game */
2319 start = *rb->current_tick;
2320 rb->splash(1, "Paused");
2321 while(pluginlib_getaction(rb,TIMEOUT_BLOCK,plugin_contexts,2)
2322 != (BUBBLES_START));
2323 bb->startedshot += *rb->current_tick-start;
2324 bubbles_drawboard(bb);
2325 rb->lcd_update();
2326 break;
2328 case BUBBLES_RESUME: /* save and end the game */
2329 if(!animblock) {
2330 rb->splash(HZ/2, "Saving game...");
2331 bubbles_savegame(bb);
2332 return BB_END;
2334 break;
2335 case BUBBLES_QUIT: /* end the game */
2336 return BB_END;
2338 case ACTION_UNKNOWN:
2339 case ACTION_NONE: /* no button pressed */
2340 break;
2342 default:
2343 if(rb->default_event_handler_ex(button, bubbles_callback,
2344 (void*) bb) == SYS_USB_CONNECTED)
2345 return BB_USB;
2346 break;
2349 return BB_NONE;
2352 /*****************************************************************************
2353 * bubbles() is the main game subroutine, it returns the final game status.
2354 ******************************************************************************/
2355 static int bubbles(struct game_context* bb) {
2356 int i;
2357 int w, h;
2358 int button;
2359 int buttonres;
2360 unsigned int startlevel = 0;
2361 char *title = "Bubbles";
2362 bool startgame = false;
2363 bool showscores = false;
2364 long timeout;
2365 const struct button_mapping *plugin_contexts[]
2366 = {generic_actions,generic_directions};
2368 bubbles_setcolors();
2370 /* don't resume by default */
2371 bb->resume = false;
2373 /********************
2374 * menu *
2375 ********************/
2376 while(!startgame){
2377 char str[30];
2378 rb->lcd_clear_display();
2380 if(!showscores) {
2381 /* welcome screen to display key bindings */
2382 rb->lcd_getstringsize(title, &w, &h);
2383 rb->lcd_putsxy((LCD_WIDTH-w)/2, 0, title);
2384 #if (CONFIG_KEYPAD == IRIVER_H100_PAD) || (CONFIG_KEYPAD == IRIVER_H300_PAD)
2385 rb->lcd_puts(0, 2, "ON to start/pause");
2386 rb->lcd_puts(0, 3, "MODE to save/resume");
2387 rb->lcd_puts(0, 4, "OFF to exit");
2388 rb->lcd_puts(0, 5, "SELECT to fire");
2389 rb->lcd_puts(0, 6, " and show high scores");
2390 rb->lcd_puts(0, 7, "LEFT/RIGHT to aim");
2391 rb->lcd_puts(0, 8, "UP/DOWN to change level");
2392 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || (CONFIG_KEYPAD == IPOD_3G_PAD) || \
2393 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
2394 rb->lcd_puts(0, 2, "PLAY to start/pause");
2395 rb->lcd_puts(0, 3, "MENU to save/resume");
2396 rb->lcd_puts(0, 4, "MENU+SELECT to exit");
2397 rb->lcd_puts(0, 5, "SELECT to fire");
2398 rb->lcd_puts(0, 6, " and show high scores");
2399 rb->lcd_puts(0, 7, "SCROLL to aim");
2400 rb->lcd_puts(0, 8, " and to change level");
2401 #elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
2402 rb->lcd_puts(0, 2, "PLAY to start/pause");
2403 rb->lcd_puts(0, 3, "REC to save/resume");
2404 rb->lcd_puts(0, 4, "POWER to exit");
2405 rb->lcd_puts(0, 5, "SELECT to fire");
2406 rb->lcd_puts(0, 6, " and show high scores");
2407 rb->lcd_puts(0, 7, "LEFT/RIGHT to aim");
2408 rb->lcd_puts(0, 8, "UP/DOWN to change level");
2409 #elif CONFIG_KEYPAD == GIGABEAT_PAD
2410 rb->lcd_puts(0, 2, "POWER to start/pause");
2411 rb->lcd_puts(0, 3, "MENU to save/resume");
2412 rb->lcd_puts(0, 4, "A to exit");
2413 rb->lcd_puts(0, 5, "SELECT to fire");
2414 rb->lcd_puts(0, 6, " and show high scores");
2415 rb->lcd_puts(0, 7, "LEFT/RIGHT to aim");
2416 rb->lcd_puts(0, 8, "UP/DOWN to change level");
2417 #elif CONFIG_KEYPAD == RECORDER_PAD
2418 rb->lcd_puts_scroll(0, 2, "ON to start/pause, "
2419 "F1 to save/resume, "
2420 "OFF to exit, "
2421 "PLAY to fire and show high scores, "
2422 "LEFT/RIGHT to aim, "
2423 "UP/DOWN to change level.");
2424 #elif CONFIG_KEYPAD == ONDIO_PAD
2425 rb->lcd_puts_scroll(0, 2, "MODE to start/pause, "
2426 "DOWN to save/resume, "
2427 "OFF to exit, "
2428 "UP to fire and show high scores, "
2429 "LEFT/RIGHT to aim and to change level.");
2430 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
2431 rb->lcd_puts(0, 2, "PLAY to start/pause");
2432 rb->lcd_puts(0, 3, "FF to save/resume");
2433 rb->lcd_puts(0, 4, "POWER to exit");
2434 rb->lcd_puts(0, 5, "REW/UP to fire");
2435 rb->lcd_puts(0, 6, " and show high scores");
2436 rb->lcd_puts(0, 7, "LEFT/RIGHT to aim");
2437 rb->lcd_puts(0, 8, "UP/DOWN to change level");
2438 #elif CONFIG_KEYPAD == SANSA_E200_PAD
2439 rb->lcd_puts(0, 2, "PLAY to start/pause");
2440 rb->lcd_puts(0, 3, "SUBMENU to save/resume");
2441 rb->lcd_puts(0, 4, "POWER to exit");
2442 rb->lcd_puts(0, 5, "SELECT to fire");
2443 rb->lcd_puts(0, 6, " and show high scores");
2444 rb->lcd_puts(0, 7, "SCROLL to aim");
2445 rb->lcd_puts(0, 8, " and change level");
2446 #elif CONFIG_KEYPAD == SANSA_C200_PAD
2447 rb->lcd_puts(0, 2, "PLAY to start/pause");
2448 rb->lcd_puts(0, 3, "SUBMENU to save/resume");
2449 rb->lcd_puts(0, 4, "POWER to exit");
2450 rb->lcd_puts_scroll(0, 5, "SELECT to fire and show high scores, "
2451 "LEFT/RIGHT to aim and change level");
2452 #elif CONFIG_KEYPAD == IAUDIO_M3_PAD
2453 rb->lcd_puts(0, 2, "PLAY to start/pause");
2454 rb->lcd_puts(0, 3, "MENU to save/resume");
2455 rb->lcd_puts(0, 4, "REC to exit");
2456 rb->lcd_puts(0, 5, "MODE to fire");
2457 rb->lcd_puts(0, 6, " and show high scores");
2458 rb->lcd_puts(0, 7, "REW/FF to aim");
2459 rb->lcd_puts(0, 8, "VOL UP/DN to chg. lvl");
2460 #endif
2461 #if LCD_WIDTH >= 138
2462 rb->snprintf(str, 28, "Start on level %d of %d", startlevel+1,
2463 bb->highlevel+1);
2464 #else
2465 rb->snprintf(str, 28, "Start on lvl %d/%d", startlevel+1,
2466 bb->highlevel+1);
2467 #endif
2468 rb->lcd_puts(0, MIN(TEXT_LINES-3,10), str);
2469 rb->lcd_puts(0, MIN(TEXT_LINES-2,12), "High Score:");
2470 rb->snprintf(str, 30, "%d, Lvl %d",
2471 bb->highscores[0].score, bb->highscores[0].level);
2472 rb->lcd_puts(2, MIN(TEXT_LINES-1,13), str);
2473 } else {
2474 /* show high scores */
2475 rb->snprintf(str, 12, "High Scores");
2476 rb->lcd_getstringsize(str, &w, &h);
2477 rb->lcd_putsxy((LCD_WIDTH-w)/2, 0, str);
2479 for(i=0; i<NUM_SCORES; i++) {
2480 rb->snprintf(str, 30, "#%02d: %d, Lvl %d", i+1,
2481 bb->highscores[i].score, bb->highscores[i].level);
2482 rb->lcd_puts(0, i+2, str);
2486 rb->lcd_update();
2488 /* handle menu button presses */
2489 button = pluginlib_getaction(rb,TIMEOUT_BLOCK,plugin_contexts,2);
2490 switch(button){
2491 case BUBBLES_START: /* start playing */
2492 bb->level = startlevel;
2493 startgame = true;
2494 break;
2495 case BUBBLES_QUIT: /* quit program */
2496 if(showscores) {
2497 showscores = false;
2498 break;
2500 return BB_QUIT;
2502 case BUBBLES_RESUME: /* resume game */
2503 if(!bubbles_loadgame(bb)) {
2504 rb->splash(HZ*2, "Nothing to resume");
2505 } else {
2506 startgame = true;
2508 break;
2510 case BUBBLES_SELECT: /* toggle high scores */
2511 showscores = !showscores;
2512 break;
2514 case BUBBLES_LVLINC: /* increase starting level */
2515 case BUBBLES_LVLINC_REP:
2516 if(startlevel >= bb->highlevel) {
2517 startlevel = 0;
2518 } else {
2519 startlevel++;
2521 break;
2523 case BUBBLES_LVLDEC: /* decrease starting level */
2524 case BUBBLES_LVLDEC_REP:
2525 if(startlevel <= 0) {
2526 startlevel = bb->highlevel;
2527 } else {
2528 startlevel--;
2530 break;
2532 default:
2533 if(rb->default_event_handler_ex(button, bubbles_callback,
2534 (void*) bb) == SYS_USB_CONNECTED)
2535 return BB_USB;
2536 break;
2540 /********************
2541 * init *
2542 ********************/
2543 bubbles_init(bb);
2544 bubbles_drawboard(bb);
2545 rb->lcd_update();
2547 /**********************
2548 * play *
2549 **********************/
2550 bb->startedshot = *rb->current_tick;
2552 while(true) {
2553 /* refresh the board */
2554 bubbles_drawboard(bb);
2555 rb->lcd_update();
2557 /* manange idle framerate */
2558 bb->elapsedshot = *rb->current_tick-bb->startedshot;
2560 if(MAX_SHOTTIME-bb->elapsedshot < HZ/2) {
2561 timeout = MAX_SHOTTIME-bb->elapsedshot;
2562 } else {
2563 timeout = HZ/2;
2566 /* handle button events */
2567 buttonres = bubbles_handlebuttons(bb, false, timeout);
2568 if(buttonres != BB_NONE) return buttonres;
2570 /* handle timing */
2571 bb->elapsedshot = *rb->current_tick-bb->startedshot;
2573 if(bb->elapsedshot > MAX_SHOTTIME) {
2574 bb->elapsedlvl += bb->elapsedshot;
2575 bb->elapsedshot = 0;
2576 buttonres = bubbles_fire(bb);
2577 if(buttonres != BB_NONE) return buttonres;
2578 buttonres = bubbles_checklevel(bb);
2579 if(buttonres != BB_NONE) return buttonres;
2580 bb->startedshot = *rb->current_tick;
2585 /*****************************************************************************
2586 * plugin entry point.
2587 ******************************************************************************/
2588 enum plugin_status plugin_start(struct plugin_api* api, void* parameter) {
2589 struct game_context bb;
2590 bool exit = false;
2591 int position;
2593 /* plugin init */
2594 (void)parameter;
2595 rb = api;
2596 /* end of plugin init */
2598 /* more init */
2599 xlcd_init(rb);
2601 /* load files */
2602 rb->splash(0, "Loading...");
2603 bubbles_loadscores(&bb);
2604 rb->lcd_clear_display();
2606 /* start app */
2607 #if LCD_DEPTH > 1
2608 rb->lcd_set_backdrop(NULL);
2609 #endif
2610 rb->lcd_setfont(FONT_SYSFIXED);
2612 while(!exit) {
2613 switch(bubbles(&bb)){
2614 char str[19];
2615 case BB_WIN:
2616 rb->splash(HZ*2, "You Win!");
2617 /* record high level */
2618 if( NUM_LEVELS-1 > bb.highlevel) {
2619 bb.highlevel = NUM_LEVELS-1;
2620 bb.dirty = true;
2623 /* record high score */
2624 if((position = bubbles_recordscore(&bb))) {
2625 rb->snprintf(str, 19, "New high score #%d!", position);
2626 rb->splash(HZ*2, str);
2628 break;
2630 case BB_LOSE:
2631 rb->splash(HZ*2, "Game Over");
2632 /* fall through to BB_END */
2634 case BB_END:
2635 if(!bb.resume) {
2636 /* record high level */
2637 if(bb.level-1 > bb.highlevel) {
2638 bb.highlevel = bb.level-1;
2639 bb.dirty = true;
2642 /* record high score */
2643 if((position = bubbles_recordscore(&bb))) {
2644 rb->snprintf(str, 19, "New high score #%d!", position);
2645 rb->splash(HZ*2, str);
2648 break;
2650 case BB_USB:
2651 rb->lcd_setfont(FONT_UI);
2652 return PLUGIN_USB_CONNECTED;
2654 case BB_QUIT:
2655 if(bb.dirty) {
2656 rb->splash(HZ/2, "Saving high scores...");
2657 bubbles_savescores(&bb);
2659 exit = true;
2660 break;
2662 default:
2663 break;
2667 rb->lcd_setfont(FONT_UI);
2668 return PLUGIN_OK;
2671 #endif