Correct butoon help text for ipods, fixes FS#7243
[Rockbox.git] / apps / plugins / bubbles.c
blob689e9de598aea05d77836a70c4c8b74ec16b10d4
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"
23 #include "xlcd.h"
24 #include "pluginlib_actions.h"
26 #ifdef HAVE_LCD_BITMAP
28 PLUGIN_HEADER
30 /* files */
31 #define SCORE_FILE PLUGIN_DIR "/bubbles.score"
32 #define SAVE_FILE PLUGIN_DIR "/bubbles.save"
34 /* final game return status */
35 #define BB_NONE 5
36 #define BB_WIN 4
37 #define BB_END 3
38 #define BB_USB 2
39 #define BB_QUIT 1
40 #define BB_LOSE 0
42 /* play board dimension */
43 #define BB_HEIGHT 12
44 #define BB_WIDTH 8
45 #define BB_LEVEL_HEIGHT 10
47 /* various amounts */
48 #define NUM_SCORES 10
49 #define NUM_LEVELS 100
50 #define NUM_QUEUE 2
51 #define NUM_BUBBLES 8
52 #define MIN_ANGLE -76
53 #define MAX_ANGLE 76
54 #define NUM_COMPRESS 9
55 #define MAX_SHOTTIME 1000
57 /* keyboard layouts */
58 #define BUBBLES_LEFT PLA_LEFT
59 #define BUBBLES_LEFT_REP PLA_LEFT_REPEAT
60 #define BUBBLES_RIGHT PLA_RIGHT
61 #define BUBBLES_RIGHT_REP PLA_RIGHT_REPEAT
62 #define BUBBLES_QUIT PLA_QUIT
63 #define BUBBLES_START PLA_START
64 #define BUBBLES_SELECT PLA_FIRE
65 #define BUBBLES_RESUME PLA_MENU
67 #if CONFIG_KEYPAD != ONDIO_PAD
69 #define BUBBLES_LVLINC PLA_UP
70 #define BUBBLES_LVLINC_REP PLA_UP_REPEAT
71 #define BUBBLES_LVLDEC PLA_DOWN
72 #define BUBBLES_LVLDEC_REP PLA_DOWN_REPEAT
74 #else /* ondio keys */
76 #define BUBBLES_LVLINC PLA_RIGHT
77 #define BUBBLES_LVLINC_REP PLA_RIGHT_REPEAT
78 #define BUBBLES_LVLDEC PLA_LEFT
79 #define BUBBLES_LVLDEC_REP PLA_LEFT_REPEAT
81 #endif
84 /* bubbles will consume height of ROW_HEIGHT*(BB_HEIGHT-1)+BUBBLE_HEIGHT*3/2 */
85 /* 22x22 bubbles (iPod Video) */
86 #if (LCD_HEIGHT == 240) && (LCD_WIDTH == 320)
87 #define BUBBLE_WIDTH 22
88 #define BUBBLE_HEIGHT 22
89 #define EMBLEM_WIDTH 16
90 #define EMBLEM_HEIGHT 16
91 #define XOFS 72
92 #define ROW_HEIGHT 18
93 #define ROW_INDENT 11
94 #define MAX_FPS 40
96 /* 22x22 bubbles (Gigabeat) */
97 #elif (LCD_HEIGHT == 320) && (LCD_WIDTH == 240)
98 #define BUBBLE_WIDTH 22
99 #define BUBBLE_HEIGHT 22
100 #define EMBLEM_WIDTH 16
101 #define EMBLEM_HEIGHT 16
102 #define XOFS 64
103 #define ROW_HEIGHT 18
104 #define ROW_INDENT 11
105 #define MAX_FPS 30
107 /* 16x16 bubbles (H300, iPod Color) */
108 #elif (LCD_HEIGHT == 176) && (LCD_WIDTH == 220)
109 #define BUBBLE_WIDTH 16
110 #define BUBBLE_HEIGHT 16
111 #define EMBLEM_WIDTH 12
112 #define EMBLEM_HEIGHT 12
113 #define XOFS 46
114 #define ROW_HEIGHT 14
115 #define ROW_INDENT 8
116 #define MAX_FPS 30
118 /* 16x16 bubbles (Sansa E200) */
119 #elif (LCD_HEIGHT == 220) && (LCD_WIDTH == 176)
120 #define BUBBLE_WIDTH 16
121 #define BUBBLE_HEIGHT 16
122 #define EMBLEM_WIDTH 12
123 #define EMBLEM_HEIGHT 12
124 #define XOFS 48
125 #define ROW_HEIGHT 14
126 #define ROW_INDENT 8
127 #define MAX_FPS 30
129 /* 12x12 bubbles (iPod Nano) */
130 #elif (LCD_HEIGHT == 132) && (LCD_WIDTH == 176)
131 #define BUBBLE_WIDTH 12
132 #define BUBBLE_HEIGHT 12
133 #define EMBLEM_WIDTH 8
134 #define EMBLEM_HEIGHT 8
135 #define XOFS 40
136 #define ROW_HEIGHT 10
137 #define ROW_INDENT 6
138 #define MAX_FPS 40
140 /* 12x12 bubbles (H100, H10, iAudio X5, iPod 3G, iPod 4G grayscale) */
141 #elif (LCD_HEIGHT == 128) && ((LCD_WIDTH == 160) || (LCD_WIDTH == 128))
142 #define BUBBLE_WIDTH 12
143 #define BUBBLE_HEIGHT 12
144 #define EMBLEM_WIDTH 8
145 #define EMBLEM_HEIGHT 8
146 #define XOFS 33
147 #define ROW_HEIGHT 10
148 #define ROW_INDENT 6
149 #define MAX_FPS 30
151 /* 10x10 bubbles (iPod Mini) */
152 #elif (LCD_HEIGHT == 110) && (LCD_WIDTH == 138)
153 #define BUBBLE_WIDTH 10
154 #define BUBBLE_HEIGHT 10
155 #define EMBLEM_WIDTH 6
156 #define EMBLEM_HEIGHT 6
157 #define XOFS 33
158 #define ROW_HEIGHT 8
159 #define ROW_INDENT 5
160 #define MAX_FPS 30
162 /* 8x7 bubbles (Archos recorder, Ondio) */
163 #elif (LCD_HEIGHT == 64) && (LCD_WIDTH == 112)
164 #define BUBBLE_WIDTH 8
165 #define BUBBLE_HEIGHT 7
166 #define EMBLEM_WIDTH 7
167 #define EMBLEM_HEIGHT 5
168 #define XOFS 33
169 #define ROW_HEIGHT 5
170 #define ROW_INDENT 4
171 #define MAX_FPS 20
173 #else
174 #error BUBBLES: Unsupported LCD type
175 #endif
177 #define TEXT_LINES (LCD_HEIGHT/8)
179 /* shot position */
180 #define SHOTX XOFS+ROW_INDENT+BUBBLE_WIDTH*3
181 #define SHOTY ROW_HEIGHT*(BB_HEIGHT-1)+BUBBLE_HEIGHT/2
183 /* collision distance squared */
184 #define MIN_DISTANCE ((BUBBLE_WIDTH*8)/10)*((BUBBLE_HEIGHT*8)/10)
186 /* external bitmaps */
187 extern const fb_data bubbles_bubble[];
188 extern const fb_data bubbles_emblem[];
189 #ifdef HAVE_LCD_COLOR
190 extern const fb_data bubbles_left[];
191 /* skip right border for square screens */
192 #if (LCD_WIDTH > LCD_HEIGHT)
193 extern const fb_data bubbles_right[];
194 #endif
195 #endif
197 /* global rockbox api */
198 static struct plugin_api* rb;
200 /* levels */
201 char level[NUM_LEVELS][BB_LEVEL_HEIGHT][BB_WIDTH] = {
202 {{ 6, 6, 4, 4, 2, 2, 3, 3},
203 { 6, 6, 4, 4, 2, 2, 3, -1},
204 { 2, 2, 3, 3, 6, 6, 4, 4},
205 { 2, 3, 3, 6, 6, 4, 4, -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, -1, -1, -1, -1, -1, -1, -1}},
212 {{-1, 7, 7, 7, 7, 7, 7, -1},
213 {-1, 1, 1, 1, 1, 1, -1, -1},
214 {-1, -1, 2, 2, 2, 2, -1, -1},
215 {-1, -1, -1, 2, -1, -1, -1, -1},
216 {-1, -1, -1, 2, 2, -1, -1, -1},
217 {-1, -1, -1, 5, -1, -1, -1, -1},
218 {-1, -1, -1, 5, 5, -1, -1, -1},
219 {-1, -1, -1, -1, -1, -1, -1, -1},
220 {-1, -1, -1, -1, -1, -1, -1, -1},
221 {-1, -1, -1, -1, -1, -1, -1, -1}},
222 {{-1, -1, 7, -1, -1, 7, -1, -1},
223 {-1, -1, 7, 1, 7, -1, -1, -1},
224 {-1, -1, -1, 1, 2, -1, -1, -1},
225 {-1, -1, 1, 2, 1, -1, -1, -1},
226 {-1, -1, -1, 2, 5, -1, -1, -1},
227 {-1, -1, 3, 5, 3, -1, -1, -1},
228 {-1, -1, -1, 5, 3, -1, -1, -1},
229 {-1, -1, -1, 3, -1, -1, -1, -1},
230 {-1, -1, -1, -1, -1, -1, -1, -1},
231 {-1, -1, -1, -1, -1, -1, -1, -1}},
232 {{-1, -1, -1, 0, 0, -1, -1, -1},
233 {-1, -1, 5, 0, 1, -1, -1, -1},
234 {-1, -1, 3, 5, 1, 6, -1, -1},
235 {-1, 4, 3, -1, 6, 7, -1, -1},
236 {-1, 7, 4, -1, -1, 7, 4, -1},
237 { 6, 7, -1, -1, -1, 4, 3, -1},
238 { 1, 6, -1, -1, -1, -1, 3, 5},
239 { 1, -1, -1, -1, -1, -1, 5, -1},
240 {-1, -1, -1, -1, -1, -1, -1, -1},
241 {-1, -1, -1, -1, -1, -1, -1, -1}},
242 {{-1, -1, 0, 0, 0, 0, -1, -1},
243 {-1, 0, 1, 1, 1, 0, -1, -1},
244 {-1, 0, 1, 0, 0, 1, 0, -1},
245 {-1, 0, 1, 1, 1, 0, -1, -1},
246 {-1, -1, 0, 0, 0, 0, -1, -1},
247 {-1, -1, 7, -1, 7, -1, -1, -1},
248 {-1, -1, 7, 7, 7, 7, -1, -1},
249 {-1, -1, -1, -1, -1, -1, -1, -1},
250 {-1, -1, -1, -1, -1, -1, -1, -1},
251 {-1, -1, -1, -1, -1, -1, -1, -1}},
252 {{-1, 4, 4, 4, 6, 6, 6, -1},
253 { 4, -1, -1, -1, -1, -1, 6, -1},
254 {-1, 4, -1, -1, -1, -1, 6, -1},
255 { 4, 2, 3, 1, 2, 3, 6, -1},
256 {-1, 3, 1, 2, 3, 1, 2, -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, -1, -1, -1, -1, -1, -1, -1}},
262 {{-1, 4, 4, 4, 6, 6, 6, -1},
263 { 4, -1, -1, -1, -1, -1, 6, -1},
264 {-1, 4, -1, -1, -1, -1, 6, -1},
265 { 4, 2, 3, 1, 2, 3, 6, -1},
266 {-1, 3, 1, 2, 3, 1, 2, -1},
267 {-1, 2, 3, 1, 2, 3, -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, -1, -1, -1, -1, -1, -1, -1}},
272 {{-1, 0, 0, -1, -1, 2, 2, -1},
273 {-1, 5, -1, -1, -1, 3, -1, -1},
274 {-1, 0, -1, -1, -1, 6, -1, -1},
275 {-1, 3, -1, -1, -1, 0, -1, -1},
276 {-1, 4, -1, -1, -1, 5, -1, -1},
277 {-1, 2, -1, -1, -1, 3, -1, -1},
278 {-1, 2, -1, -1, -1, 1, -1, -1},
279 {-1, 3, -1, -1, -1, 4, -1, -1},
280 {-1, -1, -1, -1, -1, -1, -1, -1},
281 {-1, -1, -1, -1, -1, -1, -1, -1}},
282 {{ 3, -1, -1, -1, -1, -1, -1, 3},
283 { 6, 3, 2, 4, 6, 3, 2, -1},
284 { 4, -1, -1, -1, -1, -1, -1, 4},
285 { 2, 4, 6, 3, 2, 4, 6, -1},
286 {-1, -1, -1, 6, -1, -1, -1, -1},
287 {-1, -1, -1, 3, -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, -1, -1, -1, -1, -1, -1, -1}},
292 {{-1, 2, -1, 1, -1, 1, -1, 2},
293 { 1, 2, -1, 2, 1, -1, 1, -1},
294 { 1, -1, 1, -1, 2, -1, 2, -1},
295 { 2, 1, -1, 1, 2, -1, 2, -1},
296 {-1, 2, -1, 2, -1, 2, -1, 2},
297 { 1, 2, -1, 2, 1, -1, 1, -1},
298 { 1, -1, 1, -1, 2, -1, 1, -1},
299 { 2, 2, -1, 1, 1, -1, 2, -1},
300 {-1, 2, -1, 1, -1, 1, -1, 1},
301 {-1, -1, -1, -1, -1, -1, -1, -1}},
302 {{-1, 7, 7, -1, -1, 5, 5, -1},
303 { 1, -1, -1, -1, -1, -1, 4, -1},
304 { 2, 1, -1, -1, -1, -1, 4, 3},
305 { 2, -1, -1, -1, -1, -1, 3, -1},
306 { 1, 2, -1, -1, -1, -1, 3, 4},
307 { 1, -1, -1, -1, -1, -1, 4, -1},
308 { 7, 1, -1, -1, -1, -1, 4, 5},
309 { 7, 7, -1, -1, -1, 5, 5, -1},
310 {-1, -1, -1, -1, -1, -1, -1, -1},
311 {-1, -1, -1, -1, -1, -1, -1, -1}},
312 {{ 7, 7, -1, -1, -1, -1, 5, 5},
313 { 1, 5, -1, -1, -1, 7, 4, -1},
314 { 2, 1, -1, -1, -1, -1, 4, 3},
315 { 2, -1, -1, -1, -1, -1, 3, -1},
316 { 1, 5, -1, -1, -1, -1, 7, 4},
317 { 1, -1, -1, -1, -1, -1, 4, -1},
318 { 7, 1, -1, -1, -1, -1, 4, 5},
319 { 7, 5, -1, -1, -1, 7, 5, -1},
320 {-1, -1, -1, -1, -1, -1, -1, -1},
321 {-1, -1, -1, -1, -1, -1, -1, -1}},
322 {{-1, -1, -1, 0, 0, -1, -1, -1},
323 {-1, -1, 5, 0, 1, -1, -1, -1},
324 {-1, -1, 3, 5, 1, 6, -1, -1},
325 {-1, 4, 3, 2, 6, 2, -1, -1},
326 {-1, 7, 4, 7, 2, 2, 4, -1},
327 { 6, 7, 7, 3, 3, 4, 3, -1},
328 { 1, 6, 1, 1, 1, 3, 3, 5},
329 { 1, 1, -1, -1, -1, -1, 5, -1},
330 {-1, -1, -1, -1, -1, -1, -1, -1},
331 {-1, -1, -1, -1, -1, -1, -1, -1}},
332 {{-1, -1, 0, -1, -1, 0, -1, -1},
333 {-1, 3, 3, -1, 3, 3, -1, -1},
334 {-1, 0, 2, 0, 0, 2, 0, -1},
335 {-1, 3, 3, -1, 3, 3, -1, -1},
336 {-1, -1, 0, -1, -1, 0, -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, -1, 1, 1, -1, -1, -1},
343 {-1, -1, 2, 2, 2, -1, -1, -1},
344 {-1, -1, 3, 3, 3, 3, -1, -1},
345 {-1, 4, 4, 4, 4, 4, -1, -1},
346 {-1, 5, 5, 5, 5, 5, 5, -1},
347 {-1, -1, -1, 6, -1, -1, -1, -1},
348 {-1, -1, -1, 7, 7, -1, -1, -1},
349 {-1, -1, -1, 0, -1, -1, -1, -1},
350 {-1, -1, -1, -1, -1, -1, -1, -1},
351 {-1, -1, -1, -1, -1, -1, -1, -1}},
352 {{-1, -1, -1, 2, 5, -1, -1, -1},
353 {-1, 4, 3, -1, -1, -1, -1, -1},
354 { 6, 7, -1, 5, 2, -1, -1, -1},
355 {-1, -1, -1, -1, 3, 4, -1, -1},
356 {-1, -1, -1, 2, 5, -1, 7, 6},
357 {-1, 4, 3, -1, -1, -1, -1, -1},
358 { 6, 7, -1, 5, 2, -1, -1, -1},
359 {-1, -1, -1, -1, 3, 4, -1, -1},
360 {-1, -1, -1, -1, -1, -1, 7, 6},
361 {-1, -1, -1, -1, -1, -1, -1, -1}},
362 {{-1, -1, -1, 5, 5, -1, -1, -1},
363 {-1, -1, -1, 3, -1, -1, -1, -1},
364 {-1, -1, -1, 1, -1, -1, -1, -1},
365 {-1, -1, -1, 7, -1, -1, -1, -1},
366 {-1, -1, -1, 2, -1, -1, -1, -1},
367 {-1, -1, -1, 4, -1, -1, -1, -1},
368 {-1, -1, -1, 5, -1, -1, -1, -1},
369 {-1, -1, -1, 3, -1, -1, -1, -1},
370 {-1, -1, -1, -1, -1, -1, -1, -1},
371 {-1, -1, -1, -1, -1, -1, -1, -1}},
372 {{-1, -1, -1, 0, 1, -1, -1, -1},
373 {-1, -1, 0, 2, 7, 7, -1, -1},
374 {-1, -1, -1, 0, 1, 7, -1, -1},
375 {-1, 0, 0, 0, 0, -1, -1, -1},
376 {-1, 0, 0, 0, 1, 1, -1, -1},
377 { 0, 0, 0, 1, 1, 1, -1, -1},
378 {-1, 0, 0, 1, 1, 1, -1, -1},
379 {-1, 0, 0, 0, 7, 7, -1, -1},
380 {-1, -1, 7, 7, -1, -1, -1, -1},
381 {-1, -1, -1, -1, -1, -1, -1, -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, 5, -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, -1, -1},
388 {-1, 1, -1, -1, -1, -1, -1, -1},
389 { 1, -1, -1, -1, -1, -1, -1, -1},
390 {-1, 2, 3, 4, 7, 6, 5, -1},
391 {-1, -1, -1, -1, -1, -1, -1, -1}},
392 {{-1, 6, -1, -1, -1, -1, -1, -1},
393 { 5, -1, -1, -1, -1, -1, -1, -1},
394 { 2, 3, 4, 7, 6, 5, 2, 3},
395 {-1, -1, -1, -1, -1, -1, 4, -1},
396 {-1, -1, -1, -1, -1, -1, 7, -1},
397 {-1, 4, 3, 2, 5, 6, -1, -1},
398 {-1, 7, -1, -1, -1, -1, -1, -1},
399 { 6, -1, -1, -1, -1, -1, -1, -1},
400 { 5, 2, 3, 4, 7, 6, 5, -1},
401 {-1, -1, -1, -1, -1, -1, -1, -1}},
402 {{ 3, 2, 1, 0, 0, 1, 2, 3},
403 { 3, 2, 1, 0, 1, 2, 3, -1},
404 { 4, 3, 2, 1, 1, 2, 3, 4},
405 { 4, 3, 2, 1, 2, 3, 4, -1},
406 { 5, 4, 3, 2, 2, 3, 4, 5},
407 { 5, 4, 3, 2, 3, 4, 5, -1},
408 { 6, 5, 4, 3, 3, 4, 5, 6},
409 { 6, 5, 4, 3, 4, 5, 6, -1},
410 { 7, 6, 5, 4, 4, 5, 6, 7},
411 {-1, -1, -1, -1, -1, -1, -1, -1}},
412 {{-1, -1, -1, 5, 5, -1, -1, -1},
413 {-1, -1, -1, 3, -1, -1, -1, -1},
414 {-1, -1, -1, 2, 4, -1, -1, -1},
415 {-1, -1, -1, 6, -1, -1, -1, -1},
416 {-1, -1, -1, 2, 4, -1, -1, -1},
417 {-1, 2, -1, 5, -1, 4, -1, -1},
418 { 1, 0, 1, 0, 1, 0, 1, 0},
419 { 3, -1, 3, -1, 2, -1, 6, -1},
420 {-1, -1, -1, -1, -1, -1, -1, -1},
421 {-1, -1, -1, -1, -1, -1, -1, -1}},
422 {{-1, -1, -1, -1, 1, -1, -1, -1},
423 { 7, 4, 3, 5, -1, -1, -1, -1},
424 { 6, -1, -1, 1, -1, -1, -1, -1},
425 {-1, -1, -1, 5, 3, 4, 7, -1},
426 { 6, -1, -1, -1, 1, -1, -1, 6},
427 { 7, 4, 3, 5, -1, -1, -1, -1},
428 {-1, -1, -1, 1, -1, -1, -1, 6},
429 {-1, -1, -1, 5, 3, 4, 7, -1},
430 {-1, -1, -1, -1, -1, -1, -1, -1},
431 {-1, -1, -1, -1, -1, -1, -1, -1}},
432 {{-1, -1, -1, -1, 7, 3, 6, -1},
433 {-1, -1, 3, 7, 3, 6, 3, -1},
434 {-1, -1, 5, 7, 3, 6, 3, -1},
435 {-1, 6, 7, 3, 6, 7, -1, -1},
436 {-1, 7, 7, 3, 6, 1, -1, -1},
437 { 3, 7, 3, 6, 3, -1, -1, -1},
438 { 5, 6, 2, 7, 1, -1, -1, -1},
439 {-1, -1, -1, -1, -1, -1, -1, -1},
440 {-1, -1, -1, -1, -1, -1, -1, -1},
441 {-1, -1, -1, -1, -1, -1, -1, -1}},
442 {{ 5, -1, -1, -1, -1, -1, -1, 5},
443 { 5, -1, 6, 6, 6, -1, 5, -1},
444 {-1, 5, 4, -1, -1, 4, 5, -1},
445 {-1, 3, -1, -1, -1, 3, -1, -1},
446 {-1, 6, 0, -1, -1, 0, 6, -1},
447 {-1, 3, -1, -1, -1, 3, -1, -1},
448 {-1, -1, 4, -1, -1, 4, -1, -1},
449 {-1, -1, 6, 6, 6, -1, -1, -1},
450 {-1, -1, -1, -1, -1, -1, -1, -1},
451 {-1, -1, -1, -1, -1, -1, -1, -1}},
452 {{-1, 7, 0, -1, -1, 0, 7, -1},
453 { 7, -1, 0, -1, 0, -1, 7, -1},
454 { 7, 1, -1, 0, 0, -1, 1, 7},
455 { 7, 1, 2, 0, 2, 1, 7, -1},
456 { 7, 6, 3, 2, 2, 3, 6, 7},
457 { 7, -1, 3, 2, 3, -1, 7, -1},
458 {-1, 7, 7, 3, 3, 7, 7, -1},
459 {-1, -1, -1, 3, -1, -1, -1, -1},
460 {-1, -1, -1, -1, -1, -1, -1, -1},
461 {-1, -1, -1, -1, -1, -1, -1, -1}},
462 {{-1, 3, -1, 1, -1, 7, -1, 6},
463 { 5, -1, 7, -1, 7, -1, 6, -1},
464 { 6, -1, 0, -1, 5, -1, 3, -1},
465 {-1, 2, -1, 1, -1, 5, -1, -1},
466 {-1, 4, -1, 3, -1, 4, -1, -1},
467 { 2, -1, 3, -1, 2, -1, -1, -1},
468 {-1, -1, 4, -1, 6, -1, -1, -1},
469 {-1, -1, -1, 5, -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, 1, -1, -1, -1},
473 {-1, -1, -1, -1, 3, -1, -1, -1},
474 { 6, 1, 3, 1, 2, 1, 4, 1},
475 {-1, -1, -1, -1, 6, -1, -1, -1},
476 {-1, -1, -1, 4, 1, -1, -1, -1},
477 {-1, -1, 1, -1, 3, -1, -1, -1},
478 {-1, -1, -1, 2, 1, -1, -1, -1},
479 {-1, -1, -1, -1, 4, -1, -1, -1},
480 {-1, -1, -1, 6, 1, -1, -1, -1},
481 {-1, -1, -1, 6, -1, -1, -1, -1}},
482 {{-1, -1, -1, 5, 4, -1, -1, -1},
483 {-1, -1, 4, 1, 0, -1, -1, -1},
484 {-1, -1, -1, 2, 3, -1, -1, -1},
485 {-1, 1, 4, -1, 2, 2, -1, -1},
486 {-1, 3, 1, 2, 5, 1, 4, -1},
487 {-1, 4, 2, -1, 0, 4, -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, -1, -1, 1, -1, -1, -1, -1},
494 {-1, 2, -1, -1, 1, -1, 5, -1},
495 { 5, -1, -1, 1, -1, -1, 0, -1},
496 {-1, 6, -1, -1, 1, -1, 4, -1},
497 {-1, 0, -1, 1, -1, 5, -1, -1},
498 {-1, -1, 5, 5, 0, 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, -1, -1, -1, -1, -1}},
502 {{-1, -1, -1, 6, 3, -1, -1, -1},
503 {-1, -1, 3, 2, 6, -1, -1, -1},
504 {-1, -1, 2, 6, 3, 2, -1, -1},
505 {-1, 6, 3, 2, 6, 3, -1, -1},
506 {-1, 3, 2, 6, 3, 2, 6, -1},
507 { 2, 6, 3, 2, 6, 3, 2, -1},
508 { 6, 3, 2, 6, 3, 2, 6, 3},
509 {-1, -1, -1, -1, -1, -1, -1, -1},
510 {-1, -1, -1, -1, -1, -1, -1, -1},
511 {-1, -1, -1, -1, -1, -1, -1, -1}},
512 {{ 6, 6, 6, 6, 6, 6, 6, 6},
513 { 4, -1, -1, -1, -1, -1, -1, -1},
514 {-1, 3, 2, 5, 7, 6, 4, 3},
515 {-1, 5, -1, -1, -1, -1, -1, -1},
516 {-1, -1, 7, 6, 4, 3, 2, 5},
517 {-1, -1, 4, -1, -1, -1, -1, -1},
518 {-1, -1, -1, 3, 2, 5, 7, 6},
519 {-1, -1, -1, -1, -1, -1, -1, -1},
520 {-1, -1, -1, -1, -1, -1, -1, -1},
521 {-1, -1, -1, -1, -1, -1, -1, -1}},
522 {{ 1, -1, 7, -1, -1, 6, -1, 2},
523 { 6, -1, 1, -1, 6, 1, 3, -1},
524 {-1, 4, -1, 7, 2, -1, 7, -1},
525 { 2, 7, -1, -1, -1, 4, -1, -1},
526 { 6, -1, 3, 5, 0, 2, -1, 7},
527 { 1, -1, -1, -1, -1, -1, 1, -1},
528 {-1, 1, 4, 5, 7, 5, 1, -1},
529 {-1, -1, -1, -1, -1, -1, -1, -1},
530 {-1, -1, -1, -1, -1, -1, -1, -1},
531 {-1, -1, -1, -1, -1, -1, -1, -1}},
532 {{ 6, 6, 6, -1, -1, 6, 6, 6},
533 {-1, -1, 6, -1, 6, -1, -1, -1},
534 {-1, -1, 2, 3, 3, 2, -1, -1},
535 {-1, 3, -1, 5, -1, 3, -1, -1},
536 {-1, -1, 5, 3, 3, 5, -1, -1},
537 {-1, -1, 6, 1, 6, -1, -1, -1},
538 {-1, 4, 2, -1, -1, 2, 4, -1},
539 {-1, -1, -1, -1, -1, -1, -1, -1},
540 {-1, -1, -1, -1, -1, -1, -1, -1},
541 {-1, -1, -1, -1, -1, -1, -1, -1}},
542 {{-1, -1, -1, 5, 5, -1, -1, -1},
543 {-1, -1, 5, -1, -1, -1, -1, -1},
544 {-1, 3, 4, 6, 6, -1, -1, 5},
545 { 3, 3, 4, 6, 5, -1, 5, -1},
546 { 3, 2, 3, 6, 6, 5, 5, -1},
547 { 3, 3, 4, 6, 5, -1, 5, -1},
548 {-1, 3, 4, 6, 6, -1, -1, 5},
549 {-1, -1, 5, -1, -1, -1, -1, -1},
550 {-1, -1, -1, 5, 5, -1, -1, -1},
551 {-1, -1, -1, -1, -1, -1, -1, -1}},
552 {{ 1, -1, -1, -1, -1, -1, -1, 1},
553 { 1, -1, 2, 2, 2, -1, 1, -1},
554 {-1, 1, 2, 3, 3, 2, 1, -1},
555 { 6, 2, 3, -1, 3, 2, 6, -1},
556 { 6, 2, 3, -1, -1, 3, 2, 6},
557 { 6, 2, 3, -1, 3, 2, 6, -1},
558 { 3, 3, 3, 7, 7, 3, 3, 3},
559 { 0, 5, 0, 2, 0, 5, 0, -1},
560 {-1, -1, -1, -1, -1, -1, -1, -1},
561 {-1, -1, -1, -1, -1, -1, -1, -1}},
562 {{-1, -1, 7, 7, 7, -1, -1, -1},
563 {-1, 7, 2, 2, 7, -1, -1, -1},
564 {-1, 7, 5, 5, 5, 7, -1, -1},
565 { 7, 7, 7, 7, 7, 7, -1, -1},
566 {-1, -1, 6, -1, 6, -1, -1, -1},
567 {-1, 6, -1, -1, 6, -1, -1, -1},
568 {-1, 6, 4, 4, -1, 6, 4, 4},
569 {-1, -1, -1, -1, -1, -1, -1, -1},
570 {-1, -1, -1, -1, -1, -1, -1, -1},
571 {-1, -1, -1, -1, -1, -1, -1, -1}},
572 {{-1, 3, 3, -1, 3, 3, 3, -1},
573 { 3, 7, 5, 4, 6, 5, 3, -1},
574 { 1, 3, 3, 3, -1, 3, 3, 1},
575 { 2, 1, 2, 1, 2, 1, 2, -1},
576 { 1, 3, 3, -1, 3, 3, 3, 1},
577 { 3, 5, 6, 4, 5, 7, 3, -1},
578 { 2, 3, 3, 3, -1, 3, 3, 2},
579 { 1, 1, 2, 2, 2, 1, 1, -1},
580 {-1, -1, -1, -1, -1, -1, -1, -1},
581 {-1, -1, -1, -1, -1, -1, -1, -1}},
582 {{-1, 6, 5, -1, -1, -1, -1, -1},
583 { 3, 1, 3, -1, -1, -1, -1, -1},
584 {-1, 5, 6, -1, -1, -1, -1, -1},
585 {-1, -1, 5, 3, -1, -1, -1, -1},
586 {-1, -1, 6, 1, 6, -1, -1, -1},
587 {-1, -1, 3, 5, -1, -1, -1, -1},
588 {-1, -1, -1, -1, 3, 6, -1, -1},
589 {-1, -1, -1, 5, 6, 5, -1, -1},
590 {-1, -1, -1, -1, 6, 3, -1, -1},
591 {-1, -1, -1, -1, -1, -1, -1, -1}},
592 {{ 6, 3, 7, 4, 5, 1, 6, 3},
593 { 5, 1, 6, 3, 7, 4, 5, -1},
594 { 6, 3, 7, 4, 5, 1, 6, 3},
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, -1, -1}},
602 {{-1, -1, -1, -1, -1, -1, 4, 4},
603 {-1, -1, 7, 7, 7, 4, 4, -1},
604 {-1, -1, -1, -1, -1, -1, 4, 4},
605 {-1, 1, -1, -1, -1, 7, -1, -1},
606 {-1, 1, 1, -1, -1, 7, -1, -1},
607 { 3, 3, 3, -1, 7, -1, -1, -1},
608 { 3, -1, 2, 3, 3, 3, -1, 3},
609 {-1, 2, -1, 3, -1, 3, 3, -1},
610 {-1, 2, -1, -1, -1, -1, -1, -1},
611 {-1, -1, -1, -1, -1, -1, -1, -1}},
612 {{-1, -1, 4, -1, -1, -1, -1, -1},
613 {-1, 7, 4, -1, -1, -1, -1, -1},
614 {-1, -1, 7, 4, -1, -1, -1, -1},
615 {-1, 4, 7, 4, -1, -1, -1, -1},
616 { 1, 1, 1, 1, 1, 1, 1, -1},
617 { 1, 2, 1, 2, 1, 1, -1, -1},
618 { 2, 2, 2, 2, 2, 2, 2, 2},
619 {-1, -1, -1, -1, -1, -1, -1, -1},
620 {-1, -1, -1, -1, -1, -1, -1, -1},
621 {-1, -1, -1, -1, -1, -1, -1, -1}},
622 {{ 0, -1, -1, -1, -1, -1, -1, 6},
623 { 6, 1, 4, 3, 7, 5, 0, -1},
624 { 0, -1, -1, -1, -1, -1, -1, 6},
625 { 6, 1, 4, 3, 7, 5, 0, -1},
626 { 0, -1, -1, -1, -1, -1, -1, 6},
627 { 6, 1, 4, 3, 7, 5, 0, -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 {-1, -1, -1, -1, -1, -1, -1, -1}},
632 {{ 3, 3, 4, 6, 6, 4, 3, 3},
633 { 0, 3, 4, 6, 4, 3, 1, -1},
634 { 5, 1, 3, 4, 4, 3, 0, 1},
635 { 0, 1, 3, 4, 3, 1, 0, -1},
636 { 2, 1, 6, 3, 3, 0, 0, 1},
637 { 0, 3, 4, 3, 6, 1, 5, -1},
638 { 6, 1, 2, 6, 4, 0, 0, 2},
639 {-1, -1, -1, -1, -1, -1, -1, -1},
640 {-1, -1, -1, -1, -1, -1, -1, -1},
641 {-1, -1, -1, -1, -1, -1, -1, -1}},
642 {{ 6, 6, -1, -1, -1, -1, 4, 4},
643 { 4, 0, -1, -1, -1, 3, 6, -1},
644 { 0, 6, -1, -1, -1, -1, 4, 2},
645 { 7, -1, -1, -1, -1, -1, 7, -1},
646 { 4, 4, -1, -1, -1, -1, 5, 6},
647 { 6, 4, 7, 7, 5, 6, 4, -1},
648 {-1, 7, 6, 4, 6, 4, 7, -1},
649 {-1, 0, -1, 7, -1, 7, -1, -1},
650 {-1, -1, -1, -1, -1, -1, -1, -1},
651 {-1, -1, -1, -1, -1, -1, -1, -1}},
652 {{-1, 5, -1, -1, -1, -1, 4, -1},
653 {-1, 5, -1, -1, -1, 4, -1, -1},
654 {-1, -1, 5, 6, 6, 4, -1, -1},
655 {-1, -1, 2, -1, 2, -1, -1, -1},
656 { 0, 0, 6, -1, -1, 6, 1, 1},
657 {-1, -1, 2, -1, 2, -1, -1, -1},
658 {-1, -1, 7, 6, 6, 3, -1, -1},
659 {-1, 7, -1, -1, -1, 3, -1, -1},
660 {-1, 7, -1, -1, -1, -1, 3, -1},
661 {-1, -1, -1, -1, -1, -1, -1, -1}},
662 {{-1, 6, -1, -1, -1, -1, 2, -1},
663 { 1, 7, 1, 1, 1, 3, 1, -1},
664 {-1, -1, 4, 1, 1, 4, -1, -1},
665 {-1, 1, 3, 1, 7, 1, -1, -1},
666 {-1, -1, -1, 2, 6, -1, -1, -1},
667 {-1, -1, 1, 5, 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 {-1, -1, -1, -1, -1, -1, -1, -1}},
672 {{ 7, 7, 7, 7, 7, 7, 7, 7},
673 { 7, -1, -1, -1, -1, -1, 7, -1},
674 { 7, -1, -1, 2, 0, 5, 2, 2},
675 { 7, -1, -1, -1, 0, 3, 6, -1},
676 { 7, -1, -1, -1, -1, -1, 4, 0},
677 { 5, 5, -1, -1, -1, -1, -1, -1},
678 { 4, 3, 6, 2, -1, -1, -1, -1},
679 { 0, 2, 0, 4, -1, -1, -1, -1},
680 {-1, -1, -1, -1, -1, -1, -1, -1},
681 {-1, -1, -1, -1, -1, -1, -1, -1}},
682 {{-1, -1, 1, -1, -1, 1, -1, -1},
683 {-1, 4, -1, -1, 5, -1, -1, -1},
684 {-1, 7, -1, -1, 1, 1, 1, -1},
685 { 6, -1, -1, -1, -1, 7, -1, -1},
686 { 1, 1, 1, 1, -1, 4, -1, -1},
687 {-1, -1, 5, -1, -1, -1, -1, -1},
688 {-1, -1, 0, -1, -1, -1, -1, -1},
689 {-1, 3, -1, -1, -1, -1, -1, -1},
690 {-1, 1, -1, -1, -1, -1, -1, -1},
691 {-1, -1, -1, -1, -1, -1, -1, -1}},
692 {{-1, 7, 7, -1, -1, 7, 7, -1},
693 { 6, -1, 4, -1, 4, -1, 6, -1},
694 { 5, -1, -1, 3, 3, -1, -1, 5},
695 { 6, -1, -1, -1, -1, -1, 6, -1},
696 {-1, 7, -1, -1, -1, -1, 7, -1},
697 {-1, 4, -1, -1, -1, 4, -1, -1},
698 {-1, -1, 3, -1, -1, 3, -1, -1},
699 {-1, -1, 2, -1, 2, -1, -1, -1},
700 {-1, -1, -1, 5, 5, -1, -1, -1},
701 {-1, -1, -1, -1, -1, -1, -1, -1}},
702 {{-1, 0, 0, -1, -1, 0, 0, -1},
703 { 7, 4, 6, 6, 6, 4, 3, -1},
704 { 5, 6, 6, 6, 2, 6, 6, 3},
705 { 7, 4, 6, 6, 6, 4, 3, -1},
706 {-1, 0, 0, -1, -1, 0, 0, -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, -1, -1, -1}},
712 {{-1, -1, -1, -1, -1, 7, 7, 7},
713 {-1, -1, -1, -1, 2, 7, 7, -1},
714 {-1, 0, 7, 7, 7, -1, 7, 7},
715 { 6, 7, 7, 7, -1, -1, -1, -1},
716 { 6, -1, -1, -1, 7, 7, 7, 7},
717 { 6, -1, -1, -1, -1, -1, -1, -1},
718 { 4, 2, 2, 2, 4, -1, 3, -1},
719 { 4, 4, 4, 4, 3, 3, 3, -1},
720 {-1, -1, -1, -1, -1, -1, -1, -1},
721 {-1, -1, -1, -1, -1, -1, -1, -1}},
722 {{ 4, -1, -1, 7, -1, 6, -1, 7},
723 { 7, 6, 7, -1, -1, 7, 4, -1},
724 {-1, -1, 7, -1, -1, 7, -1, -1},
725 {-1, 0, 0, 0, 0, 0, 3, -1},
726 {-1, -1, 0, 2, 2, 0, 6, 4},
727 {-1, -1, 0, 0, 0, 1, 3, -1},
728 {-1, -1, -1, 0, 0, -1, 3, 4},
729 {-1, -1, -1, 6, -1, 5, 6, -1},
730 {-1, -1, -1, -1, -1, -1, 1, 0},
731 {-1, -1, -1, -1, -1, -1, -1, -1}},
732 {{-1, 5, -1, -1, -1, -1, 5, -1},
733 { 0, -1, -1, 0, -1, -1, 0, -1},
734 { 0, 0, 0, 2, 2, 0, 0, 0},
735 { 0, -1, -1, 0, -1, -1, 0, -1},
736 {-1, 7, -1, 3, -1, -1, 7, -1},
737 {-1, -1, 3, 6, -1, -1, -1, -1},
738 {-1, -1, -1, 6, -1, -1, -1, -1},
739 {-1, 3, 6, -1, -1, -1, -1, -1},
740 {-1, 3, -1, -1, -1, -1, -1, -1},
741 {-1, -1, -1, -1, -1, -1, -1, -1}},
742 {{-1, -1, -1, 6, 5, -1, -1, -1},
743 {-1, -1, 2, 6, 3, -1, -1, -1},
744 {-1, -1, 5, 4, 7, 1, -1, -1},
745 {-1, 6, 2, 2, 3, 4, -1, -1},
746 {-1, -1, 3, 7, 3, 6, -1, -1},
747 {-1, -1, 1, 3, 2, -1, -1, -1},
748 {-1, -1, -1, 4, 5, -1, -1, -1},
749 {-1, -1, -1, 4, -1, -1, -1, -1},
750 {-1, -1, -1, -1, -1, -1, -1, -1},
751 {-1, -1, -1, -1, -1, -1, -1, -1}},
752 {{ 7, 7, -1, 2, 2, -1, 6, 6},
753 { 6, -1, -1, 6, -1, -1, 3, -1},
754 { 2, -1, -1, 1, -1, -1, 2, -1},
755 { 5, -1, -1, 3, -1, -1, 2, -1},
756 { 1, -1, -1, 2, -1, -1, 1, -1},
757 { 5, -1, -1, 2, -1, -1, 2, -1},
758 { 6, -1, -1, 1, -1, -1, 7, -1},
759 { 5, -1, -1, 5, -1, -1, 4, -1},
760 {-1, -1, -1, -1, -1, -1, -1, -1},
761 {-1, -1, -1, -1, -1, -1, -1, -1}},
762 {{-1, -1, -1, 6, 6, -1, -1, -1},
763 {-1, 0, 4, 4, 4, 0, -1, -1},
764 {-1, -1, -1, 6, 6, -1, -1, -1},
765 {-1, -1, 2, 7, 2, -1, -1, -1},
766 {-1, -1, -1, 6, 6, -1, -1, -1},
767 {-1, 0, 5, 5, 5, 0, -1, -1},
768 {-1, -1, -1, 3, 3, -1, -1, -1},
769 {-1, -1, -1, -1, -1, -1, -1, -1},
770 {-1, -1, -1, -1, -1, -1, -1, -1},
771 {-1, -1, -1, -1, -1, -1, -1, -1}},
772 {{-1, -1, 4, 1, 3, -1, -1, -1},
773 {-1, 1, -1, -1, 1, -1, -1, -1},
774 {-1, -1, 4, 1, 3, 4, 1, -1},
775 {-1, 1, 3, 4, -1, -1, 4, -1},
776 {-1, 3, -1, -1, 3, 4, 1, -1},
777 {-1, 1, 3, 4, 1, 3, -1, -1},
778 {-1, -1, 4, 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, -1, -1, -1, -1, -1, -1, -1}},
782 {{-1, 6, 4, -1, 3, 2, 5, -1},
783 { 0, -1, -1, -1, -1, -1, 1, -1},
784 {-1, 2, 3, 5, -1, 4, 6, -1},
785 { 0, -1, -1, -1, -1, -1, 1, -1},
786 {-1, 4, 6, -1, 2, 5, 3, -1},
787 { 0, -1, -1, -1, -1, -1, 1, -1},
788 {-1, 5, 2, 3, -1, 4, 6, -1},
789 {-1, -1, -1, -1, -1, -1, -1, -1},
790 {-1, -1, -1, -1, -1, -1, -1, -1},
791 {-1, -1, -1, -1, -1, -1, -1, -1}},
792 {{-1, -1, -1, 6, 6, -1, -1, -1},
793 {-1, -1, 7, 6, 4, -1, -1, -1},
794 {-1, 2, 1, 7, 4, 1, 3, -1},
795 { 2, 1, 1, 1, 1, 1, 3, -1},
796 {-1, 2, 2, 2, 3, 3, 3, -1},
797 {-1, -1, -1, 5, -1, -1, -1, -1},
798 {-1, -1, -1, 2, 3, -1, -1, -1},
799 {-1, -1, -1, 5, -1, -1, -1, -1},
800 {-1, -1, 2, 2, 3, 3, -1, -1},
801 {-1, -1, -1, -1, -1, -1, -1, -1}},
802 {{ 4, -1, 5, -1, -1, 3, -1, 6},
803 { 2, -1, 3, -1, 2, -1, 4, -1},
804 { 4, -1, -1, 1, 0, -1, -1, 6},
805 { 6, -1, 2, 3, 5, -1, 4, -1},
806 { 4, -1, -1, 0, 1, -1, -1, 6},
807 { 2, -1, 5, -1, 3, -1, 4, -1},
808 { 4, -1, 3, -1, -1, 2, -1, 6},
809 { 6, -1, -1, -1, -1, -1, 4, -1},
810 {-1, -1, -1, -1, -1, -1, -1, -1},
811 {-1, -1, -1, -1, -1, -1, -1, -1}},
812 {{ 2, 6, 0, 5, 5, 1, 3, 4},
813 { 1, -1, -1, 2, -1, -1, 0, -1},
814 { 4, -1, -1, 3, 6, -1, -1, 2},
815 {-1, -1, -1, 0, -1, -1, -1, -1},
816 {-1, -1, -1, 1, 4, -1, -1, -1},
817 {-1, -1, -1, 2, -1, -1, -1, -1},
818 {-1, -1, -1, 6, 3, -1, -1, -1},
819 {-1, -1, -1, 5, -1, -1, -1, -1},
820 {-1, -1, -1, 4, 1, -1, -1, -1},
821 {-1, -1, -1, -1, -1, -1, -1, -1}},
822 {{-1, -1, -1, -1, 5, 1, 1, 3},
823 { 0, 5, 1, 0, 5, 3, 3, -1},
824 { 5, 1, 0, 5, 1, 0, 5, 1},
825 { 0, 5, 1, 0, 5, 1, 6, -1},
826 {-1, -1, -1, -1, 1, 6, 5, 1},
827 {-1, -1, -1, -1, 5, 1, 6, -1},
828 {-1, -1, -1, -1, 1, 0, 5, 1},
829 {-1, -1, -1, -1, 5, 1, 0, -1},
830 {-1, -1, -1, -1, -1, -1, -1, -1},
831 {-1, -1, -1, -1, -1, -1, -1, -1}},
832 {{-1, 0, 7, 3, -1, -1, 2, 2},
833 {-1, 0, 7, 3, -1, -1, 2, -1},
834 {-1, 0, 7, 3, -1, -1, 2, 2},
835 {-1, 0, 7, 3, -1, 3, 1, -1},
836 {-1, 0, 7, 3, -1, 6, 4, 5},
837 {-1, 0, 7, 3, -1, 7, 0, -1},
838 {-1, 0, 7, 3, -1, 2, 3, 4},
839 {-1, 0, 7, 3, -1, 5, 6, -1},
840 {-1, -1, -1, -1, -1, 7, 0, 1},
841 {-1, -1, -1, -1, -1, -1, -1, -1}},
842 {{-1, -1, -1, 7, 7, 7, 7, -1},
843 { 3, 4, 5, -1, -1, -1, 7, -1},
844 { 2, -1, -1, -1, -1, -1, -1, 3},
845 { 7, -1, -1, -1, -1, -1, 4, -1},
846 { 7, -1, -1, -1, 3, 4, 5, 6},
847 { 7, -1, -1, 2, 0, 1, 2, -1},
848 { 6, -1, -1, -1, 3, 4, 5, 6},
849 { 0, 1, -1, -1, -1, -1, -1, -1},
850 { 2, 3, 4, -1, -1, -1, -1, -1},
851 { 5, 6, 0, -1, -1, -1, -1, -1}},
852 {{-1, 7, -1, -1, -1, -1, 2, -1},
853 { 1, 1, -1, -1, -1, 3, 3, -1},
854 {-1, 2, -1, -1, -1, -1, 4, -1},
855 { 3, 3, -1, -1, -1, 5, 5, -1},
856 {-1, 4, -1, -1, -1, -1, 6, -1},
857 { 5, 5, -1, -1, -1, 1, 1, -1},
858 {-1, 6, -1, -1, -1, -1, 7, -1},
859 {-1, -1, -1, -1, -1, -1, -1, -1},
860 {-1, -1, -1, -1, -1, -1, -1, -1},
861 {-1, -1, -1, -1, -1, -1, -1, -1}},
862 {{-1, 4, -1, -1, -1, -1, 4, -1},
863 { 2, -1, -1, 1, -1, -1, 2, -1},
864 { 5, -1, -1, 0, 0, -1, -1, 5},
865 { 5, -1, -1, 1, -1, -1, 6, -1},
866 {-1, 4, 2, 7, 7, 5, 4, -1},
867 {-1, -1, -1, 6, -1, -1, -1, -1},
868 {-1, -1, -1, 3, 3, -1, -1, -1},
869 {-1, -1, -1, 7, -1, -1, -1, -1},
870 {-1, -1, -1, -1, -1, -1, -1, -1},
871 {-1, -1, -1, -1, -1, -1, -1, -1}},
872 {{-1, 1, -1, -1, 2, 3, 4, -1},
873 { 2, -1, -1, 3, 0, 4, -1, -1},
874 { 4, -1, -1, 2, 3, 1, -1, -1},
875 { 3, -1, 4, 3, 0, -1, -1, -1},
876 { 4, -1, -1, 2, 5, 1, -1, -1},
877 { 3, -1, 4, 5, 0, 4, -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 {-1, -1, -1, -1, -1, -1, -1, -1}},
882 {{ 2, -1, -1, 1, 1, -1, -1, 2},
883 { 2, -1, 3, 3, 3, -1, 2, -1},
884 {-1, 2, -1, 4, 4, -1, 2, -1},
885 {-1, 7, 7, 0, 7, 7, -1, -1},
886 {-1, -1, -1, 4, 4, -1, -1, -1},
887 {-1, -1, 5, 7, 5, -1, -1, -1},
888 { 6, 3, 2, 6, 4, 2, 3, 6},
889 { 5, -1, -1, -1, -1, -1, 1, -1},
890 {-1, -1, -1, -1, -1, -1, -1, -1},
891 {-1, -1, -1, -1, -1, -1, -1, -1}},
892 {{ 4, 2, 3, 5, 7, 1, 3, 6},
893 { 1, -1, -1, 1, -1, -1, 1, -1},
894 { 3, 0, 1, 3, 2, 4, 3, 5},
895 { 4, -1, -1, 4, -1, -1, 4, -1},
896 {-1, 5, -1, -1, 5, -1, -1, 5},
897 { 0, 3, 2, 0, 4, 5, 0, -1},
898 {-1, 6, -1, -1, 6, -1, -1, 6},
899 { 7, -1, -1, 7, -1, -1, 7, -1},
900 {-1, -1, -1, -1, -1, -1, -1, -1},
901 {-1, -1, -1, -1, -1, -1, -1, -1}},
902 {{-1, 5, 4, -1, 1, 1, -1, -1},
903 { 5, -1, 4, 1, -1, 1, -1, -1},
904 { 0, -1, -1, -1, -1, -1, 0, -1},
905 { 0, 6, 4, -1, -1, 4, 2, -1},
906 {-1, 4, 3, 5, 2, 6, 3, 6},
907 {-1, 2, 6, -1, -1, 5, 4, -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, -1, -1, -1, -1, -1}},
912 {{-1, -1, -1, 6, 6, -1, -1, -1},
913 {-1, -1, 5, 5, 4, -1, -1, -1},
914 {-1, -1, 1, 6, 6, 4, -1, -1},
915 {-1, 1, 7, 2, 5, 3, -1, -1},
916 {-1, 2, 7, 2, 1, 5, 3, -1},
917 { 2, 1, 3, 1, 4, 2, 7, -1},
918 {-1, 3, 1, 3, 4, 2, 7, -1},
919 {-1, 3, 5, 5, 6, 6, -1, -1},
920 {-1, -1, -1, -1, -1, -1, -1, -1},
921 {-1, -1, -1, -1, -1, -1, -1, -1}},
922 {{-1, -1, 7, 3, -1, -1, -1, -1},
923 {-1, 1, 7, 6, -1, -1, -1, -1},
924 {-1, 3, 7, 5, 1, 5, -1, -1},
925 { 7, 7, 0, 2, 4, 0, 4, -1},
926 { 7, 1, 4, 6, 5, 6, 5, 7},
927 { 1, 7, 7, 1, 7, 7, 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, -1, 1, -1, -1, 1, -1, -1},
933 {-1, 5, 6, 1, 5, 6, -1, -1},
934 {-1, 1, 1, 2, 2, 1, 1, -1},
935 { 4, 7, 1, 0, 1, 7, 4, -1},
936 {-1, 3, 7, 5, 7, 5, 3, -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 {-1, -1, -1, -1, -1, -1, -1, -1}},
942 {{ 4, -1, -1, -1, 5, -1, -1, 4},
943 { 6, 6, 7, 6, -1, 4, 5, -1},
944 { 4, 2, 7, 5, 2, 2, 6, 4},
945 {-1, -1, 4, 1, -1, 5, 2, -1},
946 {-1, 5, 2, 7, 7, -1, 7, 4},
947 { 4, 6, 5, 4, -1, 4, 2, -1},
948 {-1, -1, -1, 4, -1, 4, 1, -1},
949 { 0, 0, 0, 5, -1, -1, -1, -1},
950 {-1, -1, -1, -1, 0, 0, 0, 0},
951 {-1, -1, -1, -1, -1, -1, -1, -1}},
952 {{ 1, -1, -1, -1, 0, 0, -1, -1},
953 { 2, -1, -1, 0, 1, 0, -1, -1},
954 { 3, -1, -1, 0, 2, 2, 0, -1},
955 { 4, -1, 0, 1, 1, 1, 0, -1},
956 { 5, -1, -1, 0, 4, 4, 0, -1},
957 { 6, -1, -1, 4, 4, 4, -1, -1},
958 { 7, -1, -1, -1, 4, 4, -1, -1},
959 {-1, -1, -1, 0, 1, 0, -1, -1},
960 {-1, -1, -1, 0, 1, 1, 0, -1},
961 {-1, -1, -1, -1, -1, -1, -1, -1}},
962 {{-1, -1, 3, -1, -1, 1, 7, -1},
963 {-1, 7, 4, -1, -1, 4, 3, -1},
964 { 1, -1, -1, 0, 2, 0, -1, -1},
965 { 5, 4, -1, 3, -1, -1, -1, -1},
966 { 4, -1, 3, 6, 1, 1, 6, -1},
967 {-1, 1, -1, -1, 4, -1, 1, -1},
968 {-1, 7, 5, -1, -1, -1, 3, -1},
969 {-1, -1, 3, -1, -1, -1, -1, -1},
970 {-1, -1, -1, -1, -1, -1, -1, -1},
971 {-1, -1, -1, -1, -1, -1, -1, -1}},
972 {{ 1, -1, -1, -1, 1, -1, -1, -1},
973 { 2, -1, -1, -1, 2, -1, -1, -1},
974 {-1, 3, -1, -1, 3, 3, -1, -1},
975 {-1, 4, -1, 4, -1, 4, -1, -1},
976 {-1, 5, -1, -1, 5, 5, -1, -1},
977 { 6, -1, -1, 7, 1, 7, -1, -1},
978 { 7, -1, -1, -1, 6, 6, -1, -1},
979 {-1, -1, -1, -1, -1, -1, -1, -1},
980 {-1, -1, -1, -1, -1, -1, -1, -1},
981 {-1, -1, -1, -1, -1, -1, -1, -1}},
982 {{ 2, -1, -1, 6, -1, 2, 5, 1},
983 { 5, -1, 4, -1, 4, -1, 4, -1},
984 { 6, -1, -1, 3, -1, -1, -1, 3},
985 { 4, 2, 0, -1, -1, -1, 5, -1},
986 {-1, -1, -1, 6, -1, 3, 6, -1},
987 {-1, -1, 5, -1, 5, -1, -1, -1},
988 {-1, -1, -1, 3, -1, 4, 2, 5},
989 {-1, -1, -1, -1, -1, -1, -1, -1},
990 {-1, -1, -1, -1, -1, -1, -1, -1},
991 {-1, -1, -1, -1, -1, -1, -1, -1}},
992 {{ 6, -1, -1, -1, 4, -1, -1, 3},
993 { 0, 3, -1, -1, 6, -1, 0, -1},
994 {-1, -1, 7, -1, 1, -1, 3, -1},
995 { 7, -1, 4, 7, -1, 2, -1, -1},
996 { 5, 2, 3, 2, 1, 6, -1, 3},
997 {-1, -1, 0, 4, 3, 5, 4, -1},
998 {-1, 7, 6, -1, -1, 0, -1, -1},
999 { 4, 3, -1, -1, -1, 4, 2, -1},
1000 { 0, -1, -1, -1, -1, -1, 6, -1},
1001 {-1, -1, -1, -1, -1, -1, -1, -1}},
1002 {{ 6, 1, 2, 5, 1, 6, 3, 0},
1003 {-1, -1, -1, -1, -1, -1, 4, -1},
1004 { 0, 5, 2, 7, 1, 6, 2, -1},
1005 { 3, -1, -1, -1, -1, -1, -1, -1},
1006 { 6, 7, 6, 4, 0, 5, 2, 6},
1007 {-1, -1, -1, -1, -1, -1, 1, -1},
1008 { 6, 1, 4, 0, 6, 2, 3, -1},
1009 { 0, -1, -1, -1, -1, -1, -1, -1},
1010 {-1, 0, 4, 5, 3, 7, 6, 0},
1011 {-1, -1, -1, -1, -1, -1, -1, -1}},
1012 {{-1, -1, -1, 0, 1, -1, -1, -1},
1013 {-1, -1, 0, 7, 0, -1, -1, -1},
1014 {-1, -1, 1, 2, 2, 0, -1, -1},
1015 {-1, 0, 7, 0, 7, 0, -1, -1},
1016 {-1, 6, -1, 7, 7, -1, 6, -1},
1017 { 4, 1, 6, 6, 6, 4, 1, -1},
1018 {-1, 5, -1, 7, 7, -1, 5, -1},
1019 {-1, -1, -1, -1, -1, -1, -1, -1},
1020 {-1, -1, -1, -1, -1, -1, -1, -1},
1021 {-1, -1, -1, -1, -1, -1, -1, -1}},
1022 {{-1, -1, -1, 5, 6, -1, -1, -1},
1023 {-1, -1, 3, 3, 3, -1, -1, -1},
1024 {-1, -1, 7, 5, 3, 7, -1, -1},
1025 {-1, 3, -1, 6, -1, 3, -1, -1},
1026 { 2, -1, -1, 3, 7, -1, -1, 1},
1027 { 2, 2, -1, 3, -1, 1, 1, -1},
1028 {-1, 0, 2, 5, 6, 1, 0, -1},
1029 {-1, -1, -1, 3, -1, -1, -1, -1},
1030 {-1, -1, -1, 3, 7, -1, -1, -1},
1031 {-1, -1, -1, -1, -1, -1, -1, -1}},
1032 {{-1, 6, -1, -1, -1, -1, 2, -1},
1033 {-1, 2, 6, 0, 6, 0, -1, -1},
1034 {-1, 0, -1, -1, -1, -1, -1, -1},
1035 { 6, -1, -1, -1, -1, -1, -1, -1},
1036 {-1, 3, 3, 2, 0, 6, 0, 0},
1037 {-1, 6, -1, -1, -1, -1, 0, -1},
1038 {-1, -1, -1, 6, 0, 2, 6, -1},
1039 {-1, 2, 0, -1, -1, -1, -1, -1},
1040 {-1, -1, -1, -1, -1, -1, -1, -1},
1041 {-1, -1, -1, -1, -1, -1, -1, -1}},
1042 {{ 0, 7, -1, -1, -1, -1, -1, -1},
1043 { 1, 5, -1, -1, -1, -1, -1, -1},
1044 { 7, 2, 5, -1, -1, -1, -1, -1},
1045 { 6, 3, 4, -1, -1, -1, -1, -1},
1046 { 5, 5, 4, 4, -1, -1, -1, -1},
1047 { 3, 3, 5, 3, -1, -1, -1, -1},
1048 { 1, 2, 2, 5, 3, -1, -1, -1},
1049 { 1, 0, 0, 7, 6, -1, -1, -1},
1050 { 3, 3, 5, 5, 7, 6, -1, -1},
1051 {-1, -1, -1, -1, -1, -1, -1, -1}},
1052 {{-1, -1, 2, 6, 6, 2, -1, -1},
1053 {-1, 2, 1, 1, 0, 2, -1, -1},
1054 {-1, 2, 3, 2, 2, 0, 2, -1},
1055 { 2, 3, 2, 5, 2, 7, 2, -1},
1056 { 2, 4, 2, 5, 2, 7, 2, 0},
1057 { 2, 4, 2, 6, 6, 2, 0, -1},
1058 {-1, 2, 5, 2, 2, 2, 7, 2},
1059 {-1, 2, 5, 6, 6, 7, 2, -1},
1060 {-1, -1, 2, 2, 2, 2, 2, -1},
1061 {-1, -1, -1, -1, -1, -1, -1, -1}},
1062 {{-1, -1, 0, -1, -1, 0, -1, -1},
1063 { 1, 0, 0, 1, 0, 0, 1, -1},
1064 { 1, 7, 7, 5, 5, 7, 7, 1},
1065 { 3, 2, -1, 2, -1, 2, 3, -1},
1066 { 3, 7, -1, 6, 6, -1, 7, 3},
1067 { 7, -1, -1, 6, -1, -1, 7, -1},
1068 { 4, 4, 5, -1, -1, 5, 4, 4},
1069 {-1, -1, -1, -1, -1, -1, -1, -1},
1070 {-1, -1, -1, -1, -1, -1, -1, -1},
1071 {-1, -1, -1, -1, -1, -1, -1, -1}},
1072 {{-1, 6, 3, -1, -1, 3, 6, -1},
1073 { 6, -1, 2, -1, 2, -1, 6, -1},
1074 { 2, -1, 0, 1, 1, 0, -1, 2},
1075 { 5, 0, -1, 7, -1, 0, 5, -1},
1076 {-1, 5, -1, 6, 6, -1, 5, -1},
1077 { 7, 1, 4, -1, 4, 1, 7, -1},
1078 { 7, -1, 4, -1, -1, 4, -1, 7},
1079 { 2, 0, -1, -1, -1, 0, 2, -1},
1080 {-1, 2, -1, -1, -1, -1, 2, -1},
1081 {-1, -1, -1, -1, -1, -1, -1, -1}},
1082 {{ 6, 1, -1, -1, -1, -1, 4, 0},
1083 { 2, 7, 5, 5, 5, 7, 3, -1},
1084 { 6, 1, -1, -1, -1, -1, 4, 0},
1085 { 2, 5, 7, 7, 7, 5, 3, -1},
1086 { 6, 1, -1, -1, -1, -1, 4, 0},
1087 { 2, 0, 6, 6, 6, 0, 3, -1},
1088 { 6, 1, -1, -1, -1, -1, 4, 0},
1089 {-1, -1, -1, -1, -1, -1, -1, -1},
1090 {-1, -1, -1, -1, -1, -1, -1, -1},
1091 {-1, -1, -1, -1, -1, -1, -1, -1}},
1092 {{ 5, -1, -1, 1, 1, -1, -1, 5},
1093 { 5, -1, 4, -1, 4, -1, 5, -1},
1094 {-1, 2, 4, -1, -1, 4, 2, -1},
1095 { 7, 2, -1, -1, -1, 2, 7, -1},
1096 { 0, -1, 0, 4, 4, 0, -1, 0},
1097 { 7, 2, -1, -1, -1, 2, 7, -1},
1098 {-1, 2, 3, -1, -1, 3, 2, -1},
1099 { 5, -1, 3, -1, 3, -1, 5, -1},
1100 { 5, -1, -1, 6, 6, -1, -1, 5},
1101 {-1, -1, -1, -1, -1, -1, -1, -1}},
1102 {{ 2, 2, -1, -1, -1, -1, 5, 5},
1103 { 5, -1, -1, -1, -1, -1, 2, -1},
1104 { 5, -1, -1, -1, -1, -1, -1, 2},
1105 { 1, -1, 1, 5, 1, -1, 3, -1},
1106 { 5, 2, 5, 3, 1, 2, 5, 2},
1107 { 2, 0, 5, -1, 2, 0, 5, -1},
1108 {-1, 3, 7, -1, -1, 3, 7, -1},
1109 {-1, -1, 2, 0, 5, -1, -1, -1},
1110 {-1, -1, -1, -1, -1, -1, -1, -1},
1111 {-1, -1, -1, -1, -1, -1, -1, -1}},
1112 {{ 0, 6, 5, 2, 3, 4, 1, 7},
1113 {-1, -1, -1, -1, 1, -1, -1, -1},
1114 {-1, -1, -1, 1, 1, -1, -1, -1},
1115 {-1, -1, 1, -1, -1, -1, -1, -1},
1116 { 7, 1, 4, 3, 2, 5, 6, 0},
1117 {-1, -1, -1, -1, 1, -1, -1, -1},
1118 {-1, -1, -1, 1, 1, -1, -1, -1},
1119 {-1, -1, 1, -1, -1, -1, -1, -1},
1120 { 0, 6, 5, 2, 3, 4, 1, 7},
1121 {-1, -1, -1, -1, -1, -1, -1, -1}},
1122 {{-1, -1, 1, -1, -1, 1, -1, -1},
1123 {-1, 2, 4, -1, 2, 4, -1, -1},
1124 {-1, 2, 3, 6, 5, 3, 2, -1},
1125 {-1, 6, 5, -1, 6, 5, -1, -1},
1126 {-1, -1, -1, 7, 7, -1, -1, -1},
1127 {-1, -1, -1, 7, -1, -1, -1, -1},
1128 { 1, -1, -1, 7, 7, -1, -1, 3},
1129 { 2, -1, -1, 7, -1, -1, 2, -1},
1130 {-1, 3, 4, 5, 6, 4, 1, -1},
1131 {-1, -1, -1, -1, -1, -1, -1, -1}},
1132 {{ 1, -1, -1, 2, 2, -1, -1, 2},
1133 { 1, 3, 7, 3, 7, 4, 2, -1},
1134 {-1, 1, 6, -1, -1, 6, 2, -1},
1135 { 6, -1, 7, 3, 7, -1, 6, -1},
1136 {-1, 4, 2, -1, -1, 1, 3, -1},
1137 {-1, -1, 2, 6, 1, -1, -1, -1},
1138 {-1, 4, 3, 3, 4, 4, 3, -1},
1139 {-1, -1, -1, -1, -1, -1, -1, -1},
1140 {-1, -1, -1, -1, -1, -1, -1, -1},
1141 {-1, -1, -1, -1, -1, -1, -1, -1}},
1142 {{-1, -1, -1, 5, 6, -1, -1, -1},
1143 {-1, -1, -1, 3, -1, -1, -1, -1},
1144 {-1, -1, -1, 1, 2, -1, -1, -1},
1145 {-1, -1, -1, 4, -1, -1, -1, -1},
1146 {-1, -1, -1, 5, 7, -1, -1, -1},
1147 {-1, -1, -1, 2, -1, -1, -1, -1},
1148 { 6, 5, 4, 3, 2, 1, 7, 5},
1149 {-1, -1, -1, -1, -1, -1, -1, -1},
1150 {-1, -1, -1, -1, -1, -1, -1, -1},
1151 {-1, -1, -1, -1, -1, -1, -1, -1}},
1152 {{-1, 0, -1, 1, -1, 2, -1, -1},
1153 {-1, 4, -1, 5, -1, 6, -1, -1},
1154 {-1, 7, -1, 0, -1, 2, -1, -1},
1155 {-1, 6, -1, 3, -1, 6, -1, -1},
1156 {-1, 1, -1, 1, -1, 2, -1, -1},
1157 {-1, 3, -1, 5, -1, 0, -1, -1},
1158 {-1, 2, -1, 4, -1, 6, -1, -1},
1159 {-1, 3, -1, 6, -1, 7, -1, -1},
1160 {-1, -1, -1, -1, -1, -1, -1, -1},
1161 {-1, -1, -1, -1, -1, -1, -1, -1}},
1162 {{ 1, 1, 2, 2, 3, 3, 4, 4},
1163 { 5, 5, 6, 7, 6, 5, 5, -1},
1164 { 6, 4, 3, 3, 2, 2, 1, 6},
1165 { 4, 6, 5, 7, 6, 3, 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 {-1, -1, -1, -1, -1, -1, -1, -1}},
1172 {{ 7, 4, -1, 1, 2, -1, 4, 7},
1173 { 5, 5, -1, 2, -1, 4, 4, -1},
1174 {-1, 5, -1, 7, 7, -1, 4, -1},
1175 { 1, 0, 6, 7, 6, 0, 2, -1},
1176 {-1, 2, -1, 5, 3, -1, 1, -1},
1177 { 1, 1, -1, -1, -1, 2, 2, -1},
1178 { 6, 1, 4, -1, -1, 4, 2, 6},
1179 { 5, 3, -1, -1, -1, 3, 5, -1},
1180 {-1, -1, -1, -1, -1, -1, -1, -1},
1181 {-1, -1, -1, -1, -1, -1, -1, -1}},
1182 {{ 1, 5, 1, 0, 0, 1, 5, 1},
1183 { 1, 2, 5, -1, 5, 2, 1, -1},
1184 { 3, 6, 1, 2, 2, 1, 6, 3},
1185 { 4, 3, 4, -1, 4, 3, 4, -1},
1186 { 3, 4, 6, 5, 5, 6, 4, 3},
1187 { 0, 2, 3, -1, 3, 2, 0, -1},
1188 { 2, 3, 1, 5, 5, 1, 3, 2},
1189 {-1, -1, -1, -1, -1, -1, -1, -1},
1190 {-1, -1, -1, -1, -1, -1, -1, -1},
1191 {-1, -1, -1, -1, -1, -1, -1, -1}},
1192 {{ 3, 0, 2, 7, 5, 7, 6, 5},
1193 { 6, -1, 1, -1, 2, -1, 1, -1},
1194 {-1, 6, 4, 0, 3, 4, 5, -1},
1195 {-1, 5, -1, 1, -1, 4, -1, -1},
1196 {-1, 7, 3, 5, 6, 5, 3, -1},
1197 { 1, -1, 2, -1, 4, -1, 2, -1},
1198 { 6, 4, 4, 6, 6, 5, 5, 1},
1199 {-1, -1, -1, -1, -1, -1, -1, -1},
1200 {-1, -1, -1, -1, -1, -1, -1, -1},
1201 {-1, -1, -1, -1, -1, -1, -1, -1}}
1204 /* the tile struct
1205 * type is the bubble number 0-7
1206 * fallx is the x axis movement for the falling bubble
1207 * fallvel is the initial upward velocity for the falling bubble
1208 * ingroup denotes a bubble that is part of a group to be removed
1209 * anchored denotes a bubble that is anchored to the ceiling
1211 struct tile {
1212 int type;
1213 int fallx;
1214 int fallvel;
1215 bool ingroup;
1216 bool anchored;
1217 bool delete;
1220 /* the highscore struct
1221 * level is the highscore level
1222 * score is the highscore score
1224 struct highscore {
1225 unsigned int level;
1226 unsigned int score;
1229 /* the game context struct
1230 * score is the current score
1231 * level is the current level
1232 * highlevel is the highest level beaten
1233 * highscores is the list of high scores
1234 * angle is the current cannon direction
1235 * shots is the number of shots fired since last compression
1236 * compress is the height of the compressor
1237 * onboardcnt is the number of unique bubbles on the playing board
1238 * onboard is the unique bubbles on the playing board
1239 * nextinq is the pointer to the next bubble in the firing queue
1240 * queue is the circular buffer of bubbles to be fired
1241 * elapsedlvl is level elapsed time in 1/100s of seconds
1242 * elapsedshot is the shot elapsed time in 1/100s of seconds
1243 * startedshot is when the current shot began
1244 * resume denotes whether to resume the currently loaded game
1245 * dirty denotes whether the high scores are out of sync with the saved file
1246 * playboard is the game playing board
1248 struct game_context {
1249 unsigned int score;
1250 unsigned int level;
1251 unsigned int highlevel;
1252 struct highscore highscores[NUM_SCORES];
1253 int angle;
1254 int shots;
1255 int compress;
1256 int onboardcnt;
1257 int onboard[NUM_BUBBLES];
1258 int nextinq;
1259 int queue[NUM_QUEUE];
1260 long elapsedlvl;
1261 long elapsedshot;
1262 long startedshot;
1263 bool resume;
1264 bool dirty;
1265 struct tile playboard[BB_HEIGHT][BB_WIDTH];
1269 * Precalculated sine and cosine * 16384 (fixed point 18.14)
1270 * Borrowed from cube.c plugin
1272 static const short sin_table[91] = {
1273 0, 285, 571, 857, 1142, 1427, 1712, 1996, 2280, 2563,
1274 2845, 3126, 3406, 3685, 3963, 4240, 4516, 4790, 5062, 5334,
1275 5603, 5871, 6137, 6401, 6663, 6924, 7182, 7438, 7691, 7943,
1276 8191, 8438, 8682, 8923, 9161, 9397, 9630, 9860, 10086, 10310,
1277 10531, 10748, 10963, 11173, 11381, 11585, 11785, 11982, 12175, 12365,
1278 12550, 12732, 12910, 13084, 13254, 13420, 13582, 13740, 13894, 14043,
1279 14188, 14329, 14466, 14598, 14725, 14848, 14967, 15081, 15190, 15295,
1280 15395, 15491, 15582, 15668, 15749, 15825, 15897, 15964, 16025, 16082,
1281 16135, 16182, 16224, 16261, 16294, 16321, 16344, 16361, 16374, 16381,
1282 16384
1285 static long sin(int val) {
1286 val = (val+360)%360;
1288 if(val < 181) {
1289 if(val < 91) {
1290 /* phase 0-90 degree */
1291 return (long)sin_table[val];
1292 } else {
1293 /* phase 91-180 degree */
1294 return (long)sin_table[180-val];
1296 } else {
1297 if(val < 271) {
1298 /* phase 181-270 degree */
1299 return -(long)sin_table[val-180];
1300 } else {
1301 /* phase 270-359 degree */
1302 return -(long)sin_table[360-val];
1305 return 0;
1308 static long cos(int val) {
1309 val = (val+360)%360;
1311 if(val < 181) {
1312 if(val < 91) {
1313 /* phase 0-90 degree */
1314 return (long)sin_table[90-val];
1315 } else {
1316 /* phase 91-180 degree */
1317 return -(long)sin_table[val-90];
1319 } else {
1320 if(val < 271) {
1321 /* phase 181-270 degree */
1322 return -(long)sin_table[270-val];
1323 } else {
1324 /* phase 270-359 degree */
1325 return (long)sin_table[val-270];
1328 return 0;
1333 static void bubbles_init(struct game_context* bb);
1334 static bool bubbles_nextlevel(struct game_context* bb);
1335 static void bubbles_getonboard(struct game_context* bb);
1336 static void bubbles_drawboard(struct game_context* bb);
1337 static int bubbles_fire(struct game_context* bb);
1338 static bool bubbles_collision(struct game_context* bb, int y, int x,
1339 int nearrow, int nearcol);
1340 static bool bubbles_ingroup(struct game_context* bb, int row, int col);
1341 static int bubbles_searchgroup(struct game_context* bb, int row, int col);
1342 static int bubbles_remove(struct game_context* bb);
1343 static void bubbles_anchored(struct game_context* bb, int row, int col);
1344 static int bubbles_fall(struct game_context* bb);
1345 static int bubbles_checklevel(struct game_context* bb);
1346 static int bubbles_recordscore(struct game_context* bb);
1347 static void bubbles_savescores(struct game_context* bb);
1348 static bool bubbles_loadgame(struct game_context* bb);
1349 static void bubbles_savegame(struct game_context* bb);
1350 static void bubbles_setcolors(void);
1351 static void bubbles_callback(void* param);
1352 static int bubbles_handlebuttons(struct game_context* bb, bool animblock,
1353 int timeout);
1354 static int bubbles(struct game_context* bb);
1356 /*****************************************************************************
1357 * bubbles_init() initializes bubbles data structures.
1358 ******************************************************************************/
1359 static void bubbles_init(struct game_context* bb) {
1360 /* seed the rand generator */
1361 rb->srand(*rb->current_tick);
1363 /* check for resumed game */
1364 if(bb->resume) {
1365 bb->resume = false;
1366 return;
1369 bb->score = 0;
1370 bubbles_nextlevel(bb);
1373 /*****************************************************************************
1374 * bubbles_nextlevel() sets up the game for the next level, returns false if
1375 * there are no more levels.
1376 ******************************************************************************/
1377 static bool bubbles_nextlevel(struct game_context* bb) {
1378 int i, j, pos;
1380 bb->level++;
1382 /* check if there are no more levels */
1383 if(bb->level > NUM_LEVELS) return false;
1385 /* set up the play board */
1386 rb->memset(bb->playboard, 0, sizeof(bb->playboard));
1387 for(i=0; i<BB_LEVEL_HEIGHT; i++) {
1388 for(j=0; j<BB_WIDTH; j++) {
1389 pos = (int)level[bb->level-1][i][j];
1390 if(pos >=0 && pos < NUM_BUBBLES) {
1391 bb->playboard[i][j].type = pos;
1392 } else {
1393 bb->playboard[i][j].type = -1;
1397 for(i=BB_LEVEL_HEIGHT; i<BB_HEIGHT; i++) {
1398 for(j=0; j<BB_WIDTH; j++) {
1399 bb->playboard[i][j].type = -1;
1403 /* fill first bubbles in shot queue */
1404 bubbles_getonboard(bb);
1405 for(i=0; i<NUM_QUEUE; i++) {
1406 bb->queue[i] = bb->onboard[rb->rand()%bb->onboardcnt];
1409 bb->angle = 0;
1410 bb->shots = 0;
1411 bb->compress = 0;
1412 bb->nextinq = 0;
1413 bb->elapsedlvl = 0;
1414 bb->elapsedshot = 0;
1416 return true;
1419 /*****************************************************************************
1420 * bubbles_getonboard() determines which bubble types are on the play board.
1421 ******************************************************************************/
1422 static void bubbles_getonboard(struct game_context* bb) {
1423 int i, j, k;
1424 bool found;
1426 bb->onboardcnt = 0;
1427 rb->memset(bb->onboard, -1, sizeof(bb->onboard));
1429 for(i=0; i<BB_HEIGHT; i++) {
1430 for(j=0; j<BB_WIDTH; j++) {
1431 if(bb->playboard[i][j].type >= 0) {
1432 found = false;
1434 for(k=0; k<bb->onboardcnt; k++) {
1435 if(bb->playboard[i][j].type == bb->onboard[k]) {
1436 found = true;
1437 break;
1441 if(!found) {
1442 bb->onboard[bb->onboardcnt] = bb->playboard[i][j].type;
1443 bb->onboardcnt++;
1446 if(bb->onboardcnt == NUM_BUBBLES) return;
1452 /*****************************************************************************
1453 * bubbles_drawboard() draws the game board to the buffer but does not update
1454 * the lcd.
1455 ******************************************************************************/
1456 static void bubbles_drawboard(struct game_context* bb) {
1457 int i, j;
1458 int w, h;
1459 int colmax, indent;
1460 int tipx, tipy;
1461 bool evenline = false;
1462 char *level = "Level";
1463 char *score = "Score";
1464 char *next = "Next";
1465 char *hurry = "HURRY!";
1466 char str[11];
1468 /* clear screen */
1469 rb->lcd_clear_display();
1471 /* draw sidebars */
1472 #ifdef HAVE_LCD_COLOR
1473 rb->lcd_bitmap(bubbles_left, 0, 0, XOFS, LCD_HEIGHT);
1474 /* skip right border for square screens */
1475 #if (LCD_WIDTH > LCD_HEIGHT)
1476 rb->lcd_bitmap(bubbles_right, XOFS-1+BB_WIDTH*BUBBLE_WIDTH, 0,
1477 LCD_WIDTH-(XOFS-1+BB_WIDTH*BUBBLE_WIDTH), LCD_HEIGHT);
1478 #endif
1479 #endif
1481 /* display play board */
1482 for(i=0; i<BB_HEIGHT; i++) {
1483 colmax = BB_WIDTH;
1484 if(evenline) {
1485 colmax--;
1486 indent = ROW_INDENT;
1487 } else {
1488 indent = 0;
1490 evenline = !evenline;
1492 for(j=0; j<colmax; j++) {
1493 if(bb->playboard[i][j].type >= 0 && !bb->playboard[i][j].delete) {
1494 rb->lcd_bitmap_part(bubbles_emblem,
1495 0, EMBLEM_HEIGHT*bb->playboard[i][j].type, EMBLEM_WIDTH,
1496 XOFS+indent+BUBBLE_WIDTH*j+(BUBBLE_WIDTH-EMBLEM_WIDTH)/2,
1497 ROW_HEIGHT*i+(BUBBLE_HEIGHT-EMBLEM_HEIGHT)/2+bb->compress*ROW_HEIGHT,
1498 EMBLEM_WIDTH, EMBLEM_HEIGHT);
1499 rb->lcd_set_drawmode(DRMODE_FG);
1500 rb->lcd_mono_bitmap((const unsigned char *)bubbles_bubble,
1501 XOFS+indent+BUBBLE_WIDTH*j,
1502 ROW_HEIGHT*i+bb->compress*ROW_HEIGHT,
1503 BUBBLE_WIDTH, BUBBLE_HEIGHT);
1504 rb->lcd_set_drawmode(DRMODE_SOLID);
1509 /* display bubble to be shot */
1510 rb->lcd_bitmap_part(bubbles_emblem,
1511 0, EMBLEM_HEIGHT*bb->queue[bb->nextinq], EMBLEM_WIDTH,
1512 SHOTX+(BUBBLE_WIDTH-EMBLEM_WIDTH)/2,
1513 SHOTY+(BUBBLE_HEIGHT-EMBLEM_HEIGHT)/2,
1514 EMBLEM_WIDTH, EMBLEM_HEIGHT);
1515 rb->lcd_set_drawmode(DRMODE_FG);
1516 rb->lcd_mono_bitmap((const unsigned char *)bubbles_bubble,
1517 SHOTX, SHOTY,
1518 BUBBLE_WIDTH, BUBBLE_HEIGHT);
1519 rb->lcd_set_drawmode(DRMODE_SOLID);
1521 /* display next bubble to be shot */
1522 rb->lcd_bitmap_part(bubbles_emblem,
1523 0, EMBLEM_HEIGHT*bb->queue[(bb->nextinq+1)%NUM_QUEUE], EMBLEM_WIDTH,
1524 XOFS/2-BUBBLE_WIDTH/2+(BUBBLE_WIDTH-EMBLEM_WIDTH)/2,
1525 SHOTY+(BUBBLE_HEIGHT-EMBLEM_HEIGHT)/2,
1526 EMBLEM_WIDTH, EMBLEM_HEIGHT);
1527 rb->lcd_set_drawmode(DRMODE_FG);
1528 rb->lcd_mono_bitmap((const unsigned char *)bubbles_bubble,
1529 XOFS/2-BUBBLE_WIDTH/2, SHOTY,
1530 BUBBLE_WIDTH, BUBBLE_HEIGHT);
1531 rb->lcd_set_drawmode(DRMODE_SOLID);
1533 /* draw bounding lines */
1534 #ifndef HAVE_LCD_COLOR
1535 rb->lcd_vline(XOFS-1, 0, LCD_HEIGHT);
1536 rb->lcd_vline(XOFS+BUBBLE_WIDTH*BB_WIDTH, 0, LCD_HEIGHT);
1537 #endif
1538 rb->lcd_hline(XOFS, XOFS+BUBBLE_WIDTH*BB_WIDTH-1, bb->compress*ROW_HEIGHT-1);
1539 rb->lcd_hline(XOFS, XOFS+BUBBLE_WIDTH*BB_WIDTH-1,
1540 ROW_HEIGHT*(BB_HEIGHT-2)+BUBBLE_HEIGHT);
1542 /* draw arrow */
1543 tipx = SHOTX+BUBBLE_WIDTH/2+(((sin(bb->angle)>>4)*BUBBLE_WIDTH*3/2)>>10);
1544 tipy = SHOTY+BUBBLE_HEIGHT/2-(((cos(bb->angle)>>4)*BUBBLE_HEIGHT*3/2)>>10);
1546 rb->lcd_drawline(SHOTX+BUBBLE_WIDTH/2+(((sin(bb->angle)>>4)*BUBBLE_WIDTH/2)>>10),
1547 SHOTY+BUBBLE_HEIGHT/2-(((cos(bb->angle)>>4)*BUBBLE_HEIGHT/2)>>10),
1548 tipx, tipy);
1549 xlcd_filltriangle(tipx, tipy,
1550 tipx+(((sin(bb->angle-135)>>4)*BUBBLE_WIDTH/3)>>10),
1551 tipy-(((cos(bb->angle-135)>>4)*BUBBLE_HEIGHT/3)>>10),
1552 tipx+(((sin(bb->angle+135)>>4)*BUBBLE_WIDTH/3)>>10),
1553 tipy-(((cos(bb->angle+135)>>4)*BUBBLE_HEIGHT/3)>>10));
1555 /* draw text */
1556 rb->lcd_getstringsize(level, &w, &h);
1557 rb->lcd_putsxy(XOFS/2-w/2, 2, level);
1559 rb->snprintf(str, 4, "%d", bb->level);
1560 rb->lcd_getstringsize(str, &w, &h);
1561 rb->lcd_putsxy(XOFS/2-w/2, 11, str);
1563 rb->lcd_getstringsize(score, &w, &h);
1564 rb->lcd_putsxy(XOFS/2-w/2, 29, score);
1566 rb->snprintf(str, 10, "%d", bb->score);
1567 rb->lcd_getstringsize(str, &w, &h);
1568 rb->lcd_putsxy(XOFS/2-w/2, 38, str);
1570 rb->lcd_getstringsize(next, &w, &h);
1571 rb->lcd_putsxy(XOFS/2-w/2, SHOTY-9, next);
1573 if(bb->elapsedshot >= (MAX_SHOTTIME*7)/10) {
1574 rb->lcd_getstringsize(hurry, &w, &h);
1575 rb->lcd_putsxy(LCD_WIDTH/2-w/2, LCD_HEIGHT/2-h/2, hurry);
1579 /*****************************************************************************
1580 * bubbles_fire() fires the current bubble, reloads the cannon, attaches
1581 * bubble to playboard, removes appropriate bubbles, and advances the
1582 * the compressor.
1583 ******************************************************************************/
1584 static int bubbles_fire(struct game_context* bb) {
1585 int bubblecur;
1586 long shotxinc, shotyinc;
1587 long shotxofs, shotyofs;
1588 int shotxdirec = 1;
1589 long tempxofs, tempyofs;
1590 int nearrow, nearcol;
1591 int lastrow = BB_HEIGHT-1;
1592 int lastcol = (BB_WIDTH-1)/2;
1593 int buttonres;
1594 long lasttick, currenttick;
1596 /* get current bubble */
1597 bubblecur = bb->queue[bb->nextinq];
1598 shotxinc = ((sin(bb->angle)>>4)*BUBBLE_WIDTH)/3;
1599 shotyinc = ((-1*(cos(bb->angle)>>4))*BUBBLE_HEIGHT)/3;
1600 shotxofs = shotyofs = 0;
1602 /* advance the queue */
1603 bb->queue[bb->nextinq] = bb->onboard[rb->rand()%bb->onboardcnt];
1604 bb->nextinq = (bb->nextinq+1)%NUM_QUEUE;
1605 bubbles_drawboard(bb);
1606 rb->lcd_update_rect(0, 0, XOFS, LCD_HEIGHT);
1608 /* move the bubble across the play board */
1609 lasttick = *rb->current_tick;
1611 while(true) {
1612 /* move the bubble one step */
1613 shotyofs += shotyinc;
1614 shotxofs += shotxinc*shotxdirec;
1616 /* check for bounce off sides */
1617 if(SHOTX+(shotxofs>>10) < XOFS) {
1618 shotxofs += 2*((XOFS<<10)-(((SHOTX)<<10)+shotxofs));
1619 shotxdirec *= -1;
1620 } else if(SHOTX+(shotxofs>>10) > XOFS+(BB_WIDTH-1)*BUBBLE_WIDTH) {
1621 shotxofs -= 2*((((SHOTX)<<10)+shotxofs)-
1622 ((XOFS<<10)+(((BB_WIDTH-1)*BUBBLE_WIDTH)<<10)));
1623 shotxdirec *= -1;
1626 tempxofs = shotxofs>>10;
1627 tempyofs = shotyofs>>10;
1629 /* display shot */
1630 bubbles_drawboard(bb);
1631 rb->lcd_bitmap_part(bubbles_emblem, 0, EMBLEM_HEIGHT*bubblecur, EMBLEM_WIDTH,
1632 SHOTX+tempxofs+(BUBBLE_WIDTH-EMBLEM_WIDTH)/2,
1633 SHOTY+tempyofs+(BUBBLE_HEIGHT-EMBLEM_HEIGHT)/2,
1634 EMBLEM_WIDTH, EMBLEM_HEIGHT);
1635 rb->lcd_set_drawmode(DRMODE_FG);
1636 rb->lcd_mono_bitmap((const unsigned char *)bubbles_bubble,
1637 SHOTX+tempxofs, SHOTY+tempyofs,
1638 BUBBLE_WIDTH, BUBBLE_HEIGHT);
1639 rb->lcd_set_drawmode(DRMODE_SOLID);
1640 rb->lcd_update_rect(XOFS, 0, BB_WIDTH*BUBBLE_WIDTH, LCD_HEIGHT);
1642 /* find nearest position */
1643 nearrow = ((SHOTY+tempyofs)-
1644 (bb->compress*ROW_HEIGHT)+
1645 (ROW_HEIGHT/2))/ROW_HEIGHT;
1646 if(nearrow >= BB_HEIGHT) nearrow = BB_HEIGHT-1;
1648 if(nearrow%2) { /* odd row */
1649 nearcol = ((SHOTX+tempxofs)-
1650 (XOFS+ROW_INDENT)+
1651 (BUBBLE_WIDTH/2))/BUBBLE_WIDTH;
1652 if(nearcol >= BB_WIDTH-1) nearcol = BB_WIDTH-2;
1653 } else { /* even row */
1654 nearcol = ((SHOTX+tempxofs)-XOFS+(BUBBLE_WIDTH/2))/BUBBLE_WIDTH;
1655 if(nearcol >= BB_WIDTH) nearcol = BB_WIDTH-1;
1657 if(nearcol < 0) nearcol = 0;
1659 /* if nearest position is occupied attach to last position */
1660 if(bb->playboard[nearrow][nearcol].type >= 0) {
1661 bb->playboard[lastrow][lastcol].type = bubblecur;
1662 break;
1665 /* save last position */
1666 lastrow = nearrow;
1667 lastcol = nearcol;
1669 /* if collision with neighbor then attach shot */
1670 if(bubbles_collision(bb, SHOTY+tempyofs, SHOTX+tempxofs,
1671 nearrow, nearcol)) {
1672 bb->playboard[nearrow][nearcol].type = bubblecur;
1673 break;
1676 /* if at top then attach shot to the ceiling */
1677 if(nearrow == 0 && SHOTY+tempyofs <= bb->compress*ROW_HEIGHT) {
1678 bb->playboard[nearrow][nearcol].type = bubblecur;
1679 break;
1682 /* handle button events */
1683 buttonres = bubbles_handlebuttons(bb, true, 0);
1684 if(buttonres != BB_NONE) return buttonres;
1686 /* framerate limiting */
1687 currenttick = *rb->current_tick;
1688 if(currenttick-lasttick < HZ/MAX_FPS) {
1689 rb->sleep((HZ/MAX_FPS)-(currenttick-lasttick));
1690 } else {
1691 rb->yield();
1693 lasttick = currenttick;
1696 bubbles_drawboard(bb);
1697 rb->lcd_update();
1699 /* clear appropriate bubbles from playing board */
1700 if(bubbles_ingroup(bb, lastrow, lastcol)) {
1701 buttonres = bubbles_remove(bb);
1702 if(buttonres != BB_NONE) return buttonres;
1705 /* update shots and compress amount */
1706 bb->shots++;
1707 if(bb->shots >= NUM_COMPRESS) {
1708 bb->shots = 0;
1709 bb->compress++;
1712 return BB_NONE;
1715 /*****************************************************************************
1716 * bubbles_collision() determines if a fired bubble has collided with another
1717 * bubble.
1718 ******************************************************************************/
1719 static bool bubbles_collision(struct game_context* bb, int y, int x,
1720 int nearrow, int nearcol) {
1721 int nx, ny;
1722 int adj = nearrow%2;
1724 /* check neighbors */
1725 if(nearcol-1 >= 0) {
1726 if(bb->playboard[nearrow][nearcol-1].type >= 0) {
1727 nx = XOFS+(nearrow%2 ? ROW_INDENT : 0)+BUBBLE_WIDTH*(nearcol-1);
1728 ny = ROW_HEIGHT*nearrow+bb->compress*ROW_HEIGHT;
1729 if((x-nx)*(x-nx)+(y-ny)*(y-ny) < MIN_DISTANCE) return true;
1733 if(nearcol-1+adj >= 0) {
1734 if(nearrow-1 >= 0) {
1735 if(bb->playboard[nearrow-1][nearcol-1+adj].type >= 0) {
1736 nx = XOFS+((nearrow-1)%2 ? ROW_INDENT : 0)+
1737 BUBBLE_WIDTH*(nearcol-1+adj);
1738 ny = ROW_HEIGHT*(nearrow-1)+bb->compress*ROW_HEIGHT;
1739 if((x-nx)*(x-nx)+(y-ny)*(y-ny) < MIN_DISTANCE) return true;
1743 if(nearrow+1 < BB_HEIGHT) {
1744 if(bb->playboard[nearrow+1][nearcol-1+adj].type >= 0) {
1745 nx = XOFS+((nearrow+1)%2 ? ROW_INDENT : 0)+
1746 BUBBLE_WIDTH*(nearcol-1+adj);
1747 ny = ROW_HEIGHT*(nearrow+1)+bb->compress*ROW_HEIGHT;
1748 if((x-nx)*(x-nx)+(y-ny)*(y-ny) < MIN_DISTANCE) return true;
1753 if(nearcol+adj >= 0) {
1754 if(nearrow-1 >= 0) {
1755 if(bb->playboard[nearrow-1][nearcol+adj].type >= 0) {
1756 nx = XOFS+((nearrow-1)%2 ? ROW_INDENT : 0)+
1757 BUBBLE_WIDTH*(nearcol+adj);
1758 ny = ROW_HEIGHT*(nearrow-1)+bb->compress*ROW_HEIGHT;
1759 if((x-nx)*(x-nx)+(y-ny)*(y-ny) < MIN_DISTANCE) return true;
1763 if(nearrow+1 < BB_HEIGHT) {
1764 if(bb->playboard[nearrow+1][nearcol+adj].type >= 0) {
1765 nx = XOFS+((nearrow+1)%2 ? ROW_INDENT : 0)+
1766 BUBBLE_WIDTH*(nearcol+adj);
1767 ny = ROW_HEIGHT*(nearrow+1)+bb->compress*ROW_HEIGHT;
1768 if((x-nx)*(x-nx)+(y-ny)*(y-ny) < MIN_DISTANCE) return true;
1773 if(nearcol+1 < BB_WIDTH-adj) {
1774 if(bb->playboard[nearrow][nearcol+1].type >= 0) {
1775 nx = XOFS+(nearrow%2 ? ROW_INDENT : 0)+BUBBLE_WIDTH*(nearcol+1);
1776 ny = ROW_HEIGHT*nearrow+bb->compress*ROW_HEIGHT;
1777 if((x-nx)*(x-nx)+(y-ny)*(y-ny) < MIN_DISTANCE) return true;
1781 return false;
1784 /*****************************************************************************
1785 * bubbles_ingroup() marks all bubbles that form the current group.
1786 ******************************************************************************/
1787 static bool bubbles_ingroup(struct game_context* bb, int row, int col) {
1788 int i, j;
1789 int count;
1791 count = bubbles_searchgroup(bb, row, col);
1793 /* unmark group if too small */
1794 if(count < 3) {
1795 for(i=0; i<BB_HEIGHT; i++) {
1796 for(j=0; j<BB_WIDTH; j++) {
1797 bb->playboard[i][j].ingroup = false;
1801 return false;
1804 return true;
1807 /*****************************************************************************
1808 * bubbles_searchgroup() return the size of the group of bubbles of the same
1809 * type that the current bubble belongs to.
1810 ******************************************************************************/
1811 static int bubbles_searchgroup(struct game_context* bb, int row, int col) {
1812 int i, adj;
1813 int myrow, mycol, mytype;
1814 int count = 0;
1816 struct coord {
1817 int row;
1818 int col;
1819 } search[(2*BB_WIDTH-1)*(BB_HEIGHT/2)];
1821 /* search initial bubble */
1822 bb->playboard[row][col].ingroup = true;
1823 search[count].row = row;
1824 search[count].col = col;
1825 count++;
1827 /* breadth-first search neighbors */
1828 for(i=0; i<count; i++) {
1829 myrow = search[i].row;
1830 mycol = search[i].col;
1831 mytype = bb->playboard[myrow][mycol].type;
1832 adj = myrow%2;
1834 if(mycol-1 >= 0) {
1835 if(bb->playboard[myrow][mycol-1].type == mytype &&
1836 !bb->playboard[myrow][mycol-1].ingroup) {
1837 bb->playboard[myrow][mycol-1].ingroup = true;
1838 search[count].row = myrow;
1839 search[count].col = mycol-1;
1840 count++;
1844 if(mycol-1+adj >= 0) {
1845 if(myrow-1 >= 0) {
1846 if(bb->playboard[myrow-1][mycol-1+adj].type == mytype &&
1847 !bb->playboard[myrow-1][mycol-1+adj].ingroup) {
1848 bb->playboard[myrow-1][mycol-1+adj].ingroup = true;
1849 search[count].row = myrow-1;
1850 search[count].col = mycol-1+adj;
1851 count++;
1855 if(myrow+1 < BB_HEIGHT) {
1856 if(bb->playboard[myrow+1][mycol-1+adj].type == mytype &&
1857 !bb->playboard[myrow+1][mycol-1+adj].ingroup) {
1858 bb->playboard[myrow+1][mycol-1+adj].ingroup = true;
1859 search[count].row = myrow+1;
1860 search[count].col = mycol-1+adj;
1861 count++;
1866 if(mycol+adj >= 0) {
1867 if(myrow-1 >= 0) {
1868 if(bb->playboard[myrow-1][mycol+adj].type == mytype &&
1869 !bb->playboard[myrow-1][mycol+adj].ingroup) {
1870 bb->playboard[myrow-1][mycol+adj].ingroup = true;
1871 search[count].row = myrow-1;
1872 search[count].col = mycol+adj;
1873 count++;
1877 if(myrow+1 < BB_HEIGHT) {
1878 if(bb->playboard[myrow+1][mycol+adj].type == mytype &&
1879 !bb->playboard[myrow+1][mycol+adj].ingroup) {
1880 bb->playboard[myrow+1][mycol+adj].ingroup = true;
1881 search[count].row = myrow+1;
1882 search[count].col = mycol+adj;
1883 count++;
1888 if(mycol+1 < BB_WIDTH-adj) {
1889 if(bb->playboard[myrow][mycol+1].type == mytype &&
1890 !bb->playboard[myrow][mycol+1].ingroup) {
1891 bb->playboard[myrow][mycol+1].ingroup = true;
1892 search[count].row = myrow;
1893 search[count].col = mycol+1;
1894 count++;
1899 return count;
1902 /*****************************************************************************
1903 * bubbles_remove() removes all bubbles in the current group and all
1904 * unanchored bubbles from the play board.
1905 ******************************************************************************/
1906 static int bubbles_remove(struct game_context* bb) {
1907 int i, j;
1908 int buttonres;
1910 /* determine all anchored bubbles */
1911 for(j=0; j<BB_WIDTH; j++) {
1912 if(bb->playboard[0][j].type >= 0 && !bb->playboard[0][j].ingroup) {
1913 bubbles_anchored(bb, 0, j);
1917 /* mark bubbles to be deleted */
1918 for(i=0; i<BB_HEIGHT; i++) {
1919 for(j=0; j<BB_WIDTH; j++) {
1920 if(bb->playboard[i][j].type >= 0 &&
1921 (!bb->playboard[i][j].anchored || bb->playboard[i][j].ingroup)) {
1922 bb->playboard[i][j].delete = true;
1927 /* animate falling bubbles */
1928 buttonres = bubbles_fall(bb);
1929 if(buttonres != BB_NONE) return buttonres;
1931 /* remove bubbles */
1932 for(i=0; i<BB_HEIGHT; i++) {
1933 for(j=0; j<BB_WIDTH; j++) {
1934 if(bb->playboard[i][j].delete) {
1935 bb->playboard[i][j].ingroup = false;
1936 bb->playboard[i][j].type = -1;
1937 bb->playboard[i][j].delete = false;
1938 } else {
1939 bb->playboard[i][j].anchored = false;
1944 bubbles_getonboard(bb);
1946 return BB_NONE;
1949 /*****************************************************************************
1950 * bubbles_anchored() marks all bubbles that are anchored in some way to the
1951 * current bubble.
1952 ******************************************************************************/
1953 static void bubbles_anchored(struct game_context* bb, int row, int col) {
1954 int i, adj;
1955 int myrow, mycol, mytype;
1956 int count = 0;
1958 struct coord {
1959 int row;
1960 int col;
1961 } search[(2*BB_WIDTH-1)*(BB_HEIGHT/2)];
1963 /* search initial bubble */
1964 bb->playboard[row][col].anchored = true;
1965 search[count].row = row;
1966 search[count].col = col;
1967 count++;
1969 /* breadth-first search neighbors */
1970 for(i=0; i<count; i++) {
1971 myrow = search[i].row;
1972 mycol = search[i].col;
1973 mytype = bb->playboard[myrow][mycol].type;
1974 adj = myrow%2;
1976 if(mycol-1 >= 0) {
1977 if(bb->playboard[myrow][mycol-1].type >= 0 &&
1978 !bb->playboard[myrow][mycol-1].ingroup &&
1979 !bb->playboard[myrow][mycol-1].anchored) {
1980 bb->playboard[myrow][mycol-1].anchored = true;
1981 search[count].row = myrow;
1982 search[count].col = mycol-1;
1983 count++;
1987 if(mycol-1+adj >= 0) {
1988 if(myrow-1 >= 0) {
1989 if(bb->playboard[myrow-1][mycol-1+adj].type >= 0 &&
1990 !bb->playboard[myrow-1][mycol-1+adj].ingroup &&
1991 !bb->playboard[myrow-1][mycol-1+adj].anchored) {
1992 bb->playboard[myrow-1][mycol-1+adj].anchored = true;
1993 search[count].row = myrow-1;
1994 search[count].col = mycol-1+adj;
1995 count++;
1999 if(myrow+1 < BB_HEIGHT) {
2000 if(bb->playboard[myrow+1][mycol-1+adj].type >= 0 &&
2001 !bb->playboard[myrow+1][mycol-1+adj].ingroup &&
2002 !bb->playboard[myrow+1][mycol-1+adj].anchored) {
2003 bb->playboard[myrow+1][mycol-1+adj].anchored = true;
2004 search[count].row = myrow+1;
2005 search[count].col = mycol-1+adj;
2006 count++;
2011 if(mycol+adj >= 0) {
2012 if(myrow-1 >= 0) {
2013 if(bb->playboard[myrow-1][mycol+adj].type >= 0 &&
2014 !bb->playboard[myrow-1][mycol+adj].ingroup &&
2015 !bb->playboard[myrow-1][mycol+adj].anchored) {
2016 bb->playboard[myrow-1][mycol+adj].anchored = true;
2017 search[count].row = myrow-1;
2018 search[count].col = mycol+adj;
2019 count++;
2023 if(myrow+1 < BB_HEIGHT) {
2024 if(bb->playboard[myrow+1][mycol+adj].type >= 0 &&
2025 !bb->playboard[myrow+1][mycol+adj].ingroup &&
2026 !bb->playboard[myrow+1][mycol+adj].anchored) {
2027 bb->playboard[myrow+1][mycol+adj].anchored = true;
2028 search[count].row = myrow+1;
2029 search[count].col = mycol+adj;
2030 count++;
2035 if(mycol+1 < BB_WIDTH-adj) {
2036 if(bb->playboard[myrow][mycol+1].type >= 0 &&
2037 !bb->playboard[myrow][mycol+1].ingroup &&
2038 !bb->playboard[myrow][mycol+1].anchored) {
2039 bb->playboard[myrow][mycol+1].anchored = true;
2040 search[count].row = myrow;
2041 search[count].col = mycol+1;
2042 count++;
2048 /*****************************************************************************
2049 * bubbles_fall() makes removed bubbles fall from the screen.
2050 ******************************************************************************/
2051 static int bubbles_fall(struct game_context* bb) {
2052 int i, j;
2053 int count;
2054 int indent;
2055 int xofs, yofs;
2056 int buttonres;
2057 bool onscreen;
2058 long lasttick, currenttick;
2060 /* give all falling bubbles an x axis movement */
2061 for(i=0; i<BB_HEIGHT; i++) {
2062 for(j=0; j<BB_WIDTH; j++) {
2063 if(bb->playboard[i][j].delete) {
2064 bb->playboard[i][j].fallx = rb->rand()%25 - 12;
2065 bb->playboard[i][j].fallvel = rb->rand()%5 + 6;
2070 /* draw bubbles falling off the screen
2071 * follows y=x^2-8x scaled to bubble size
2073 lasttick = *rb->current_tick;
2075 for(count=1; ;count++) {
2076 onscreen = false;
2077 bubbles_drawboard(bb);
2079 for(i=0; i<BB_HEIGHT; i++) {
2080 for(j=0; j<BB_WIDTH; j++) {
2081 if(bb->playboard[i][j].delete) {
2082 indent = (i%2 ? ROW_INDENT : 0);
2083 xofs = ((bb->playboard[i][j].fallx*count)*BUBBLE_WIDTH)/48;
2084 yofs = ((count*count - bb->playboard[i][j].fallvel*count)*
2085 BUBBLE_HEIGHT)/20;
2087 /* draw bubble if it is still on the screen */
2088 if(ROW_HEIGHT*i+bb->compress*ROW_HEIGHT+yofs
2089 <= LCD_HEIGHT) {
2090 onscreen = true;
2092 rb->lcd_bitmap_part(bubbles_emblem, 0,
2093 EMBLEM_HEIGHT*bb->playboard[i][j].type, EMBLEM_WIDTH,
2094 XOFS+indent+BUBBLE_WIDTH*j+
2095 (BUBBLE_WIDTH-EMBLEM_WIDTH)/2+xofs,
2096 ROW_HEIGHT*i+(BUBBLE_HEIGHT-EMBLEM_HEIGHT)/2+
2097 bb->compress*ROW_HEIGHT+yofs,
2098 EMBLEM_WIDTH, EMBLEM_HEIGHT);
2099 rb->lcd_set_drawmode(DRMODE_FG);
2100 rb->lcd_mono_bitmap(
2101 (const unsigned char *)bubbles_bubble,
2102 XOFS+indent+BUBBLE_WIDTH*j+xofs,
2103 ROW_HEIGHT*i+bb->compress*ROW_HEIGHT+yofs,
2104 BUBBLE_WIDTH, BUBBLE_HEIGHT);
2105 rb->lcd_set_drawmode(DRMODE_SOLID);
2111 rb->lcd_update();
2113 /* break out if all bubbles are off the screen */
2114 if(!onscreen) break;
2116 /* handle button events */
2117 buttonres = bubbles_handlebuttons(bb, true, 0);
2118 if(buttonres != BB_NONE) return buttonres;
2120 /* framerate limiting */
2121 currenttick = *rb->current_tick;
2122 if(currenttick-lasttick < HZ/MAX_FPS) {
2123 rb->sleep((HZ/MAX_FPS)-(currenttick-lasttick));
2124 } else {
2125 rb->yield();
2127 lasttick = currenttick;
2130 return BB_NONE;
2133 /*****************************************************************************
2134 * bubbles_checklevel() checks the state of the playboard for a win or loss.
2135 ******************************************************************************/
2136 static int bubbles_checklevel(struct game_context* bb) {
2137 int i, j;
2138 int points;
2139 char str[13];
2141 bubbles_drawboard(bb);
2142 rb->lcd_update();
2144 /* check for bubbles below cut off point */
2145 for(i=0; i<=bb->compress; i++) {
2146 for(j=0; j<BB_WIDTH; j++) {
2147 if(bb->playboard[BB_HEIGHT-1-i][j].type >= 0) return BB_LOSE;
2151 /* check for bubbles above cut off point */
2152 for(i=0; i<BB_HEIGHT-1-bb->compress; i++) {
2153 for(j=0; j<BB_WIDTH; j++) {
2154 if(bb->playboard[i][j].type >= 0) return BB_NONE;
2158 /* level complete, record score */
2159 points = 100 - bb->elapsedlvl/100;
2160 if(points > 0) {
2161 bb->score += points;
2162 } else {
2163 points = 0;
2166 rb->snprintf(str, 12, "%d points", points);
2167 rb->splash(HZ, str);
2169 /* advance to the next level */
2170 if(!bubbles_nextlevel(bb)) {
2171 return BB_WIN;
2174 bubbles_drawboard(bb);
2175 rb->lcd_update();
2176 rb->snprintf(str, 12, "Level %d", bb->level);
2177 rb->splash(HZ, str);
2178 bubbles_drawboard(bb);
2179 rb->lcd_update();
2181 return BB_NONE;
2184 /*****************************************************************************
2185 * bubbles_recordscore() inserts a high score into the high scores list and
2186 * returns the high score position.
2187 ******************************************************************************/
2188 static int bubbles_recordscore(struct game_context* bb) {
2189 int i;
2190 int position = 0;
2191 unsigned int currentscore, currentlevel;
2192 unsigned int tempscore, templevel;
2194 if(bb->score > 0) {
2195 currentlevel = bb->level-1;
2196 currentscore = bb->score;
2198 for(i=0; i<NUM_SCORES; i++) {
2199 if(currentscore >= bb->highscores[i].score) {
2200 if(!position) {
2201 position = i+1;
2202 bb->dirty = true;
2204 templevel = bb->highscores[i].level;
2205 tempscore = bb->highscores[i].score;
2206 bb->highscores[i].level = currentlevel;
2207 bb->highscores[i].score = currentscore;
2208 currentlevel = templevel;
2209 currentscore = tempscore;
2214 return position;
2217 /*****************************************************************************
2218 * bubbles_loadscores() loads the high scores saved file.
2219 ******************************************************************************/
2220 static void bubbles_loadscores(struct game_context* bb) {
2221 int fd;
2223 bb->dirty = false;
2225 /* clear high scores */
2226 bb->highlevel = 0;
2227 rb->memset(bb->highscores, 0, sizeof(bb->highscores));
2229 /* open scores file */
2230 fd = rb->open(SCORE_FILE, O_RDONLY);
2231 if(fd < 0) return;
2233 /* read in high scores */
2234 rb->read(fd, &bb->highlevel, sizeof(bb->highlevel));
2235 if(rb->read(fd, bb->highscores, sizeof(bb->highscores)) <= 0) {
2236 /* scores are bad, reset */
2237 rb->memset(bb->highscores, 0, sizeof(bb->highscores));
2240 if( bb->highlevel >= NUM_LEVELS )
2241 bb->highlevel = NUM_LEVELS - 1;
2243 rb->close(fd);
2246 /*****************************************************************************
2247 * bubbles_savescores() saves the high scores saved file.
2248 ******************************************************************************/
2249 static void bubbles_savescores(struct game_context* bb) {
2250 int fd;
2252 /* write out the high scores to the save file */
2253 fd = rb->open(SCORE_FILE, O_WRONLY|O_CREAT);
2254 rb->write(fd, &bb->highlevel, sizeof(bb->highlevel));
2255 rb->write(fd, bb->highscores, sizeof(bb->highscores));
2256 rb->close(fd);
2257 bb->dirty = false;
2260 /*****************************************************************************
2261 * bubbles_loadgame() loads the saved game and returns load success.
2262 ******************************************************************************/
2263 static bool bubbles_loadgame(struct game_context* bb) {
2264 int fd;
2265 bool loaded = false;
2267 /* open game file */
2268 fd = rb->open(SAVE_FILE, O_RDONLY);
2269 if(fd < 0) return loaded;
2271 /* read in saved game */
2272 while(true) {
2273 if(rb->read(fd, &bb->score, sizeof(bb->score)) <= 0) break;
2274 if(rb->read(fd, &bb->level, sizeof(bb->level)) <= 0) break;
2275 if(rb->read(fd, &bb->angle, sizeof(bb->angle)) <= 0) break;
2276 if(rb->read(fd, &bb->shots, sizeof(bb->shots)) <= 0) break;
2277 if(rb->read(fd, &bb->compress, sizeof(bb->compress)) <= 0) break;
2278 if(rb->read(fd, &bb->onboardcnt, sizeof(bb->onboardcnt)) <= 0) break;
2279 if(rb->read(fd, bb->onboard, sizeof(bb->onboard)) <= 0) break;
2280 if(rb->read(fd, &bb->nextinq, sizeof(bb->nextinq)) <= 0) break;
2281 if(rb->read(fd, bb->queue, sizeof(bb->queue)) <= 0) break;
2282 if(rb->read(fd, &bb->elapsedlvl, sizeof(bb->elapsedlvl)) <= 0) break;
2283 if(rb->read(fd, bb->playboard, sizeof(bb->playboard)) <= 0) break;
2284 bb->resume = true;
2285 loaded = true;
2286 break;
2289 rb->close(fd);
2291 /* delete saved file */
2292 rb->remove(SAVE_FILE);
2293 return loaded;
2296 /*****************************************************************************
2297 * bubbles_savegame() saves the current game state.
2298 ******************************************************************************/
2299 static void bubbles_savegame(struct game_context* bb) {
2300 int fd;
2302 /* write out the game state to the save file */
2303 fd = rb->open(SAVE_FILE, O_WRONLY|O_CREAT);
2304 rb->write(fd, &bb->score, sizeof(bb->score));
2305 rb->write(fd, &bb->level, sizeof(bb->level));
2306 rb->write(fd, &bb->angle, sizeof(bb->angle));
2307 rb->write(fd, &bb->shots, sizeof(bb->shots));
2308 rb->write(fd, &bb->compress, sizeof(bb->compress));
2309 rb->write(fd, &bb->onboardcnt, sizeof(bb->onboardcnt));
2310 rb->write(fd, bb->onboard, sizeof(bb->onboard));
2311 rb->write(fd, &bb->nextinq, sizeof(bb->nextinq));
2312 rb->write(fd, bb->queue, sizeof(bb->queue));
2313 rb->write(fd, &bb->elapsedlvl, sizeof(bb->elapsedlvl));
2314 rb->write(fd, bb->playboard, sizeof(bb->playboard));
2315 rb->close(fd);
2317 bb->resume = true;
2320 /*****************************************************************************
2321 * bubbles_setcolors() set the foreground and background colors.
2322 ******************************************************************************/
2323 static inline void bubbles_setcolors(void) {
2324 #ifdef HAVE_LCD_COLOR
2325 rb->lcd_set_background(LCD_RGBPACK(181,181,222));
2326 rb->lcd_set_foreground(LCD_BLACK);
2327 #endif
2330 /*****************************************************************************
2331 * bubbles_callback() is the default event handler callback which is called
2332 * on usb connect and shutdown.
2333 ******************************************************************************/
2334 static void bubbles_callback(void* param) {
2335 struct game_context* bb = (struct game_context*) param;
2336 if(bb->dirty) {
2337 rb->splash(HZ/2, "Saving high scores...");
2338 bubbles_savescores(bb);
2342 /*****************************************************************************
2343 * bubbles_handlebuttons() handles button events during a game.
2344 ******************************************************************************/
2345 static int bubbles_handlebuttons(struct game_context* bb, bool animblock,
2346 int timeout) {
2347 int button;
2348 int buttonres;
2349 long start;
2350 const struct button_mapping *plugin_contexts[]
2351 = {generic_left_right_fire,generic_actions};
2353 if (timeout < 0)
2354 timeout = 0;
2355 button = pluginlib_getaction(rb,timeout,plugin_contexts,2);
2356 #ifdef HAS_BUTTON_HOLD
2357 if (rb->button_hold())
2358 button = BUBBLES_START;
2359 #endif
2361 switch(button){
2362 case BUBBLES_LEFT_REP:
2363 if(bb->angle > MIN_ANGLE) bb->angle -= 4;
2364 case BUBBLES_LEFT: /* change angle to the left */
2365 if(bb->angle > MIN_ANGLE) bb->angle -= 2;
2366 break;
2368 case BUBBLES_RIGHT_REP:
2369 if(bb->angle < MAX_ANGLE) bb->angle += 4;
2370 case BUBBLES_RIGHT: /* change angle to the right */
2371 if(bb->angle < MAX_ANGLE) bb->angle += 2;
2372 break;
2374 case BUBBLES_SELECT: /* fire the shot */
2375 if(!animblock) {
2376 bb->elapsedlvl += bb->elapsedshot;
2377 bb->elapsedshot = 0;
2378 buttonres = bubbles_fire(bb);
2379 if(buttonres != BB_NONE) return buttonres;
2380 buttonres = bubbles_checklevel(bb);
2381 if(buttonres != BB_NONE) return buttonres;
2382 bb->startedshot = *rb->current_tick;
2384 break;
2386 case BUBBLES_START: /* pause the game */
2387 start = *rb->current_tick;
2388 rb->splash(1, "Paused");
2389 while(pluginlib_getaction(rb,TIMEOUT_BLOCK,plugin_contexts,2)
2390 != (BUBBLES_START));
2391 bb->startedshot += *rb->current_tick-start;
2392 bubbles_drawboard(bb);
2393 rb->lcd_update();
2394 break;
2396 case BUBBLES_RESUME: /* save and end the game */
2397 if(!animblock) {
2398 rb->splash(HZ/2, "Saving game...");
2399 bubbles_savegame(bb);
2400 return BB_END;
2402 break;
2403 case BUBBLES_QUIT: /* end the game */
2404 return BB_END;
2406 case ACTION_UNKNOWN:
2407 case ACTION_NONE: /* no button pressed */
2408 break;
2410 default:
2411 if(rb->default_event_handler_ex(button, bubbles_callback,
2412 (void*) bb) == SYS_USB_CONNECTED)
2413 return BB_USB;
2414 break;
2417 return BB_NONE;
2420 /*****************************************************************************
2421 * bubbles() is the main game subroutine, it returns the final game status.
2422 ******************************************************************************/
2423 static int bubbles(struct game_context* bb) {
2424 int i;
2425 int w, h;
2426 int button;
2427 int buttonres;
2428 unsigned int startlevel = 0;
2429 char *title = "Bubbles";
2430 bool startgame = false;
2431 bool showscores = false;
2432 long timeout;
2433 const struct button_mapping *plugin_contexts[]
2434 = {generic_actions,generic_directions};
2436 bubbles_setcolors();
2438 /* don't resume by default */
2439 bb->resume = false;
2441 /********************
2442 * menu *
2443 ********************/
2444 while(!startgame){
2445 char str[30];
2446 rb->lcd_clear_display();
2448 if(!showscores) {
2449 /* welcome screen to display key bindings */
2450 rb->lcd_getstringsize(title, &w, &h);
2451 rb->lcd_putsxy((LCD_WIDTH-w)/2, 0, title);
2452 #if (CONFIG_KEYPAD == IRIVER_H100_PAD) || (CONFIG_KEYPAD == IRIVER_H300_PAD)
2453 rb->lcd_puts(0, 2, "ON to start/pause");
2454 rb->lcd_puts(0, 3, "MODE to save/resume");
2455 rb->lcd_puts(0, 4, "OFF to exit");
2456 rb->lcd_puts(0, 5, "SELECT to fire");
2457 rb->lcd_puts(0, 6, " and show high scores");
2458 rb->lcd_puts(0, 7, "LEFT/RIGHT to aim");
2459 rb->lcd_puts(0, 8, "UP/DOWN to change level");
2460 #elif (CONFIG_KEYPAD == IPOD_3G_PAD) || (CONFIG_KEYPAD == IPOD_4G_PAD)
2461 rb->lcd_puts(0, 2, "PLAY to start/pause");
2462 rb->lcd_puts(0, 3, "MENU to save/resume");
2463 rb->lcd_puts(0, 4, "MENU+SELECT to exit");
2464 rb->lcd_puts(0, 5, "SELECT to fire");
2465 rb->lcd_puts(0, 6, " and show high scores");
2466 rb->lcd_puts(0, 7, "SCROLL to aim");
2467 rb->lcd_puts(0, 8, " and to change level");
2468 #elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
2469 rb->lcd_puts(0, 2, "PLAY to start/pause");
2470 rb->lcd_puts(0, 3, "REC to save/resume");
2471 rb->lcd_puts(0, 4, "POWER to exit");
2472 rb->lcd_puts(0, 5, "SELECT to fire");
2473 rb->lcd_puts(0, 6, " and show high scores");
2474 rb->lcd_puts(0, 7, "LEFT/RIGHT to aim");
2475 rb->lcd_puts(0, 8, "UP/DOWN to change level");
2476 #elif CONFIG_KEYPAD == GIGABEAT_PAD
2477 rb->lcd_puts(0, 2, "POWER to start/pause");
2478 rb->lcd_puts(0, 3, "MENU to save/resume");
2479 rb->lcd_puts(0, 4, "A to exit");
2480 rb->lcd_puts(0, 5, "SELECT to fire");
2481 rb->lcd_puts(0, 6, " and show high scores");
2482 rb->lcd_puts(0, 7, "LEFT/RIGHT to aim");
2483 rb->lcd_puts(0, 8, "UP/DOWN to change level");
2484 #elif CONFIG_KEYPAD == RECORDER_PAD
2485 rb->lcd_puts_scroll(0, 2, "ON to start/pause, "
2486 "F1 to save/resume, "
2487 "OFF to exit, "
2488 "PLAY to fire and show high scores, "
2489 "LEFT/RIGHT to aim, "
2490 "UP/DOWN to change level.");
2491 #elif CONFIG_KEYPAD == ONDIO_PAD
2492 rb->lcd_puts_scroll(0, 2, "MODE to start/pause, "
2493 "DOWN to save/resume, "
2494 "OFF to exit, "
2495 "UP to fire and show high scores, "
2496 "LEFT/RIGHT to aim and to change level.");
2497 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
2498 rb->lcd_puts(0, 2, "PLAY to start/pause");
2499 rb->lcd_puts(0, 3, "FF to save/resume");
2500 rb->lcd_puts(0, 4, "POWER to exit");
2501 rb->lcd_puts(0, 5, "REW/UP to fire");
2502 rb->lcd_puts(0, 6, " and show high scores");
2503 rb->lcd_puts(0, 7, "LEFT/RIGHT to aim");
2504 rb->lcd_puts(0, 8, "UP/DOWN to change level");
2505 #elif CONFIG_KEYPAD == SANSA_E200_PAD
2506 rb->lcd_puts(0, 2, "PLAY to start/pause");
2507 rb->lcd_puts(0, 3, "SUBMENU to save/resume");
2508 rb->lcd_puts(0, 4, "POWER to exit");
2509 rb->lcd_puts(0, 5, "SELECT to fire");
2510 rb->lcd_puts(0, 6, " and show high scores");
2511 rb->lcd_puts(0, 7, "LEFT/RIGHT to aim");
2512 rb->lcd_puts(0, 8, "SCROLL to change level");
2513 #endif
2514 #if LCD_WIDTH >= 138
2515 rb->snprintf(str, 28, "Start on level %d of %d", startlevel+1,
2516 bb->highlevel+1);
2517 #else
2518 rb->snprintf(str, 28, "Start on lvl %d/%d", startlevel+1,
2519 bb->highlevel+1);
2520 #endif
2521 rb->lcd_puts(0, MIN(TEXT_LINES-3,10), str);
2522 rb->lcd_puts(0, MIN(TEXT_LINES-2,12), "High Score:");
2523 rb->snprintf(str, 30, "%d, Lvl %d",
2524 bb->highscores[0].score, bb->highscores[0].level);
2525 rb->lcd_puts(2, MIN(TEXT_LINES-1,13), str);
2526 } else {
2527 /* show high scores */
2528 rb->snprintf(str, 12, "High Scores");
2529 rb->lcd_getstringsize(str, &w, &h);
2530 rb->lcd_putsxy((LCD_WIDTH-w)/2, 0, str);
2532 for(i=0; i<NUM_SCORES; i++) {
2533 rb->snprintf(str, 30, "#%02d: %d, Lvl %d", i+1,
2534 bb->highscores[i].score, bb->highscores[i].level);
2535 rb->lcd_puts(0, i+2, str);
2539 rb->lcd_update();
2541 /* handle menu button presses */
2542 button = pluginlib_getaction(rb,TIMEOUT_BLOCK,plugin_contexts,2);
2543 switch(button){
2544 case BUBBLES_START: /* start playing */
2545 bb->level = startlevel;
2546 startgame = true;
2547 break;
2548 case BUBBLES_QUIT: /* quit program */
2549 if(showscores) {
2550 showscores = false;
2551 break;
2553 return BB_QUIT;
2555 case BUBBLES_RESUME: /* resume game */
2556 if(!bubbles_loadgame(bb)) {
2557 rb->splash(HZ*2, "Nothing to resume");
2558 } else {
2559 startgame = true;
2561 break;
2563 case BUBBLES_SELECT: /* toggle high scores */
2564 showscores = !showscores;
2565 break;
2567 case BUBBLES_LVLINC: /* increase starting level */
2568 case BUBBLES_LVLINC_REP:
2569 if(startlevel >= bb->highlevel) {
2570 startlevel = 0;
2571 } else {
2572 startlevel++;
2574 break;
2576 case BUBBLES_LVLDEC: /* decrease starting level */
2577 case BUBBLES_LVLDEC_REP:
2578 if(startlevel <= 0) {
2579 startlevel = bb->highlevel;
2580 } else {
2581 startlevel--;
2583 break;
2585 default:
2586 if(rb->default_event_handler_ex(button, bubbles_callback,
2587 (void*) bb) == SYS_USB_CONNECTED)
2588 return BB_USB;
2589 break;
2593 /********************
2594 * init *
2595 ********************/
2596 bubbles_init(bb);
2597 bubbles_drawboard(bb);
2598 rb->lcd_update();
2600 /**********************
2601 * play *
2602 **********************/
2603 bb->startedshot = *rb->current_tick;
2605 while(true) {
2606 /* refresh the board */
2607 bubbles_drawboard(bb);
2608 rb->lcd_update();
2610 /* manange idle framerate */
2611 bb->elapsedshot = *rb->current_tick-bb->startedshot;
2613 if(MAX_SHOTTIME-bb->elapsedshot < HZ/2) {
2614 timeout = MAX_SHOTTIME-bb->elapsedshot;
2615 } else {
2616 timeout = HZ/2;
2619 /* handle button events */
2620 buttonres = bubbles_handlebuttons(bb, false, timeout);
2621 if(buttonres != BB_NONE) return buttonres;
2623 /* handle timing */
2624 bb->elapsedshot = *rb->current_tick-bb->startedshot;
2626 if(bb->elapsedshot > MAX_SHOTTIME) {
2627 bb->elapsedlvl += bb->elapsedshot;
2628 bb->elapsedshot = 0;
2629 buttonres = bubbles_fire(bb);
2630 if(buttonres != BB_NONE) return buttonres;
2631 buttonres = bubbles_checklevel(bb);
2632 if(buttonres != BB_NONE) return buttonres;
2633 bb->startedshot = *rb->current_tick;
2638 /*****************************************************************************
2639 * plugin entry point.
2640 ******************************************************************************/
2641 enum plugin_status plugin_start(struct plugin_api* api, void* parameter) {
2642 struct game_context bb;
2643 bool exit = false;
2644 int position;
2646 /* plugin init */
2647 (void)parameter;
2648 rb = api;
2649 /* end of plugin init */
2651 /* more init */
2652 xlcd_init(rb);
2654 /* load files */
2655 rb->splash(0, "Loading...");
2656 bubbles_loadscores(&bb);
2657 rb->lcd_clear_display();
2659 /* start app */
2660 #if LCD_DEPTH > 1
2661 rb->lcd_set_backdrop(NULL);
2662 #endif
2663 rb->lcd_setfont(FONT_SYSFIXED);
2665 while(!exit) {
2666 switch(bubbles(&bb)){
2667 char str[19];
2668 case BB_WIN:
2669 rb->splash(HZ*2, "You Win!");
2670 /* record high level */
2671 if( NUM_LEVELS-1 > bb.highlevel) {
2672 bb.highlevel = NUM_LEVELS-1;
2673 bb.dirty = true;
2676 /* record high score */
2677 if((position = bubbles_recordscore(&bb))) {
2678 rb->snprintf(str, 19, "New high score #%d!", position);
2679 rb->splash(HZ*2, str);
2681 break;
2683 case BB_LOSE:
2684 rb->splash(HZ*2, "Game Over");
2685 /* fall through to BB_END */
2687 case BB_END:
2688 if(!bb.resume) {
2689 /* record high level */
2690 if(bb.level-1 > bb.highlevel) {
2691 bb.highlevel = bb.level-1;
2692 bb.dirty = true;
2695 /* record high score */
2696 if((position = bubbles_recordscore(&bb))) {
2697 rb->snprintf(str, 19, "New high score #%d!", position);
2698 rb->splash(HZ*2, str);
2701 break;
2703 case BB_USB:
2704 rb->lcd_setfont(FONT_UI);
2705 return PLUGIN_USB_CONNECTED;
2707 case BB_QUIT:
2708 if(bb.dirty) {
2709 rb->splash(HZ/2, "Saving high scores...");
2710 bubbles_savescores(&bb);
2712 exit = true;
2713 break;
2715 default:
2716 break;
2720 rb->lcd_setfont(FONT_UI);
2721 return PLUGIN_OK;
2724 #endif