A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 2674 lines 94 kB view raw
1/*************************************************************************** 2* __________ __ ___. 3* Open \______ \ ____ ____ | | _\_ |__ _______ ___ 4* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 5* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 6* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 7* \/ \/ \/ \/ \/ 8* $Id$ 9* 10* Copyright (C) 2005 Adam Boot 11* 12* Color graphics from Frozen Bubble (http://www.frozen-bubble.org/) 13* 14* This program is free software; you can redistribute it and/or 15* modify it under the terms of the GNU General Public License 16* as published by the Free Software Foundation; either version 2 17* of the License, or (at your option) any later version. 18* 19* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 20* KIND, either express or implied. 21* 22****************************************************************************/ 23 24#include "plugin.h" 25#include "fixedpoint.h" 26 27#include "lib/xlcd.h" 28#include "lib/pluginlib_actions.h" 29#include "lib/playback_control.h" 30#include "lib/highscore.h" 31 32/* files */ 33#define SCORE_FILE PLUGIN_GAMES_DATA_DIR "/bubbles.score" 34#define SAVE_FILE PLUGIN_GAMES_DATA_DIR "/bubbles.save" 35#define DATA_FILE PLUGIN_GAMES_DATA_DIR "/bubbles.data" 36 37/* final game return status */ 38enum { 39 BB_LOSE, 40 BB_QUIT_WITHOUT_SAVING, 41 BB_QUIT, 42 BB_USB, 43 BB_END, 44 BB_WIN, 45 BB_NONE, 46}; 47 48/* play board dimension */ 49#define BB_HEIGHT 12 50#define BB_WIDTH 8 51#define BB_LEVEL_HEIGHT 10 52 53/* various amounts */ 54#define NUM_SCORES 5 55#define NUM_LEVELS 100 56#define NUM_QUEUE 2 57#define NUM_BUBBLES 8 58#define MIN_ANGLE -76 59#define MAX_ANGLE 76 60#define NUM_COMPRESS 9 61#define MAX_SHOTTIME 1000 62 63/* keyboard layouts */ 64 65#ifdef HAVE_SCROLLWHEEL 66/* sansas use the wheel instead of left/right if available */ 67#define BUBBLES_LEFT PLA_SCROLL_BACK 68#define BUBBLES_LEFT_REP PLA_SCROLL_BACK_REPEAT 69#define BUBBLES_RIGHT PLA_SCROLL_FWD 70#define BUBBLES_RIGHT_REP PLA_SCROLL_FWD_REPEAT 71#else 72#define BUBBLES_LEFT PLA_LEFT 73#define BUBBLES_LEFT_REP PLA_LEFT_REPEAT 74#define BUBBLES_RIGHT PLA_RIGHT 75#define BUBBLES_RIGHT_REP PLA_RIGHT_REPEAT 76#endif 77 78#define ANGLE_STEP 2 79#define ANGLE_STEP_REP 6 80 81#define BUBBLES_QUIT1 PLA_EXIT 82 83/* these are better off shooting with up */ 84#if (CONFIG_KEYPAD == SAMSUNG_YH820_PAD) \ 85 || (CONFIG_KEYPAD == SAMSUNG_YH92X_PAD) \ 86 || (CONFIG_KEYPAD == IRIVER_H10_PAD) 87#define SHOOT_WITH_UP 88#endif 89 90#ifdef SHOOT_WITH_UP 91#define BUBBLES_FIRE PLA_UP 92#define BUBBLES_FIRE_REPEAT PLA_UP_REPEAT 93#define BUBBLES_PAUSE PLA_SELECT 94#define BUBBLES_QUIT2 PLA_CANCEL 95#elif (CONFIG_KEYPAD == IPOD_1G2G_PAD) \ 96 || (CONFIG_KEYPAD == IPOD_3G_PAD) \ 97 || (CONFIG_KEYPAD == IPOD_4G_PAD) 98#define BUBBLES_FIRE PLA_SELECT 99#define BUBBLES_FIRE_REPEAT PLA_SELECT_REPEAT 100#define BUBBLES_PAUSE PLA_DOWN 101#define BUBBLES_QUIT2 PLA_UP 102#else 103#define BUBBLES_FIRE PLA_SELECT 104#define BUBBLES_FIRE_REPEAT PLA_SELECT_REPEAT 105#define BUBBLES_PAUSE PLA_UP 106#define BUBBLES_QUIT2 PLA_CANCEL 107#endif 108 109/* external bitmaps */ 110#ifdef HAVE_LCD_COLOR 111#include "pluginbitmaps/bubbles_background.h" 112#endif 113#include "pluginbitmaps/bubbles_bubble.h" 114#include "pluginbitmaps/bubbles_emblem.h" 115 116#define BUBBLE_WIDTH BMPWIDTH_bubbles_bubble 117#define BUBBLE_HEIGHT BMPHEIGHT_bubbles_bubble 118#define EMBLEM_WIDTH BMPWIDTH_bubbles_emblem 119#define EMBLEM_HEIGHT (BMPHEIGHT_bubbles_emblem/8) 120 121/* bubbles will consume height of ROW_HEIGHT*(BB_HEIGHT-1)+BUBBLE_HEIGHT*3/2 */ 122/* 44x44 bubbles (m:robe 500) */ 123#if (LCD_WIDTH == 640) && (LCD_HEIGHT == 480) 124#define XOFS 144 125#define MAX_FPS 40 126 127/* custom text positioning */ 128#define LEVEL_TXT_X 58 129#define LEVEL_TXT_WIDTH 32 130#define LEVEL_TXT_Y 8 131#define SCORE_TXT_X 58 132#define SCORE_TXT_WIDTH 32 133#define SCORE_TXT_Y 62 134#define NEXT_BB_X 58 135#define NEXT_BB_WIDTH 32 136#define NEXT_BB_Y 402 137 138#elif (LCD_WIDTH == 480) && (LCD_HEIGHT == 640) 139#define XOFS 128 140#define MAX_FPS 40 141 142#elif (LCD_WIDTH == 360) && (LCD_HEIGHT == 400) 143#define XOFS 86 144#define YOFS 100 145#define SCORE_TXT_X 28 146#define SCORE_TXT_WIDTH 32 147#define SCORE_TXT_Y 48 148#define LEVEL_TXT_X 27 149#define LEVEL_TXT_WIDTH 32 150#define LEVEL_TXT_Y 5 151#define MAX_FPS 40 152 153/* 22x22 bubbles (iPod Video) */ 154#elif (LCD_HEIGHT == 240) && (LCD_WIDTH == 320) 155#define XOFS 72 156#define MAX_FPS 40 157 158/* custom text positioning */ 159#define NEXT_BB_X 20 160#define NEXT_BB_WIDTH 32 161#define NEXT_BB_Y 200 162 163/* 22x22 bubbles (Gigabeat, Onda VX747) */ 164#elif ((LCD_HEIGHT == 320) || (LCD_HEIGHT == 400)) && (LCD_WIDTH == 240) 165#define XOFS 64 166#define MAX_FPS 30 167 168/* custom text positioning */ 169#define LEVEL_TXT_X 21 170#define LEVEL_TXT_WIDTH 32 171#define LEVEL_TXT_Y 2 172#define SCORE_TXT_X 20 173#define SCORE_TXT_WIDTH 32 174#define SCORE_TXT_Y 29 175#define NEXT_BB_X 20 176#define NEXT_BB_WIDTH 32 177#define NEXT_BB_Y 200 178 179/* 22x22 bubbles (Anbernic RG Nano) */ 180#elif (LCD_HEIGHT == 240) && (LCD_WIDTH == 240) 181#define XOFS 64 182#define MAX_FPS 40 183 184/* custom text positioning */ 185#define SCORE_TXT_X 12 186#define SCORE_TXT_WIDTH 32 187#define SCORE_TXT_Y 29 188#define LEVEL_TXT_X 12 189#define LEVEL_TXT_WIDTH 32 190#define LEVEL_TXT_Y 2 191#define NEXT_BB_X 12 192#define NEXT_BB_WIDTH 32 193#define NEXT_BB_Y 200 194 195/* 16x16 bubbles (H300, iPod Color, HDD6330) */ 196#elif (LCD_HEIGHT == 176) && (LCD_WIDTH == 220) 197#define XOFS 46 198#define MAX_FPS 30 199 200/* 16x16 bubbles (Sansa E200) */ 201#elif (LCD_HEIGHT == 220) && (LCD_WIDTH == 176) 202#define XOFS 24 203#define MAX_FPS 30 204#define YOFS 45 205 206/* custom text positioning */ 207#define LEVEL_TXT_X 24 208#define LEVEL_TXT_WIDTH 31 209#define LEVEL_TXT_Y 5 210#define SCORE_TXT_X 58 211#define SCORE_TXT_WIDTH 31 212#define SCORE_TXT_Y 5 213#define NEXT_BB_X 112 214#define NEXT_BB_WIDTH 31 215#define NEXT_BB_Y 3 216 217/* 12x12 bubbles (iPod Nano) */ 218#elif (LCD_HEIGHT == 132) && (LCD_WIDTH == 176) 219#define XOFS 40 220#define MAX_FPS 40 221 222/* 12x12 bubbles (H100, H10, iAudio X5, HDD1630, iPod 3G, iPod 4G grayscale) */ 223#elif (LCD_HEIGHT == 128) && ((LCD_WIDTH == 160) || (LCD_WIDTH == 128)) 224#define XOFS 33 225#define MAX_FPS 30 226 227/* 12x12 bubbles (GoGear SA9200) */ 228#elif (LCD_HEIGHT == 160) && (LCD_WIDTH == 128) 229#define XOFS 16 230#define YOFS 32 231#define ROW_HEIGHT 10 232#define ROW_INDENT 6 233#define MAX_FPS 30 234 235/* custom text positioning */ 236#define LEVEL_TXT_X 2 237#define LEVEL_TXT_WIDTH 31 238#define LEVEL_TXT_Y 3 239#define SCORE_TXT_X 34 240#define SCORE_TXT_WIDTH 31 241#define SCORE_TXT_Y 3 242#define NEXT_BB_X 81 243#define NEXT_BB_WIDTH 31 244#define NEXT_BB_Y 2 245 246/* 10x10 bubbles (iPod Mini) */ 247#elif (LCD_HEIGHT == 110) && (LCD_WIDTH == 138) 248#define XOFS 33 249#define MAX_FPS 30 250 251/* 9x9 bubbles (iAudio M3, Samsung YH-820) */ 252#elif (LCD_HEIGHT == 96) && (LCD_WIDTH == 128) 253#define XOFS 29 254#define MAX_FPS 30 255 256/* 8x8 bubbles (Sansa C200) */ 257#elif ((LCD_HEIGHT == 80) && (LCD_WIDTH == 132)) 258#define XOFS 45 259#define ROW_HEIGHT 6 260#define MAX_FPS 30 261 262/* 7x7 bubbles (Sansa Clip/m200) */ 263#elif (LCD_HEIGHT == 64 && LCD_WIDTH == 128) 264#define XOFS 33 265#define ROW_HEIGHT 5 266#define MAX_FPS 30 267 268/* 8x7 bubbles (Archos recorder, Ondio) */ 269#elif (LCD_HEIGHT == 64) && (LCD_WIDTH == 112) 270#define XOFS 33 271#define ROW_HEIGHT 5 272#define MAX_FPS 20 273 274/* 7x7 bubbles (Sansa Clip Zip) */ 275#elif (LCD_HEIGHT == 96 && LCD_WIDTH == 96) 276#define XOFS 33 277#define ROW_HEIGHT 5 278#define MAX_FPS 30 279 280/* custom text positioning */ 281#define LEVEL_TXT_X 1 282#define LEVEL_TXT_WIDTH 31 283#define LEVEL_TXT_Y 4 284#define SCORE_TXT_X 1 285#define SCORE_TXT_WIDTH 31 286#define SCORE_TXT_Y 31 287#define NEXT_BB_X 1 288#define NEXT_BB_WIDTH 31 289#define NEXT_BB_Y 72 290 291#else 292 #error BUBBLES: Unsupported LCD type 293#endif 294 295#if !defined(ROW_HEIGHT) 296#define ROW_HEIGHT (BUBBLE_WIDTH-(BUBBLE_WIDTH-EMBLEM_WIDTH)/2) 297#endif 298 299#if !defined(ROW_INDENT) 300#define ROW_INDENT (BUBBLE_WIDTH/2) 301#endif 302 303#define TEXT_LINES (LCD_HEIGHT/8) 304 305#ifndef YOFS 306#define YOFS 0 307#endif 308 309/* shot position */ 310#define SHOTX XOFS+ROW_INDENT+BUBBLE_WIDTH*3 311#define SHOTY (YOFS+ROW_HEIGHT*(BB_HEIGHT-1)+BUBBLE_HEIGHT/2) 312 313/* collision distance squared */ 314#define MIN_DISTANCE ((BUBBLE_WIDTH*8)/10)*((BUBBLE_HEIGHT*8)/10) 315 316/* levels */ 317char level[NUM_LEVELS][BB_LEVEL_HEIGHT][BB_WIDTH] = { 318 {{ 6, 6, 4, 4, 2, 2, 3, 3}, 319 { 6, 6, 4, 4, 2, 2, 3, -1}, 320 { 2, 2, 3, 3, 6, 6, 4, 4}, 321 { 2, 3, 3, 6, 6, 4, 4, -1}, 322 {-1, -1, -1, -1, -1, -1, -1, -1}, 323 {-1, -1, -1, -1, -1, -1, -1, -1}, 324 {-1, -1, -1, -1, -1, -1, -1, -1}, 325 {-1, -1, -1, -1, -1, -1, -1, -1}, 326 {-1, -1, -1, -1, -1, -1, -1, -1}, 327 {-1, -1, -1, -1, -1, -1, -1, -1}}, 328 {{-1, 7, 7, 7, 7, 7, 7, -1}, 329 {-1, 1, 1, 1, 1, 1, -1, -1}, 330 {-1, -1, 2, 2, 2, 2, -1, -1}, 331 {-1, -1, -1, 2, -1, -1, -1, -1}, 332 {-1, -1, -1, 2, 2, -1, -1, -1}, 333 {-1, -1, -1, 5, -1, -1, -1, -1}, 334 {-1, -1, -1, 5, 5, -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, 7, -1, -1, 7, -1, -1}, 339 {-1, -1, 7, 1, 7, -1, -1, -1}, 340 {-1, -1, -1, 1, 2, -1, -1, -1}, 341 {-1, -1, 1, 2, 1, -1, -1, -1}, 342 {-1, -1, -1, 2, 5, -1, -1, -1}, 343 {-1, -1, 3, 5, 3, -1, -1, -1}, 344 {-1, -1, -1, 5, 3, -1, -1, -1}, 345 {-1, -1, -1, 3, -1, -1, -1, -1}, 346 {-1, -1, -1, -1, -1, -1, -1, -1}, 347 {-1, -1, -1, -1, -1, -1, -1, -1}}, 348 {{-1, -1, -1, 0, 0, -1, -1, -1}, 349 {-1, -1, 5, 0, 1, -1, -1, -1}, 350 {-1, -1, 3, 5, 1, 6, -1, -1}, 351 {-1, 4, 3, -1, 6, 7, -1, -1}, 352 {-1, 7, 4, -1, -1, 7, 4, -1}, 353 { 6, 7, -1, -1, -1, 4, 3, -1}, 354 { 1, 6, -1, -1, -1, -1, 3, 5}, 355 { 1, -1, -1, -1, -1, -1, 5, -1}, 356 {-1, -1, -1, -1, -1, -1, -1, -1}, 357 {-1, -1, -1, -1, -1, -1, -1, -1}}, 358 {{-1, -1, 0, 0, 0, 0, -1, -1}, 359 {-1, 0, 1, 1, 1, 0, -1, -1}, 360 {-1, 0, 1, 0, 0, 1, 0, -1}, 361 {-1, 0, 1, 1, 1, 0, -1, -1}, 362 {-1, -1, 0, 0, 0, 0, -1, -1}, 363 {-1, -1, 7, -1, 7, -1, -1, -1}, 364 {-1, -1, 7, 7, 7, 7, -1, -1}, 365 {-1, -1, -1, -1, -1, -1, -1, -1}, 366 {-1, -1, -1, -1, -1, -1, -1, -1}, 367 {-1, -1, -1, -1, -1, -1, -1, -1}}, 368 {{-1, 4, 4, 4, 6, 6, 6, -1}, 369 { 4, -1, -1, -1, -1, -1, 6, -1}, 370 {-1, 4, -1, -1, -1, -1, 6, -1}, 371 { 4, 2, 3, 1, 2, 3, 6, -1}, 372 {-1, 3, 1, 2, 3, 1, 2, -1}, 373 {-1, -1, -1, -1, -1, -1, -1, -1}, 374 {-1, -1, -1, -1, -1, -1, -1, -1}, 375 {-1, -1, -1, -1, -1, -1, -1, -1}, 376 {-1, -1, -1, -1, -1, -1, -1, -1}, 377 {-1, -1, -1, -1, -1, -1, -1, -1}}, 378 {{-1, 4, 4, 4, 6, 6, 6, -1}, 379 { 4, -1, -1, -1, -1, -1, 6, -1}, 380 {-1, 4, -1, -1, -1, -1, 6, -1}, 381 { 4, 2, 3, 1, 2, 3, 6, -1}, 382 {-1, 3, 1, 2, 3, 1, 2, -1}, 383 {-1, 2, 3, 1, 2, 3, -1, -1}, 384 {-1, -1, -1, -1, -1, -1, -1, -1}, 385 {-1, -1, -1, -1, -1, -1, -1, -1}, 386 {-1, -1, -1, -1, -1, -1, -1, -1}, 387 {-1, -1, -1, -1, -1, -1, -1, -1}}, 388 {{-1, 0, 0, -1, -1, 2, 2, -1}, 389 {-1, 5, -1, -1, -1, 3, -1, -1}, 390 {-1, 0, -1, -1, -1, 6, -1, -1}, 391 {-1, 3, -1, -1, -1, 0, -1, -1}, 392 {-1, 4, -1, -1, -1, 5, -1, -1}, 393 {-1, 2, -1, -1, -1, 3, -1, -1}, 394 {-1, 2, -1, -1, -1, 1, -1, -1}, 395 {-1, 3, -1, -1, -1, 4, -1, -1}, 396 {-1, -1, -1, -1, -1, -1, -1, -1}, 397 {-1, -1, -1, -1, -1, -1, -1, -1}}, 398 {{ 3, -1, -1, -1, -1, -1, -1, 3}, 399 { 6, 3, 2, 4, 6, 3, 2, -1}, 400 { 4, -1, -1, -1, -1, -1, -1, 4}, 401 { 2, 4, 6, 3, 2, 4, 6, -1}, 402 {-1, -1, -1, 6, -1, -1, -1, -1}, 403 {-1, -1, -1, 3, -1, -1, -1, -1}, 404 {-1, -1, -1, -1, -1, -1, -1, -1}, 405 {-1, -1, -1, -1, -1, -1, -1, -1}, 406 {-1, -1, -1, -1, -1, -1, -1, -1}, 407 {-1, -1, -1, -1, -1, -1, -1, -1}}, 408 {{-1, 2, -1, 1, -1, 1, -1, 2}, 409 { 1, 2, -1, 2, 1, -1, 1, -1}, 410 { 1, -1, 1, -1, 2, -1, 2, -1}, 411 { 2, 1, -1, 1, 2, -1, 2, -1}, 412 {-1, 2, -1, 2, -1, 2, -1, 2}, 413 { 1, 2, -1, 2, 1, -1, 1, -1}, 414 { 1, -1, 1, -1, 2, -1, 1, -1}, 415 { 2, 2, -1, 1, 1, -1, 2, -1}, 416 {-1, 2, -1, 1, -1, 1, -1, 1}, 417 {-1, -1, -1, -1, -1, -1, -1, -1}}, 418 {{-1, 7, 7, -1, -1, 5, 5, -1}, 419 { 1, -1, -1, -1, -1, -1, 4, -1}, 420 { 2, 1, -1, -1, -1, -1, 4, 3}, 421 { 2, -1, -1, -1, -1, -1, 3, -1}, 422 { 1, 2, -1, -1, -1, -1, 3, 4}, 423 { 1, -1, -1, -1, -1, -1, 4, -1}, 424 { 7, 1, -1, -1, -1, -1, 4, 5}, 425 { 7, 7, -1, -1, -1, 5, 5, -1}, 426 {-1, -1, -1, -1, -1, -1, -1, -1}, 427 {-1, -1, -1, -1, -1, -1, -1, -1}}, 428 {{ 7, 7, -1, -1, -1, -1, 5, 5}, 429 { 1, 5, -1, -1, -1, 7, 4, -1}, 430 { 2, 1, -1, -1, -1, -1, 4, 3}, 431 { 2, -1, -1, -1, -1, -1, 3, -1}, 432 { 1, 5, -1, -1, -1, -1, 7, 4}, 433 { 1, -1, -1, -1, -1, -1, 4, -1}, 434 { 7, 1, -1, -1, -1, -1, 4, 5}, 435 { 7, 5, -1, -1, -1, 7, 5, -1}, 436 {-1, -1, -1, -1, -1, -1, -1, -1}, 437 {-1, -1, -1, -1, -1, -1, -1, -1}}, 438 {{-1, -1, -1, 0, 0, -1, -1, -1}, 439 {-1, -1, 5, 0, 1, -1, -1, -1}, 440 {-1, -1, 3, 5, 1, 6, -1, -1}, 441 {-1, 4, 3, 2, 6, 2, -1, -1}, 442 {-1, 7, 4, 7, 2, 2, 4, -1}, 443 { 6, 7, 7, 3, 3, 4, 3, -1}, 444 { 1, 6, 1, 1, 1, 3, 3, 5}, 445 { 1, 1, -1, -1, -1, -1, 5, -1}, 446 {-1, -1, -1, -1, -1, -1, -1, -1}, 447 {-1, -1, -1, -1, -1, -1, -1, -1}}, 448 {{-1, -1, 0, -1, -1, 0, -1, -1}, 449 {-1, 3, 3, -1, 3, 3, -1, -1}, 450 {-1, 0, 2, 0, 0, 2, 0, -1}, 451 {-1, 3, 3, -1, 3, 3, -1, -1}, 452 {-1, -1, 0, -1, -1, 0, -1, -1}, 453 {-1, -1, -1, -1, -1, -1, -1, -1}, 454 {-1, -1, -1, -1, -1, -1, -1, -1}, 455 {-1, -1, -1, -1, -1, -1, -1, -1}, 456 {-1, -1, -1, -1, -1, -1, -1, -1}, 457 {-1, -1, -1, -1, -1, -1, -1, -1}}, 458 {{-1, -1, -1, 1, 1, -1, -1, -1}, 459 {-1, -1, 2, 2, 2, -1, -1, -1}, 460 {-1, -1, 3, 3, 3, 3, -1, -1}, 461 {-1, 4, 4, 4, 4, 4, -1, -1}, 462 {-1, 5, 5, 5, 5, 5, 5, -1}, 463 {-1, -1, -1, 6, -1, -1, -1, -1}, 464 {-1, -1, -1, 7, 7, -1, -1, -1}, 465 {-1, -1, -1, 0, -1, -1, -1, -1}, 466 {-1, -1, -1, -1, -1, -1, -1, -1}, 467 {-1, -1, -1, -1, -1, -1, -1, -1}}, 468 {{-1, -1, -1, 2, 5, -1, -1, -1}, 469 {-1, 4, 3, -1, -1, -1, -1, -1}, 470 { 6, 7, -1, 5, 2, -1, -1, -1}, 471 {-1, -1, -1, -1, 3, 4, -1, -1}, 472 {-1, -1, -1, 2, 5, -1, 7, 6}, 473 {-1, 4, 3, -1, -1, -1, -1, -1}, 474 { 6, 7, -1, 5, 2, -1, -1, -1}, 475 {-1, -1, -1, -1, 3, 4, -1, -1}, 476 {-1, -1, -1, -1, -1, -1, 7, 6}, 477 {-1, -1, -1, -1, -1, -1, -1, -1}}, 478 {{-1, -1, -1, 5, 5, -1, -1, -1}, 479 {-1, -1, -1, 3, -1, -1, -1, -1}, 480 {-1, -1, -1, 1, -1, -1, -1, -1}, 481 {-1, -1, -1, 7, -1, -1, -1, -1}, 482 {-1, -1, -1, 2, -1, -1, -1, -1}, 483 {-1, -1, -1, 4, -1, -1, -1, -1}, 484 {-1, -1, -1, 5, -1, -1, -1, -1}, 485 {-1, -1, -1, 3, -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, 0, 1, -1, -1, -1}, 489 {-1, -1, 0, 2, 7, 7, -1, -1}, 490 {-1, -1, -1, 0, 1, 7, -1, -1}, 491 {-1, 0, 0, 0, 0, -1, -1, -1}, 492 {-1, 0, 0, 0, 1, 1, -1, -1}, 493 { 0, 0, 0, 1, 1, 1, -1, -1}, 494 {-1, 0, 0, 1, 1, 1, -1, -1}, 495 {-1, 0, 0, 0, 7, 7, -1, -1}, 496 {-1, -1, 7, 7, -1, -1, -1, -1}, 497 {-1, -1, -1, -1, -1, -1, -1, -1}}, 498 {{-1, 1, -1, -1, -1, -1, -1, -1}, 499 { 1, -1, -1, -1, -1, -1, -1, -1}, 500 {-1, 2, 3, 4, 7, 6, 5, -1}, 501 {-1, -1, -1, -1, -1, -1, 1, -1}, 502 {-1, -1, -1, -1, -1, -1, 1, -1}, 503 {-1, 2, 3, 4, 7, 6, -1, -1}, 504 {-1, 1, -1, -1, -1, -1, -1, -1}, 505 { 1, -1, -1, -1, -1, -1, -1, -1}, 506 {-1, 2, 3, 4, 7, 6, 5, -1}, 507 {-1, -1, -1, -1, -1, -1, -1, -1}}, 508 {{-1, 6, -1, -1, -1, -1, -1, -1}, 509 { 5, -1, -1, -1, -1, -1, -1, -1}, 510 { 2, 3, 4, 7, 6, 5, 2, 3}, 511 {-1, -1, -1, -1, -1, -1, 4, -1}, 512 {-1, -1, -1, -1, -1, -1, 7, -1}, 513 {-1, 4, 3, 2, 5, 6, -1, -1}, 514 {-1, 7, -1, -1, -1, -1, -1, -1}, 515 { 6, -1, -1, -1, -1, -1, -1, -1}, 516 { 5, 2, 3, 4, 7, 6, 5, -1}, 517 {-1, -1, -1, -1, -1, -1, -1, -1}}, 518 {{ 3, 2, 1, 0, 0, 1, 2, 3}, 519 { 3, 2, 1, 0, 1, 2, 3, -1}, 520 { 4, 3, 2, 1, 1, 2, 3, 4}, 521 { 4, 3, 2, 1, 2, 3, 4, -1}, 522 { 5, 4, 3, 2, 2, 3, 4, 5}, 523 { 5, 4, 3, 2, 3, 4, 5, -1}, 524 { 6, 5, 4, 3, 3, 4, 5, 6}, 525 { 6, 5, 4, 3, 4, 5, 6, -1}, 526 { 7, 6, 5, 4, 4, 5, 6, 7}, 527 {-1, -1, -1, -1, -1, -1, -1, -1}}, 528 {{-1, -1, -1, 5, 5, -1, -1, -1}, 529 {-1, -1, -1, 3, -1, -1, -1, -1}, 530 {-1, -1, -1, 2, 4, -1, -1, -1}, 531 {-1, -1, -1, 6, -1, -1, -1, -1}, 532 {-1, -1, -1, 2, 4, -1, -1, -1}, 533 {-1, 2, -1, 5, -1, 4, -1, -1}, 534 { 1, 0, 1, 0, 1, 0, 1, 0}, 535 { 3, -1, 3, -1, 2, -1, 6, -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 { 7, 4, 3, 5, -1, -1, -1, -1}, 540 { 6, -1, -1, 1, -1, -1, -1, -1}, 541 {-1, -1, -1, 5, 3, 4, 7, -1}, 542 { 6, -1, -1, -1, 1, -1, -1, 6}, 543 { 7, 4, 3, 5, -1, -1, -1, -1}, 544 {-1, -1, -1, 1, -1, -1, -1, 6}, 545 {-1, -1, -1, 5, 3, 4, 7, -1}, 546 {-1, -1, -1, -1, -1, -1, -1, -1}, 547 {-1, -1, -1, -1, -1, -1, -1, -1}}, 548 {{-1, -1, -1, -1, 7, 3, 6, -1}, 549 {-1, -1, 3, 7, 3, 6, 3, -1}, 550 {-1, -1, 5, 7, 3, 6, 3, -1}, 551 {-1, 6, 7, 3, 6, 7, -1, -1}, 552 {-1, 7, 7, 3, 6, 1, -1, -1}, 553 { 3, 7, 3, 6, 3, -1, -1, -1}, 554 { 5, 6, 2, 7, 1, -1, -1, -1}, 555 {-1, -1, -1, -1, -1, -1, -1, -1}, 556 {-1, -1, -1, -1, -1, -1, -1, -1}, 557 {-1, -1, -1, -1, -1, -1, -1, -1}}, 558 {{ 5, -1, -1, -1, -1, -1, -1, 5}, 559 { 5, -1, 6, 6, 6, -1, 5, -1}, 560 {-1, 5, 4, -1, -1, 4, 5, -1}, 561 {-1, 3, -1, -1, -1, 3, -1, -1}, 562 {-1, 6, 0, -1, -1, 0, 6, -1}, 563 {-1, 3, -1, -1, -1, 3, -1, -1}, 564 {-1, -1, 4, -1, -1, 4, -1, -1}, 565 {-1, -1, 6, 6, 6, -1, -1, -1}, 566 {-1, -1, -1, -1, -1, -1, -1, -1}, 567 {-1, -1, -1, -1, -1, -1, -1, -1}}, 568 {{-1, 7, 0, -1, -1, 0, 7, -1}, 569 { 7, -1, 0, -1, 0, -1, 7, -1}, 570 { 7, 1, -1, 0, 0, -1, 1, 7}, 571 { 7, 1, 2, 0, 2, 1, 7, -1}, 572 { 7, 6, 3, 2, 2, 3, 6, 7}, 573 { 7, -1, 3, 2, 3, -1, 7, -1}, 574 {-1, 7, 7, 3, 3, 7, 7, -1}, 575 {-1, -1, -1, 3, -1, -1, -1, -1}, 576 {-1, -1, -1, -1, -1, -1, -1, -1}, 577 {-1, -1, -1, -1, -1, -1, -1, -1}}, 578 {{-1, 3, -1, 1, -1, 7, -1, 6}, 579 { 5, -1, 7, -1, 7, -1, 6, -1}, 580 { 6, -1, 0, -1, 5, -1, 3, -1}, 581 {-1, 2, -1, 1, -1, 5, -1, -1}, 582 {-1, 4, -1, 3, -1, 4, -1, -1}, 583 { 2, -1, 3, -1, 2, -1, -1, -1}, 584 {-1, -1, 4, -1, 6, -1, -1, -1}, 585 {-1, -1, -1, 5, -1, -1, -1, -1}, 586 {-1, -1, -1, -1, -1, -1, -1, -1}, 587 {-1, -1, -1, -1, -1, -1, -1, -1}}, 588 {{-1, -1, -1, -1, 1, -1, -1, -1}, 589 {-1, -1, -1, -1, 3, -1, -1, -1}, 590 { 6, 1, 3, 1, 2, 1, 4, 1}, 591 {-1, -1, -1, -1, 6, -1, -1, -1}, 592 {-1, -1, -1, 4, 1, -1, -1, -1}, 593 {-1, -1, 1, -1, 3, -1, -1, -1}, 594 {-1, -1, -1, 2, 1, -1, -1, -1}, 595 {-1, -1, -1, -1, 4, -1, -1, -1}, 596 {-1, -1, -1, 6, 1, -1, -1, -1}, 597 {-1, -1, -1, 6, -1, -1, -1, -1}}, 598 {{-1, -1, -1, 5, 4, -1, -1, -1}, 599 {-1, -1, 4, 1, 0, -1, -1, -1}, 600 {-1, -1, -1, 2, 3, -1, -1, -1}, 601 {-1, 1, 4, -1, 2, 2, -1, -1}, 602 {-1, 3, 1, 2, 5, 1, 4, -1}, 603 {-1, 4, 2, -1, 0, 4, -1, -1}, 604 {-1, -1, -1, -1, -1, -1, -1, -1}, 605 {-1, -1, -1, -1, -1, -1, -1, -1}, 606 {-1, -1, -1, -1, -1, -1, -1, -1}, 607 {-1, -1, -1, -1, -1, -1, -1, -1}}, 608 {{-1, -1, -1, -1, 1, -1, -1, -1}, 609 {-1, -1, -1, 1, -1, -1, -1, -1}, 610 {-1, 2, -1, -1, 1, -1, 5, -1}, 611 { 5, -1, -1, 1, -1, -1, 0, -1}, 612 {-1, 6, -1, -1, 1, -1, 4, -1}, 613 {-1, 0, -1, 1, -1, 5, -1, -1}, 614 {-1, -1, 5, 5, 0, 1, -1, -1}, 615 {-1, -1, -1, -1, -1, -1, -1, -1}, 616 {-1, -1, -1, -1, -1, -1, -1, -1}, 617 {-1, -1, -1, -1, -1, -1, -1, -1}}, 618 {{-1, -1, -1, 6, 3, -1, -1, -1}, 619 {-1, -1, 3, 2, 6, -1, -1, -1}, 620 {-1, -1, 2, 6, 3, 2, -1, -1}, 621 {-1, 6, 3, 2, 6, 3, -1, -1}, 622 {-1, 3, 2, 6, 3, 2, 6, -1}, 623 { 2, 6, 3, 2, 6, 3, 2, -1}, 624 { 6, 3, 2, 6, 3, 2, 6, 3}, 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 {{ 6, 6, 6, 6, 6, 6, 6, 6}, 629 { 4, -1, -1, -1, -1, -1, -1, -1}, 630 {-1, 3, 2, 5, 7, 6, 4, 3}, 631 {-1, 5, -1, -1, -1, -1, -1, -1}, 632 {-1, -1, 7, 6, 4, 3, 2, 5}, 633 {-1, -1, 4, -1, -1, -1, -1, -1}, 634 {-1, -1, -1, 3, 2, 5, 7, 6}, 635 {-1, -1, -1, -1, -1, -1, -1, -1}, 636 {-1, -1, -1, -1, -1, -1, -1, -1}, 637 {-1, -1, -1, -1, -1, -1, -1, -1}}, 638 {{ 1, -1, 7, -1, -1, 6, -1, 2}, 639 { 6, -1, 1, -1, 6, 1, 3, -1}, 640 {-1, 4, -1, 7, 2, -1, 7, -1}, 641 { 2, 7, -1, -1, -1, 4, -1, -1}, 642 { 6, -1, 3, 5, 0, 2, -1, 7}, 643 { 1, -1, -1, -1, -1, -1, 1, -1}, 644 {-1, 1, 4, 5, 7, 5, 1, -1}, 645 {-1, -1, -1, -1, -1, -1, -1, -1}, 646 {-1, -1, -1, -1, -1, -1, -1, -1}, 647 {-1, -1, -1, -1, -1, -1, -1, -1}}, 648 {{ 6, 6, 6, -1, -1, 6, 6, 6}, 649 {-1, -1, 6, -1, 6, -1, -1, -1}, 650 {-1, -1, 2, 3, 3, 2, -1, -1}, 651 {-1, 3, -1, 5, -1, 3, -1, -1}, 652 {-1, -1, 5, 3, 3, 5, -1, -1}, 653 {-1, -1, 6, 1, 6, -1, -1, -1}, 654 {-1, 4, 2, -1, -1, 2, 4, -1}, 655 {-1, -1, -1, -1, -1, -1, -1, -1}, 656 {-1, -1, -1, -1, -1, -1, -1, -1}, 657 {-1, -1, -1, -1, -1, -1, -1, -1}}, 658 {{-1, -1, -1, 5, 5, -1, -1, -1}, 659 {-1, -1, 5, -1, -1, -1, -1, -1}, 660 {-1, 3, 4, 6, 6, -1, -1, 5}, 661 { 3, 3, 4, 6, 5, -1, 5, -1}, 662 { 3, 2, 3, 6, 6, 5, 5, -1}, 663 { 3, 3, 4, 6, 5, -1, 5, -1}, 664 {-1, 3, 4, 6, 6, -1, -1, 5}, 665 {-1, -1, 5, -1, -1, -1, -1, -1}, 666 {-1, -1, -1, 5, 5, -1, -1, -1}, 667 {-1, -1, -1, -1, -1, -1, -1, -1}}, 668 {{ 1, -1, -1, -1, -1, -1, -1, 1}, 669 { 1, -1, 2, 2, 2, -1, 1, -1}, 670 {-1, 1, 2, 3, 3, 2, 1, -1}, 671 { 6, 2, 3, -1, 3, 2, 6, -1}, 672 { 6, 2, 3, -1, -1, 3, 2, 6}, 673 { 6, 2, 3, -1, 3, 2, 6, -1}, 674 { 3, 3, 3, 7, 7, 3, 3, 3}, 675 { 0, 5, 0, 2, 0, 5, 0, -1}, 676 {-1, -1, -1, -1, -1, -1, -1, -1}, 677 {-1, -1, -1, -1, -1, -1, -1, -1}}, 678 {{-1, -1, 7, 7, 7, -1, -1, -1}, 679 {-1, 7, 2, 2, 7, -1, -1, -1}, 680 {-1, 7, 5, 5, 5, 7, -1, -1}, 681 { 7, 7, 7, 7, 7, 7, -1, -1}, 682 {-1, -1, 6, -1, 6, -1, -1, -1}, 683 {-1, 6, -1, -1, 6, -1, -1, -1}, 684 {-1, 6, 4, 4, -1, 6, 4, 4}, 685 {-1, -1, -1, -1, -1, -1, -1, -1}, 686 {-1, -1, -1, -1, -1, -1, -1, -1}, 687 {-1, -1, -1, -1, -1, -1, -1, -1}}, 688 {{-1, 3, 3, -1, 3, 3, 3, -1}, 689 { 3, 7, 5, 4, 6, 5, 3, -1}, 690 { 1, 3, 3, 3, -1, 3, 3, 1}, 691 { 2, 1, 2, 1, 2, 1, 2, -1}, 692 { 1, 3, 3, -1, 3, 3, 3, 1}, 693 { 3, 5, 6, 4, 5, 7, 3, -1}, 694 { 2, 3, 3, 3, -1, 3, 3, 2}, 695 { 1, 1, 2, 2, 2, 1, 1, -1}, 696 {-1, -1, -1, -1, -1, -1, -1, -1}, 697 {-1, -1, -1, -1, -1, -1, -1, -1}}, 698 {{-1, 6, 5, -1, -1, -1, -1, -1}, 699 { 3, 1, 3, -1, -1, -1, -1, -1}, 700 {-1, 5, 6, -1, -1, -1, -1, -1}, 701 {-1, -1, 5, 3, -1, -1, -1, -1}, 702 {-1, -1, 6, 1, 6, -1, -1, -1}, 703 {-1, -1, 3, 5, -1, -1, -1, -1}, 704 {-1, -1, -1, -1, 3, 6, -1, -1}, 705 {-1, -1, -1, 5, 6, 5, -1, -1}, 706 {-1, -1, -1, -1, 6, 3, -1, -1}, 707 {-1, -1, -1, -1, -1, -1, -1, -1}}, 708 {{ 6, 3, 7, 4, 5, 1, 6, 3}, 709 { 5, 1, 6, 3, 7, 4, 5, -1}, 710 { 6, 3, 7, 4, 5, 1, 6, 3}, 711 {-1, -1, -1, -1, -1, -1, -1, -1}, 712 {-1, -1, -1, -1, -1, -1, -1, -1}, 713 {-1, -1, -1, -1, -1, -1, -1, -1}, 714 {-1, -1, -1, -1, -1, -1, -1, -1}, 715 {-1, -1, -1, -1, -1, -1, -1, -1}, 716 {-1, -1, -1, -1, -1, -1, -1, -1}, 717 {-1, -1, -1, -1, -1, -1, -1, -1}}, 718 {{-1, -1, -1, -1, -1, -1, 4, 4}, 719 {-1, -1, 7, 7, 7, 4, 4, -1}, 720 {-1, -1, -1, -1, -1, -1, 4, 4}, 721 {-1, 1, -1, -1, -1, 7, -1, -1}, 722 {-1, 1, 1, -1, -1, 7, -1, -1}, 723 { 3, 3, 3, -1, 7, -1, -1, -1}, 724 { 3, -1, 2, 3, 3, 3, -1, 3}, 725 {-1, 2, -1, 3, -1, 3, 3, -1}, 726 {-1, 2, -1, -1, -1, -1, -1, -1}, 727 {-1, -1, -1, -1, -1, -1, -1, -1}}, 728 {{-1, -1, 4, -1, -1, -1, -1, -1}, 729 {-1, 7, 4, -1, -1, -1, -1, -1}, 730 {-1, -1, 7, 4, -1, -1, -1, -1}, 731 {-1, 4, 7, 4, -1, -1, -1, -1}, 732 { 1, 1, 1, 1, 1, 1, 1, -1}, 733 { 1, 2, 1, 2, 1, 1, -1, -1}, 734 { 2, 2, 2, 2, 2, 2, 2, 2}, 735 {-1, -1, -1, -1, -1, -1, -1, -1}, 736 {-1, -1, -1, -1, -1, -1, -1, -1}, 737 {-1, -1, -1, -1, -1, -1, -1, -1}}, 738 {{ 0, -1, -1, -1, -1, -1, -1, 6}, 739 { 6, 1, 4, 3, 7, 5, 0, -1}, 740 { 0, -1, -1, -1, -1, -1, -1, 6}, 741 { 6, 1, 4, 3, 7, 5, 0, -1}, 742 { 0, -1, -1, -1, -1, -1, -1, 6}, 743 { 6, 1, 4, 3, 7, 5, 0, -1}, 744 {-1, -1, -1, -1, -1, -1, -1, -1}, 745 {-1, -1, -1, -1, -1, -1, -1, -1}, 746 {-1, -1, -1, -1, -1, -1, -1, -1}, 747 {-1, -1, -1, -1, -1, -1, -1, -1}}, 748 {{ 3, 3, 4, 6, 6, 4, 3, 3}, 749 { 0, 3, 4, 6, 4, 3, 1, -1}, 750 { 5, 1, 3, 4, 4, 3, 0, 1}, 751 { 0, 1, 3, 4, 3, 1, 0, -1}, 752 { 2, 1, 6, 3, 3, 0, 0, 1}, 753 { 0, 3, 4, 3, 6, 1, 5, -1}, 754 { 6, 1, 2, 6, 4, 0, 0, 2}, 755 {-1, -1, -1, -1, -1, -1, -1, -1}, 756 {-1, -1, -1, -1, -1, -1, -1, -1}, 757 {-1, -1, -1, -1, -1, -1, -1, -1}}, 758 {{ 6, 6, -1, -1, -1, -1, 4, 4}, 759 { 4, 0, -1, -1, -1, 3, 6, -1}, 760 { 0, 6, -1, -1, -1, -1, 4, 2}, 761 { 7, -1, -1, -1, -1, -1, 7, -1}, 762 { 4, 4, -1, -1, -1, -1, 5, 6}, 763 { 6, 4, 7, 7, 5, 6, 4, -1}, 764 {-1, 7, 6, 4, 6, 4, 7, -1}, 765 {-1, 0, -1, 7, -1, 7, -1, -1}, 766 {-1, -1, -1, -1, -1, -1, -1, -1}, 767 {-1, -1, -1, -1, -1, -1, -1, -1}}, 768 {{-1, 5, -1, -1, -1, -1, 4, -1}, 769 {-1, 5, -1, -1, -1, 4, -1, -1}, 770 {-1, -1, 5, 6, 6, 4, -1, -1}, 771 {-1, -1, 2, -1, 2, -1, -1, -1}, 772 { 0, 0, 6, -1, -1, 6, 1, 1}, 773 {-1, -1, 2, -1, 2, -1, -1, -1}, 774 {-1, -1, 7, 6, 6, 3, -1, -1}, 775 {-1, 7, -1, -1, -1, 3, -1, -1}, 776 {-1, 7, -1, -1, -1, -1, 3, -1}, 777 {-1, -1, -1, -1, -1, -1, -1, -1}}, 778 {{-1, 6, -1, -1, -1, -1, 2, -1}, 779 { 1, 7, 1, 1, 1, 3, 1, -1}, 780 {-1, -1, 4, 1, 1, 4, -1, -1}, 781 {-1, 1, 3, 1, 7, 1, -1, -1}, 782 {-1, -1, -1, 2, 6, -1, -1, -1}, 783 {-1, -1, 1, 5, 1, -1, -1, -1}, 784 {-1, -1, -1, -1, -1, -1, -1, -1}, 785 {-1, -1, -1, -1, -1, -1, -1, -1}, 786 {-1, -1, -1, -1, -1, -1, -1, -1}, 787 {-1, -1, -1, -1, -1, -1, -1, -1}}, 788 {{ 7, 7, 7, 7, 7, 7, 7, 7}, 789 { 7, -1, -1, -1, -1, -1, 7, -1}, 790 { 7, -1, -1, 2, 0, 5, 2, 2}, 791 { 7, -1, -1, -1, 0, 3, 6, -1}, 792 { 7, -1, -1, -1, -1, -1, 4, 0}, 793 { 5, 5, -1, -1, -1, -1, -1, -1}, 794 { 4, 3, 6, 2, -1, -1, -1, -1}, 795 { 0, 2, 0, 4, -1, -1, -1, -1}, 796 {-1, -1, -1, -1, -1, -1, -1, -1}, 797 {-1, -1, -1, -1, -1, -1, -1, -1}}, 798 {{-1, -1, 1, -1, -1, 1, -1, -1}, 799 {-1, 4, -1, -1, 5, -1, -1, -1}, 800 {-1, 7, -1, -1, 1, 1, 1, -1}, 801 { 6, -1, -1, -1, -1, 7, -1, -1}, 802 { 1, 1, 1, 1, -1, 4, -1, -1}, 803 {-1, -1, 5, -1, -1, -1, -1, -1}, 804 {-1, -1, 0, -1, -1, -1, -1, -1}, 805 {-1, 3, -1, -1, -1, -1, -1, -1}, 806 {-1, 1, -1, -1, -1, -1, -1, -1}, 807 {-1, -1, -1, -1, -1, -1, -1, -1}}, 808 {{-1, 7, 7, -1, -1, 7, 7, -1}, 809 { 6, -1, 4, -1, 4, -1, 6, -1}, 810 { 5, -1, -1, 3, 3, -1, -1, 5}, 811 { 6, -1, -1, -1, -1, -1, 6, -1}, 812 {-1, 7, -1, -1, -1, -1, 7, -1}, 813 {-1, 4, -1, -1, -1, 4, -1, -1}, 814 {-1, -1, 3, -1, -1, 3, -1, -1}, 815 {-1, -1, 2, -1, 2, -1, -1, -1}, 816 {-1, -1, -1, 5, 5, -1, -1, -1}, 817 {-1, -1, -1, -1, -1, -1, -1, -1}}, 818 {{-1, 0, 0, -1, -1, 0, 0, -1}, 819 { 7, 4, 6, 6, 6, 4, 3, -1}, 820 { 5, 6, 6, 6, 2, 6, 6, 3}, 821 { 7, 4, 6, 6, 6, 4, 3, -1}, 822 {-1, 0, 0, -1, -1, 0, 0, -1}, 823 {-1, -1, -1, -1, -1, -1, -1, -1}, 824 {-1, -1, -1, -1, -1, -1, -1, -1}, 825 {-1, -1, -1, -1, -1, -1, -1, -1}, 826 {-1, -1, -1, -1, -1, -1, -1, -1}, 827 {-1, -1, -1, -1, -1, -1, -1, -1}}, 828 {{-1, -1, -1, -1, -1, 7, 7, 7}, 829 {-1, -1, -1, -1, 2, 7, 7, -1}, 830 {-1, 0, 7, 7, 7, -1, 7, 7}, 831 { 6, 7, 7, 7, -1, -1, -1, -1}, 832 { 6, -1, -1, -1, 7, 7, 7, 7}, 833 { 6, -1, -1, -1, -1, -1, -1, -1}, 834 { 4, 2, 2, 2, 4, -1, 3, -1}, 835 { 4, 4, 4, 4, 3, 3, 3, -1}, 836 {-1, -1, -1, -1, -1, -1, -1, -1}, 837 {-1, -1, -1, -1, -1, -1, -1, -1}}, 838 {{ 4, -1, -1, 7, -1, 6, -1, 7}, 839 { 7, 6, 7, -1, -1, 7, 4, -1}, 840 {-1, -1, 7, -1, -1, 7, -1, -1}, 841 {-1, 0, 0, 0, 0, 0, 3, -1}, 842 {-1, -1, 0, 2, 2, 0, 6, 4}, 843 {-1, -1, 0, 0, 0, 1, 3, -1}, 844 {-1, -1, -1, 0, 0, -1, 3, 4}, 845 {-1, -1, -1, 6, -1, 5, 6, -1}, 846 {-1, -1, -1, -1, -1, -1, 1, 0}, 847 {-1, -1, -1, -1, -1, -1, -1, -1}}, 848 {{-1, 5, -1, -1, -1, -1, 5, -1}, 849 { 0, -1, -1, 0, -1, -1, 0, -1}, 850 { 0, 0, 0, 2, 2, 0, 0, 0}, 851 { 0, -1, -1, 0, -1, -1, 0, -1}, 852 {-1, 7, -1, 3, -1, -1, 7, -1}, 853 {-1, -1, 3, 6, -1, -1, -1, -1}, 854 {-1, -1, -1, 6, -1, -1, -1, -1}, 855 {-1, 3, 6, -1, -1, -1, -1, -1}, 856 {-1, 3, -1, -1, -1, -1, -1, -1}, 857 {-1, -1, -1, -1, -1, -1, -1, -1}}, 858 {{-1, -1, -1, 6, 5, -1, -1, -1}, 859 {-1, -1, 2, 6, 3, -1, -1, -1}, 860 {-1, -1, 5, 4, 7, 1, -1, -1}, 861 {-1, 6, 2, 2, 3, 4, -1, -1}, 862 {-1, -1, 3, 7, 3, 6, -1, -1}, 863 {-1, -1, 1, 3, 2, -1, -1, -1}, 864 {-1, -1, -1, 4, 5, -1, -1, -1}, 865 {-1, -1, -1, 4, -1, -1, -1, -1}, 866 {-1, -1, -1, -1, -1, -1, -1, -1}, 867 {-1, -1, -1, -1, -1, -1, -1, -1}}, 868 {{ 7, 7, -1, 2, 2, -1, 6, 6}, 869 { 6, -1, -1, 6, -1, -1, 3, -1}, 870 { 2, -1, -1, 1, -1, -1, 2, -1}, 871 { 5, -1, -1, 3, -1, -1, 2, -1}, 872 { 1, -1, -1, 2, -1, -1, 1, -1}, 873 { 5, -1, -1, 2, -1, -1, 2, -1}, 874 { 6, -1, -1, 1, -1, -1, 7, -1}, 875 { 5, -1, -1, 5, -1, -1, 4, -1}, 876 {-1, -1, -1, -1, -1, -1, -1, -1}, 877 {-1, -1, -1, -1, -1, -1, -1, -1}}, 878 {{-1, -1, -1, 6, 6, -1, -1, -1}, 879 {-1, 0, 4, 4, 4, 0, -1, -1}, 880 {-1, -1, -1, 6, 6, -1, -1, -1}, 881 {-1, -1, 2, 7, 2, -1, -1, -1}, 882 {-1, -1, -1, 6, 6, -1, -1, -1}, 883 {-1, 0, 5, 5, 5, 0, -1, -1}, 884 {-1, -1, -1, 3, 3, -1, -1, -1}, 885 {-1, -1, -1, -1, -1, -1, -1, -1}, 886 {-1, -1, -1, -1, -1, -1, -1, -1}, 887 {-1, -1, -1, -1, -1, -1, -1, -1}}, 888 {{-1, -1, 4, 1, 3, -1, -1, -1}, 889 {-1, 1, -1, -1, 1, -1, -1, -1}, 890 {-1, -1, 4, 1, 3, 4, 1, -1}, 891 {-1, 1, 3, 4, -1, -1, 4, -1}, 892 {-1, 3, -1, -1, 3, 4, 1, -1}, 893 {-1, 1, 3, 4, 1, 3, -1, -1}, 894 {-1, -1, 4, 1, -1, -1, -1, -1}, 895 {-1, -1, -1, -1, -1, -1, -1, -1}, 896 {-1, -1, -1, -1, -1, -1, -1, -1}, 897 {-1, -1, -1, -1, -1, -1, -1, -1}}, 898 {{-1, 6, 4, -1, 3, 2, 5, -1}, 899 { 0, -1, -1, -1, -1, -1, 1, -1}, 900 {-1, 2, 3, 5, -1, 4, 6, -1}, 901 { 0, -1, -1, -1, -1, -1, 1, -1}, 902 {-1, 4, 6, -1, 2, 5, 3, -1}, 903 { 0, -1, -1, -1, -1, -1, 1, -1}, 904 {-1, 5, 2, 3, -1, 4, 6, -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, 6, 6, -1, -1, -1}, 909 {-1, -1, 7, 6, 4, -1, -1, -1}, 910 {-1, 2, 1, 7, 4, 1, 3, -1}, 911 { 2, 1, 1, 1, 1, 1, 3, -1}, 912 {-1, 2, 2, 2, 3, 3, 3, -1}, 913 {-1, -1, -1, 5, -1, -1, -1, -1}, 914 {-1, -1, -1, 2, 3, -1, -1, -1}, 915 {-1, -1, -1, 5, -1, -1, -1, -1}, 916 {-1, -1, 2, 2, 3, 3, -1, -1}, 917 {-1, -1, -1, -1, -1, -1, -1, -1}}, 918 {{ 4, -1, 5, -1, -1, 3, -1, 6}, 919 { 2, -1, 3, -1, 2, -1, 4, -1}, 920 { 4, -1, -1, 1, 0, -1, -1, 6}, 921 { 6, -1, 2, 3, 5, -1, 4, -1}, 922 { 4, -1, -1, 0, 1, -1, -1, 6}, 923 { 2, -1, 5, -1, 3, -1, 4, -1}, 924 { 4, -1, 3, -1, -1, 2, -1, 6}, 925 { 6, -1, -1, -1, -1, -1, 4, -1}, 926 {-1, -1, -1, -1, -1, -1, -1, -1}, 927 {-1, -1, -1, -1, -1, -1, -1, -1}}, 928 {{ 2, 6, 0, 5, 5, 1, 3, 4}, 929 { 1, -1, -1, 2, -1, -1, 0, -1}, 930 { 4, -1, -1, 3, 6, -1, -1, 2}, 931 {-1, -1, -1, 0, -1, -1, -1, -1}, 932 {-1, -1, -1, 1, 4, -1, -1, -1}, 933 {-1, -1, -1, 2, -1, -1, -1, -1}, 934 {-1, -1, -1, 6, 3, -1, -1, -1}, 935 {-1, -1, -1, 5, -1, -1, -1, -1}, 936 {-1, -1, -1, 4, 1, -1, -1, -1}, 937 {-1, -1, -1, -1, -1, -1, -1, -1}}, 938 {{-1, -1, -1, -1, 5, 1, 1, 3}, 939 { 0, 5, 1, 0, 5, 3, 3, -1}, 940 { 5, 1, 0, 5, 1, 0, 5, 1}, 941 { 0, 5, 1, 0, 5, 1, 6, -1}, 942 {-1, -1, -1, -1, 1, 6, 5, 1}, 943 {-1, -1, -1, -1, 5, 1, 6, -1}, 944 {-1, -1, -1, -1, 1, 0, 5, 1}, 945 {-1, -1, -1, -1, 5, 1, 0, -1}, 946 {-1, -1, -1, -1, -1, -1, -1, -1}, 947 {-1, -1, -1, -1, -1, -1, -1, -1}}, 948 {{-1, 0, 7, 3, -1, -1, 2, 2}, 949 {-1, 0, 7, 3, -1, -1, 2, -1}, 950 {-1, 0, 7, 3, -1, -1, 2, 2}, 951 {-1, 0, 7, 3, -1, 3, 1, -1}, 952 {-1, 0, 7, 3, -1, 6, 4, 5}, 953 {-1, 0, 7, 3, -1, 7, 0, -1}, 954 {-1, 0, 7, 3, -1, 2, 3, 4}, 955 {-1, 0, 7, 3, -1, 5, 6, -1}, 956 {-1, -1, -1, -1, -1, 7, 0, 1}, 957 {-1, -1, -1, -1, -1, -1, -1, -1}}, 958 {{-1, -1, -1, 7, 7, 7, 7, -1}, 959 { 3, 4, 5, -1, -1, -1, 7, -1}, 960 { 2, -1, -1, -1, -1, -1, -1, 3}, 961 { 7, -1, -1, -1, -1, -1, 4, -1}, 962 { 7, -1, -1, -1, 3, 4, 5, 6}, 963 { 7, -1, -1, 2, 0, 1, 2, -1}, 964 { 6, -1, -1, -1, 3, 4, 5, 6}, 965 { 0, 1, -1, -1, -1, -1, -1, -1}, 966 { 2, 3, 4, -1, -1, -1, -1, -1}, 967 { 5, 6, 0, -1, -1, -1, -1, -1}}, 968 {{-1, 7, -1, -1, -1, -1, 2, -1}, 969 { 1, 1, -1, -1, -1, 3, 3, -1}, 970 {-1, 2, -1, -1, -1, -1, 4, -1}, 971 { 3, 3, -1, -1, -1, 5, 5, -1}, 972 {-1, 4, -1, -1, -1, -1, 6, -1}, 973 { 5, 5, -1, -1, -1, 1, 1, -1}, 974 {-1, 6, -1, -1, -1, -1, 7, -1}, 975 {-1, -1, -1, -1, -1, -1, -1, -1}, 976 {-1, -1, -1, -1, -1, -1, -1, -1}, 977 {-1, -1, -1, -1, -1, -1, -1, -1}}, 978 {{-1, 4, -1, -1, -1, -1, 4, -1}, 979 { 2, -1, -1, 1, -1, -1, 2, -1}, 980 { 5, -1, -1, 0, 0, -1, -1, 5}, 981 { 5, -1, -1, 1, -1, -1, 6, -1}, 982 {-1, 4, 2, 7, 7, 5, 4, -1}, 983 {-1, -1, -1, 6, -1, -1, -1, -1}, 984 {-1, -1, -1, 3, 3, -1, -1, -1}, 985 {-1, -1, -1, 7, -1, -1, -1, -1}, 986 {-1, -1, -1, -1, -1, -1, -1, -1}, 987 {-1, -1, -1, -1, -1, -1, -1, -1}}, 988 {{-1, 1, -1, -1, 2, 3, 4, -1}, 989 { 2, -1, -1, 3, 0, 4, -1, -1}, 990 { 4, -1, -1, 2, 3, 1, -1, -1}, 991 { 3, -1, 4, 3, 0, -1, -1, -1}, 992 { 4, -1, -1, 2, 5, 1, -1, -1}, 993 { 3, -1, 4, 5, 0, 4, -1, -1}, 994 {-1, -1, -1, -1, -1, -1, -1, -1}, 995 {-1, -1, -1, -1, -1, -1, -1, -1}, 996 {-1, -1, -1, -1, -1, -1, -1, -1}, 997 {-1, -1, -1, -1, -1, -1, -1, -1}}, 998 {{ 2, -1, -1, 1, 1, -1, -1, 2}, 999 { 2, -1, 3, 3, 3, -1, 2, -1}, 1000 {-1, 2, -1, 4, 4, -1, 2, -1}, 1001 {-1, 7, 7, 0, 7, 7, -1, -1}, 1002 {-1, -1, -1, 4, 4, -1, -1, -1}, 1003 {-1, -1, 5, 7, 5, -1, -1, -1}, 1004 { 6, 3, 2, 6, 4, 2, 3, 6}, 1005 { 5, -1, -1, -1, -1, -1, 1, -1}, 1006 {-1, -1, -1, -1, -1, -1, -1, -1}, 1007 {-1, -1, -1, -1, -1, -1, -1, -1}}, 1008 {{ 4, 2, 3, 5, 7, 1, 3, 6}, 1009 { 1, -1, -1, 1, -1, -1, 1, -1}, 1010 { 3, 0, 1, 3, 2, 4, 3, 5}, 1011 { 4, -1, -1, 4, -1, -1, 4, -1}, 1012 {-1, 5, -1, -1, 5, -1, -1, 5}, 1013 { 0, 3, 2, 0, 4, 5, 0, -1}, 1014 {-1, 6, -1, -1, 6, -1, -1, 6}, 1015 { 7, -1, -1, 7, -1, -1, 7, -1}, 1016 {-1, -1, -1, -1, -1, -1, -1, -1}, 1017 {-1, -1, -1, -1, -1, -1, -1, -1}}, 1018 {{-1, 5, 4, -1, 1, 1, -1, -1}, 1019 { 5, -1, 4, 1, -1, 1, -1, -1}, 1020 { 0, -1, -1, -1, -1, -1, 0, -1}, 1021 { 0, 6, 4, -1, -1, 4, 2, -1}, 1022 {-1, 4, 3, 5, 2, 6, 3, 6}, 1023 {-1, 2, 6, -1, -1, 5, 4, -1}, 1024 {-1, -1, -1, -1, -1, -1, -1, -1}, 1025 {-1, -1, -1, -1, -1, -1, -1, -1}, 1026 {-1, -1, -1, -1, -1, -1, -1, -1}, 1027 {-1, -1, -1, -1, -1, -1, -1, -1}}, 1028 {{-1, -1, -1, 6, 6, -1, -1, -1}, 1029 {-1, -1, 5, 5, 4, -1, -1, -1}, 1030 {-1, -1, 1, 6, 6, 4, -1, -1}, 1031 {-1, 1, 7, 2, 5, 3, -1, -1}, 1032 {-1, 2, 7, 2, 1, 5, 3, -1}, 1033 { 2, 1, 3, 1, 4, 2, 7, -1}, 1034 {-1, 3, 1, 3, 4, 2, 7, -1}, 1035 {-1, 3, 5, 5, 6, 6, -1, -1}, 1036 {-1, -1, -1, -1, -1, -1, -1, -1}, 1037 {-1, -1, -1, -1, -1, -1, -1, -1}}, 1038 {{-1, -1, 7, 3, -1, -1, -1, -1}, 1039 {-1, 1, 7, 6, -1, -1, -1, -1}, 1040 {-1, 3, 7, 5, 1, 5, -1, -1}, 1041 { 7, 7, 0, 2, 4, 0, 4, -1}, 1042 { 7, 1, 4, 6, 5, 6, 5, 7}, 1043 { 1, 7, 7, 1, 7, 7, 1, -1}, 1044 {-1, -1, -1, -1, -1, -1, -1, -1}, 1045 {-1, -1, -1, -1, -1, -1, -1, -1}, 1046 {-1, -1, -1, -1, -1, -1, -1, -1}, 1047 {-1, -1, -1, -1, -1, -1, -1, -1}}, 1048 {{-1, -1, 1, -1, -1, 1, -1, -1}, 1049 {-1, 5, 6, 1, 5, 6, -1, -1}, 1050 {-1, 1, 1, 2, 2, 1, 1, -1}, 1051 { 4, 7, 1, 0, 1, 7, 4, -1}, 1052 {-1, 3, 7, 5, 7, 5, 3, -1}, 1053 {-1, 1, 1, 1, 1, 1, -1, -1}, 1054 {-1, -1, -1, -1, -1, -1, -1, -1}, 1055 {-1, -1, -1, -1, -1, -1, -1, -1}, 1056 {-1, -1, -1, -1, -1, -1, -1, -1}, 1057 {-1, -1, -1, -1, -1, -1, -1, -1}}, 1058 {{ 4, -1, -1, -1, 5, -1, -1, 4}, 1059 { 6, 6, 7, 6, -1, 4, 5, -1}, 1060 { 4, 2, 7, 5, 2, 2, 6, 4}, 1061 {-1, -1, 4, 1, -1, 5, 2, -1}, 1062 {-1, 5, 2, 7, 7, -1, 7, 4}, 1063 { 4, 6, 5, 4, -1, 4, 2, -1}, 1064 {-1, -1, -1, 4, -1, 4, 1, -1}, 1065 { 0, 0, 0, 5, -1, -1, -1, -1}, 1066 {-1, -1, -1, -1, 0, 0, 0, 0}, 1067 {-1, -1, -1, -1, -1, -1, -1, -1}}, 1068 {{ 1, -1, -1, -1, 0, 0, -1, -1}, 1069 { 2, -1, -1, 0, 1, 0, -1, -1}, 1070 { 3, -1, -1, 0, 2, 2, 0, -1}, 1071 { 4, -1, 0, 1, 1, 1, 0, -1}, 1072 { 5, -1, -1, 0, 4, 4, 0, -1}, 1073 { 6, -1, -1, 4, 4, 4, -1, -1}, 1074 { 7, -1, -1, -1, 4, 4, -1, -1}, 1075 {-1, -1, -1, 0, 1, 0, -1, -1}, 1076 {-1, -1, -1, 0, 1, 1, 0, -1}, 1077 {-1, -1, -1, -1, -1, -1, -1, -1}}, 1078 {{-1, -1, 3, -1, -1, 1, 7, -1}, 1079 {-1, 7, 4, -1, -1, 4, 3, -1}, 1080 { 1, -1, -1, 0, 2, 0, -1, -1}, 1081 { 5, 4, -1, 3, -1, -1, -1, -1}, 1082 { 4, -1, 3, 6, 1, 1, 6, -1}, 1083 {-1, 1, -1, -1, 4, -1, 1, -1}, 1084 {-1, 7, 5, -1, -1, -1, 3, -1}, 1085 {-1, -1, 3, -1, -1, -1, -1, -1}, 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 { 2, -1, -1, -1, 2, -1, -1, -1}, 1090 {-1, 3, -1, -1, 3, 3, -1, -1}, 1091 {-1, 4, -1, 4, -1, 4, -1, -1}, 1092 {-1, 5, -1, -1, 5, 5, -1, -1}, 1093 { 6, -1, -1, 7, 1, 7, -1, -1}, 1094 { 7, -1, -1, -1, 6, 6, -1, -1}, 1095 {-1, -1, -1, -1, -1, -1, -1, -1}, 1096 {-1, -1, -1, -1, -1, -1, -1, -1}, 1097 {-1, -1, -1, -1, -1, -1, -1, -1}}, 1098 {{ 2, -1, -1, 6, -1, 2, 5, 1}, 1099 { 5, -1, 4, -1, 4, -1, 4, -1}, 1100 { 6, -1, -1, 3, -1, -1, -1, 3}, 1101 { 4, 2, 0, -1, -1, -1, 5, -1}, 1102 {-1, -1, -1, 6, -1, 3, 6, -1}, 1103 {-1, -1, 5, -1, 5, -1, -1, -1}, 1104 {-1, -1, -1, 3, -1, 4, 2, 5}, 1105 {-1, -1, -1, -1, -1, -1, -1, -1}, 1106 {-1, -1, -1, -1, -1, -1, -1, -1}, 1107 {-1, -1, -1, -1, -1, -1, -1, -1}}, 1108 {{ 6, -1, -1, -1, 4, -1, -1, 3}, 1109 { 0, 3, -1, -1, 6, -1, 0, -1}, 1110 {-1, -1, 7, -1, 1, -1, 3, -1}, 1111 { 7, -1, 4, 7, -1, 2, -1, -1}, 1112 { 5, 2, 3, 2, 1, 6, -1, 3}, 1113 {-1, -1, 0, 4, 3, 5, 4, -1}, 1114 {-1, 7, 6, -1, -1, 0, -1, -1}, 1115 { 4, 3, -1, -1, -1, 4, 2, -1}, 1116 { 0, -1, -1, -1, -1, -1, 6, -1}, 1117 {-1, -1, -1, -1, -1, -1, -1, -1}}, 1118 {{ 6, 1, 2, 5, 1, 6, 3, 0}, 1119 {-1, -1, -1, -1, -1, -1, 4, -1}, 1120 { 0, 5, 2, 7, 1, 6, 2, -1}, 1121 { 3, -1, -1, -1, -1, -1, -1, -1}, 1122 { 6, 7, 6, 4, 0, 5, 2, 6}, 1123 {-1, -1, -1, -1, -1, -1, 1, -1}, 1124 { 6, 1, 4, 0, 6, 2, 3, -1}, 1125 { 0, -1, -1, -1, -1, -1, -1, -1}, 1126 {-1, 0, 4, 5, 3, 7, 6, 0}, 1127 {-1, -1, -1, -1, -1, -1, -1, -1}}, 1128 {{-1, -1, -1, 0, 1, -1, -1, -1}, 1129 {-1, -1, 0, 7, 0, -1, -1, -1}, 1130 {-1, -1, 1, 2, 2, 0, -1, -1}, 1131 {-1, 0, 7, 0, 7, 0, -1, -1}, 1132 {-1, 6, -1, 7, 7, -1, 6, -1}, 1133 { 4, 1, 6, 6, 6, 4, 1, -1}, 1134 {-1, 5, -1, 7, 7, -1, 5, -1}, 1135 {-1, -1, -1, -1, -1, -1, -1, -1}, 1136 {-1, -1, -1, -1, -1, -1, -1, -1}, 1137 {-1, -1, -1, -1, -1, -1, -1, -1}}, 1138 {{-1, -1, -1, 5, 6, -1, -1, -1}, 1139 {-1, -1, 3, 3, 3, -1, -1, -1}, 1140 {-1, -1, 7, 5, 3, 7, -1, -1}, 1141 {-1, 3, -1, 6, -1, 3, -1, -1}, 1142 { 2, -1, -1, 3, 7, -1, -1, 1}, 1143 { 2, 2, -1, 3, -1, 1, 1, -1}, 1144 {-1, 0, 2, 5, 6, 1, 0, -1}, 1145 {-1, -1, -1, 3, -1, -1, -1, -1}, 1146 {-1, -1, -1, 3, 7, -1, -1, -1}, 1147 {-1, -1, -1, -1, -1, -1, -1, -1}}, 1148 {{-1, 6, -1, -1, -1, -1, 2, -1}, 1149 {-1, 2, 6, 0, 6, 0, -1, -1}, 1150 {-1, 0, -1, -1, -1, -1, -1, -1}, 1151 { 6, -1, -1, -1, -1, -1, -1, -1}, 1152 {-1, 3, 3, 2, 0, 6, 0, 0}, 1153 {-1, 6, -1, -1, -1, -1, 0, -1}, 1154 {-1, -1, -1, 6, 0, 2, 6, -1}, 1155 {-1, 2, 0, -1, -1, -1, -1, -1}, 1156 {-1, -1, -1, -1, -1, -1, -1, -1}, 1157 {-1, -1, -1, -1, -1, -1, -1, -1}}, 1158 {{ 0, 7, -1, -1, -1, -1, -1, -1}, 1159 { 1, 5, -1, -1, -1, -1, -1, -1}, 1160 { 7, 2, 5, -1, -1, -1, -1, -1}, 1161 { 6, 3, 4, -1, -1, -1, -1, -1}, 1162 { 5, 5, 4, 4, -1, -1, -1, -1}, 1163 { 3, 3, 5, 3, -1, -1, -1, -1}, 1164 { 1, 2, 2, 5, 3, -1, -1, -1}, 1165 { 1, 0, 0, 7, 6, -1, -1, -1}, 1166 { 3, 3, 5, 5, 7, 6, -1, -1}, 1167 {-1, -1, -1, -1, -1, -1, -1, -1}}, 1168 {{-1, -1, 2, 6, 6, 2, -1, -1}, 1169 {-1, 2, 1, 1, 0, 2, -1, -1}, 1170 {-1, 2, 3, 2, 2, 0, 2, -1}, 1171 { 2, 3, 2, 5, 2, 7, 2, -1}, 1172 { 2, 4, 2, 5, 2, 7, 2, 0}, 1173 { 2, 4, 2, 6, 6, 2, 0, -1}, 1174 {-1, 2, 5, 2, 2, 2, 7, 2}, 1175 {-1, 2, 5, 6, 6, 7, 2, -1}, 1176 {-1, -1, 2, 2, 2, 2, 2, -1}, 1177 {-1, -1, -1, -1, -1, -1, -1, -1}}, 1178 {{-1, -1, 0, -1, -1, 0, -1, -1}, 1179 { 1, 0, 0, 1, 0, 0, 1, -1}, 1180 { 1, 7, 7, 5, 5, 7, 7, 1}, 1181 { 3, 2, -1, 2, -1, 2, 3, -1}, 1182 { 3, 7, -1, 6, 6, -1, 7, 3}, 1183 { 7, -1, -1, 6, -1, -1, 7, -1}, 1184 { 4, 4, 5, -1, -1, 5, 4, 4}, 1185 {-1, -1, -1, -1, -1, -1, -1, -1}, 1186 {-1, -1, -1, -1, -1, -1, -1, -1}, 1187 {-1, -1, -1, -1, -1, -1, -1, -1}}, 1188 {{-1, 6, 3, -1, -1, 3, 6, -1}, 1189 { 6, -1, 2, -1, 2, -1, 6, -1}, 1190 { 2, -1, 0, 1, 1, 0, -1, 2}, 1191 { 5, 0, -1, 7, -1, 0, 5, -1}, 1192 {-1, 5, -1, 6, 6, -1, 5, -1}, 1193 { 7, 1, 4, -1, 4, 1, 7, -1}, 1194 { 7, -1, 4, -1, -1, 4, -1, 7}, 1195 { 2, 0, -1, -1, -1, 0, 2, -1}, 1196 {-1, 2, -1, -1, -1, -1, 2, -1}, 1197 {-1, -1, -1, -1, -1, -1, -1, -1}}, 1198 {{ 6, 1, -1, -1, -1, -1, 4, 0}, 1199 { 2, 7, 5, 5, 5, 7, 3, -1}, 1200 { 6, 1, -1, -1, -1, -1, 4, 0}, 1201 { 2, 5, 7, 7, 7, 5, 3, -1}, 1202 { 6, 1, -1, -1, -1, -1, 4, 0}, 1203 { 2, 0, 6, 6, 6, 0, 3, -1}, 1204 { 6, 1, -1, -1, -1, -1, 4, 0}, 1205 {-1, -1, -1, -1, -1, -1, -1, -1}, 1206 {-1, -1, -1, -1, -1, -1, -1, -1}, 1207 {-1, -1, -1, -1, -1, -1, -1, -1}}, 1208 {{ 5, -1, -1, 1, 1, -1, -1, 5}, 1209 { 5, -1, 4, -1, 4, -1, 5, -1}, 1210 {-1, 2, 4, -1, -1, 4, 2, -1}, 1211 { 7, 2, -1, -1, -1, 2, 7, -1}, 1212 { 0, -1, 0, 4, 4, 0, -1, 0}, 1213 { 7, 2, -1, -1, -1, 2, 7, -1}, 1214 {-1, 2, 3, -1, -1, 3, 2, -1}, 1215 { 5, -1, 3, -1, 3, -1, 5, -1}, 1216 { 5, -1, -1, 6, 6, -1, -1, 5}, 1217 {-1, -1, -1, -1, -1, -1, -1, -1}}, 1218 {{ 2, 2, -1, -1, -1, -1, 5, 5}, 1219 { 5, -1, -1, -1, -1, -1, 2, -1}, 1220 { 5, -1, -1, -1, -1, -1, -1, 2}, 1221 { 1, -1, 1, 5, 1, -1, 3, -1}, 1222 { 5, 2, 5, 3, 1, 2, 5, 2}, 1223 { 2, 0, 5, -1, 2, 0, 5, -1}, 1224 {-1, 3, 7, -1, -1, 3, 7, -1}, 1225 {-1, -1, 2, 0, 5, -1, -1, -1}, 1226 {-1, -1, -1, -1, -1, -1, -1, -1}, 1227 {-1, -1, -1, -1, -1, -1, -1, -1}}, 1228 {{ 0, 6, 5, 2, 3, 4, 1, 7}, 1229 {-1, -1, -1, -1, 1, -1, -1, -1}, 1230 {-1, -1, -1, 1, 1, -1, -1, -1}, 1231 {-1, -1, 1, -1, -1, -1, -1, -1}, 1232 { 7, 1, 4, 3, 2, 5, 6, 0}, 1233 {-1, -1, -1, -1, 1, -1, -1, -1}, 1234 {-1, -1, -1, 1, 1, -1, -1, -1}, 1235 {-1, -1, 1, -1, -1, -1, -1, -1}, 1236 { 0, 6, 5, 2, 3, 4, 1, 7}, 1237 {-1, -1, -1, -1, -1, -1, -1, -1}}, 1238 {{-1, -1, 1, -1, -1, 1, -1, -1}, 1239 {-1, 2, 4, -1, 2, 4, -1, -1}, 1240 {-1, 2, 3, 6, 5, 3, 2, -1}, 1241 {-1, 6, 5, -1, 6, 5, -1, -1}, 1242 {-1, -1, -1, 7, 7, -1, -1, -1}, 1243 {-1, -1, -1, 7, -1, -1, -1, -1}, 1244 { 1, -1, -1, 7, 7, -1, -1, 3}, 1245 { 2, -1, -1, 7, -1, -1, 2, -1}, 1246 {-1, 3, 4, 5, 6, 4, 1, -1}, 1247 {-1, -1, -1, -1, -1, -1, -1, -1}}, 1248 {{ 1, -1, -1, 2, 2, -1, -1, 2}, 1249 { 1, 3, 7, 3, 7, 4, 2, -1}, 1250 {-1, 1, 6, -1, -1, 6, 2, -1}, 1251 { 6, -1, 7, 3, 7, -1, 6, -1}, 1252 {-1, 4, 2, -1, -1, 1, 3, -1}, 1253 {-1, -1, 2, 6, 1, -1, -1, -1}, 1254 {-1, 4, 3, 3, 4, 4, 3, -1}, 1255 {-1, -1, -1, -1, -1, -1, -1, -1}, 1256 {-1, -1, -1, -1, -1, -1, -1, -1}, 1257 {-1, -1, -1, -1, -1, -1, -1, -1}}, 1258 {{-1, -1, -1, 5, 6, -1, -1, -1}, 1259 {-1, -1, -1, 3, -1, -1, -1, -1}, 1260 {-1, -1, -1, 1, 2, -1, -1, -1}, 1261 {-1, -1, -1, 4, -1, -1, -1, -1}, 1262 {-1, -1, -1, 5, 7, -1, -1, -1}, 1263 {-1, -1, -1, 2, -1, -1, -1, -1}, 1264 { 6, 5, 4, 3, 2, 1, 7, 5}, 1265 {-1, -1, -1, -1, -1, -1, -1, -1}, 1266 {-1, -1, -1, -1, -1, -1, -1, -1}, 1267 {-1, -1, -1, -1, -1, -1, -1, -1}}, 1268 {{-1, 0, -1, 1, -1, 2, -1, -1}, 1269 {-1, 4, -1, 5, -1, 6, -1, -1}, 1270 {-1, 7, -1, 0, -1, 2, -1, -1}, 1271 {-1, 6, -1, 3, -1, 6, -1, -1}, 1272 {-1, 1, -1, 1, -1, 2, -1, -1}, 1273 {-1, 3, -1, 5, -1, 0, -1, -1}, 1274 {-1, 2, -1, 4, -1, 6, -1, -1}, 1275 {-1, 3, -1, 6, -1, 7, -1, -1}, 1276 {-1, -1, -1, -1, -1, -1, -1, -1}, 1277 {-1, -1, -1, -1, -1, -1, -1, -1}}, 1278 {{ 1, 1, 2, 2, 3, 3, 4, 4}, 1279 { 5, 5, 6, 7, 6, 5, 5, -1}, 1280 { 6, 4, 3, 3, 2, 2, 1, 6}, 1281 { 4, 6, 5, 7, 6, 3, 1, -1}, 1282 {-1, -1, -1, -1, -1, -1, -1, -1}, 1283 {-1, -1, -1, -1, -1, -1, -1, -1}, 1284 {-1, -1, -1, -1, -1, -1, -1, -1}, 1285 {-1, -1, -1, -1, -1, -1, -1, -1}, 1286 {-1, -1, -1, -1, -1, -1, -1, -1}, 1287 {-1, -1, -1, -1, -1, -1, -1, -1}}, 1288 {{ 7, 4, -1, 1, 2, -1, 4, 7}, 1289 { 5, 5, -1, 2, -1, 4, 4, -1}, 1290 {-1, 5, -1, 7, 7, -1, 4, -1}, 1291 { 1, 0, 6, 7, 6, 0, 2, -1}, 1292 {-1, 2, -1, 5, 3, -1, 1, -1}, 1293 { 1, 1, -1, -1, -1, 2, 2, -1}, 1294 { 6, 1, 4, -1, -1, 4, 2, 6}, 1295 { 5, 3, -1, -1, -1, 3, 5, -1}, 1296 {-1, -1, -1, -1, -1, -1, -1, -1}, 1297 {-1, -1, -1, -1, -1, -1, -1, -1}}, 1298 {{ 1, 5, 1, 0, 0, 1, 5, 1}, 1299 { 1, 2, 5, -1, 5, 2, 1, -1}, 1300 { 3, 6, 1, 2, 2, 1, 6, 3}, 1301 { 4, 3, 4, -1, 4, 3, 4, -1}, 1302 { 3, 4, 6, 5, 5, 6, 4, 3}, 1303 { 0, 2, 3, -1, 3, 2, 0, -1}, 1304 { 2, 3, 1, 5, 5, 1, 3, 2}, 1305 {-1, -1, -1, -1, -1, -1, -1, -1}, 1306 {-1, -1, -1, -1, -1, -1, -1, -1}, 1307 {-1, -1, -1, -1, -1, -1, -1, -1}}, 1308 {{ 3, 0, 2, 7, 5, 7, 6, 5}, 1309 { 6, -1, 1, -1, 2, -1, 1, -1}, 1310 {-1, 6, 4, 0, 3, 4, 5, -1}, 1311 {-1, 5, -1, 1, -1, 4, -1, -1}, 1312 {-1, 7, 3, 5, 6, 5, 3, -1}, 1313 { 1, -1, 2, -1, 4, -1, 2, -1}, 1314 { 6, 4, 4, 6, 6, 5, 5, 1}, 1315 {-1, -1, -1, -1, -1, -1, -1, -1}, 1316 {-1, -1, -1, -1, -1, -1, -1, -1}, 1317 {-1, -1, -1, -1, -1, -1, -1, -1}} 1318}; 1319 1320/* the tile struct 1321 * type is the bubble number 0-7 1322 * fallx is the x axis movement for the falling bubble 1323 * fallvel is the initial upward velocity for the falling bubble 1324 * ingroup denotes a bubble that is part of a group to be removed 1325 * anchored denotes a bubble that is anchored to the ceiling 1326 */ 1327struct tile { 1328 int type; 1329 int fallx; 1330 int fallvel; 1331 bool ingroup; 1332 bool anchored; 1333 bool delete; 1334}; 1335 1336/* the game context struct 1337 * score is the current score 1338 * level is the current level 1339 * angle is the current cannon direction 1340 * shots is the number of shots fired since last compression 1341 * compress is the height of the compressor 1342 * onboardcnt is the number of unique bubbles on the playing board 1343 * onboard is the unique bubbles on the playing board 1344 * nextinq is the pointer to the next bubble in the firing queue 1345 * queue is the circular buffer of bubbles to be fired 1346 * elapsedlvl is level elapsed time in 1/100s of seconds 1347 * elapsedshot is the shot elapsed time in 1/100s of seconds 1348 * startedshot is when the current shot began 1349 * playboard is the game playing board 1350 */ 1351struct game_context { 1352 unsigned int score; 1353 unsigned int level; 1354 int angle; 1355 int shots; 1356 int compress; 1357 int onboardcnt; 1358 int onboard[NUM_BUBBLES]; 1359 int nextinq; 1360 int queue[NUM_QUEUE]; 1361 long elapsedlvl; 1362 long elapsedshot; 1363 long startedshot; 1364 struct tile playboard[BB_HEIGHT][BB_WIDTH]; 1365}; 1366 1367static struct highscore highscores[NUM_SCORES]; 1368 1369/* used to denote available resume info */ 1370static bool resume = false; 1371static bool resume_file = false; 1372static unsigned int highlevel = 0; /* the highest level beaten */ 1373static unsigned int last_highlevel = 0; 1374 1375static void bubbles_init(struct game_context* bb); 1376static bool bubbles_nextlevel(struct game_context* bb); 1377static void bubbles_getonboard(struct game_context* bb); 1378static void bubbles_drawboard(struct game_context* bb); 1379static int bubbles_fire(struct game_context* bb); 1380static bool bubbles_collision(struct game_context* bb, int y, int x, 1381 int nearrow, int nearcol); 1382static bool bubbles_ingroup(struct game_context* bb, int row, int col); 1383static int bubbles_searchgroup(struct game_context* bb, int row, int col); 1384static int bubbles_remove(struct game_context* bb); 1385static void bubbles_anchored(struct game_context* bb, int row, int col); 1386static int bubbles_fall(struct game_context* bb); 1387static int bubbles_checklevel(struct game_context* bb); 1388static void bubbles_recordscore(struct game_context* bb); 1389static bool bubbles_loadgame(struct game_context* bb); 1390static void bubbles_savegame(struct game_context* bb); 1391static inline void bubbles_setcolors(void); 1392static void bubbles_callback(void* param); 1393static int bubbles_handlebuttons(struct game_context* bb, bool animblock, 1394 int timeout); 1395static int bubbles(struct game_context* bb); 1396 1397/***************************************************************************** 1398* bubbles_init() initializes bubbles data structures. 1399******************************************************************************/ 1400static void bubbles_init(struct game_context* bb) { 1401 bubbles_setcolors(); 1402 /* seed the rand generator */ 1403 rb->srand(*rb->current_tick); 1404 1405 /* check for resumed game */ 1406 if (resume) 1407 { 1408 resume = false; 1409 return; 1410 } 1411 1412 bb->score = 0; 1413 bubbles_nextlevel(bb); 1414} 1415 1416/***************************************************************************** 1417* bubbles_nextlevel() sets up the game for the next level, returns false if 1418* there are no more levels. 1419******************************************************************************/ 1420static bool bubbles_nextlevel(struct game_context* bb) { 1421 int i, j, pos; 1422 1423 bb->level++; 1424 1425 /* check if there are no more levels */ 1426 if(bb->level > NUM_LEVELS) return false; 1427 1428 /* save highest level */ 1429 if (bb->level-1 > highlevel) 1430 highlevel = bb->level-1; 1431 1432 /* set up the play board */ 1433 rb->memset(bb->playboard, 0, sizeof(bb->playboard)); 1434 for(i=0; i<BB_LEVEL_HEIGHT; i++) { 1435 for(j=0; j<BB_WIDTH; j++) { 1436 pos = (int)level[bb->level-1][i][j]; 1437 if(pos >=0 && pos < NUM_BUBBLES) { 1438 bb->playboard[i][j].type = pos; 1439 } else { 1440 bb->playboard[i][j].type = -1; 1441 } 1442 } 1443 } 1444 for(i=BB_LEVEL_HEIGHT; i<BB_HEIGHT; i++) { 1445 for(j=0; j<BB_WIDTH; j++) { 1446 bb->playboard[i][j].type = -1; 1447 } 1448 } 1449 1450 /* fill first bubbles in shot queue */ 1451 bubbles_getonboard(bb); 1452 for(i=0; i<NUM_QUEUE; i++) { 1453 bb->queue[i] = bb->onboard[rb->rand()%bb->onboardcnt]; 1454 } 1455 1456 bb->angle = 0; 1457 bb->shots = 0; 1458 bb->compress = 0; 1459 bb->nextinq = 0; 1460 bb->elapsedlvl = 0; 1461 bb->elapsedshot = 0; 1462 1463 return true; 1464} 1465 1466/***************************************************************************** 1467* bubbles_getonboard() determines which bubble types are on the play board. 1468******************************************************************************/ 1469static void bubbles_getonboard(struct game_context* bb) { 1470 int i, j, k; 1471 bool found; 1472 1473 bb->onboardcnt = 0; 1474 rb->memset(bb->onboard, -1, sizeof(bb->onboard)); 1475 1476 for(i=0; i<BB_HEIGHT; i++) { 1477 for(j=0; j<BB_WIDTH; j++) { 1478 if(bb->playboard[i][j].type >= 0) { 1479 found = false; 1480 1481 for(k=0; k<bb->onboardcnt; k++) { 1482 if(bb->playboard[i][j].type == bb->onboard[k]) { 1483 found = true; 1484 break; 1485 } 1486 } 1487 1488 if(!found) { 1489 bb->onboard[bb->onboardcnt] = bb->playboard[i][j].type; 1490 bb->onboardcnt++; 1491 } 1492 1493 if(bb->onboardcnt == NUM_BUBBLES) return; 1494 } 1495 } 1496 } 1497} 1498 1499/***************************************************************************** 1500* bubbles_drawboard() draws the game board to the buffer but does not update 1501* the lcd. 1502******************************************************************************/ 1503static void bubbles_drawboard(struct game_context* bb) { 1504 int i, j; 1505 int w1, w2, h; 1506 int colmax, indent; 1507 int tipx, tipy; 1508 bool evenline = false; 1509 char *level = "Level"; 1510 char *score = "Score"; 1511 char *next = "Next"; 1512 char *hurry = "HURRY!"; 1513 char str[11]; 1514 1515 /* clear screen */ 1516 rb->lcd_clear_display(); 1517#if ((LCD_HEIGHT >= 128) && (LCD_WIDTH <= 320)) || ((LCD_WIDTH == 132) && (LCD_HEIGHT == 80)) 1518 h = rb->font_get(FONT_SYSFIXED)->height + 1; 1519#elif (LCD_WIDTH == 640) && (LCD_HEIGHT == 480) 1520 h = rb->font_get(FONT_SYSFIXED)->height + 6; 1521#else 1522 int font = rb->screens[SCREEN_MAIN]->getuifont(); 1523 h = rb->font_get(font)->height + 1; 1524#endif 1525 /* draw background */ 1526#ifdef HAVE_LCD_COLOR 1527 rb->lcd_bitmap(bubbles_background, 0, 0, LCD_WIDTH, LCD_HEIGHT); 1528#endif 1529 1530 /* display play board */ 1531 for(i=0; i<BB_HEIGHT; i++) { 1532 colmax = BB_WIDTH; 1533 if(evenline) { 1534 colmax--; 1535 indent = ROW_INDENT; 1536 } else { 1537 indent = 0; 1538 } 1539 evenline = !evenline; 1540 1541 for(j=0; j<colmax; j++) { 1542 if(bb->playboard[i][j].type >= 0 && !bb->playboard[i][j].delete) { 1543 rb->lcd_bitmap_part(bubbles_emblem, 1544 0, EMBLEM_HEIGHT*bb->playboard[i][j].type, 1545 STRIDE( SCREEN_MAIN, 1546 BMPWIDTH_bubbles_emblem, BMPHEIGHT_bubbles_emblem), 1547 XOFS+indent+BUBBLE_WIDTH*j+(BUBBLE_WIDTH-EMBLEM_WIDTH)/2, 1548 YOFS+ROW_HEIGHT*i+(BUBBLE_HEIGHT-EMBLEM_HEIGHT)/2+bb->compress*ROW_HEIGHT, 1549 EMBLEM_WIDTH, EMBLEM_HEIGHT); 1550 rb->lcd_set_drawmode(DRMODE_FG); 1551 rb->lcd_mono_bitmap((const unsigned char *)bubbles_bubble, 1552 XOFS+indent+BUBBLE_WIDTH*j, 1553 YOFS+ROW_HEIGHT*i+bb->compress*ROW_HEIGHT, 1554 BUBBLE_WIDTH, BUBBLE_HEIGHT); 1555 rb->lcd_set_drawmode(DRMODE_SOLID); 1556 } 1557 } 1558 } 1559 1560 /* display bubble to be shot */ 1561 rb->lcd_bitmap_part(bubbles_emblem, 1562 0, EMBLEM_HEIGHT*bb->queue[bb->nextinq], 1563 STRIDE( SCREEN_MAIN, 1564 BMPWIDTH_bubbles_emblem, BMPHEIGHT_bubbles_emblem), 1565 SHOTX+(BUBBLE_WIDTH-EMBLEM_WIDTH)/2, 1566 SHOTY+(BUBBLE_HEIGHT-EMBLEM_HEIGHT)/2, 1567 EMBLEM_WIDTH, EMBLEM_HEIGHT); 1568 rb->lcd_set_drawmode(DRMODE_FG); 1569 rb->lcd_mono_bitmap((const unsigned char *)bubbles_bubble, 1570 SHOTX, SHOTY, 1571 BUBBLE_WIDTH, BUBBLE_HEIGHT); 1572 rb->lcd_set_drawmode(DRMODE_SOLID); 1573 1574 /* display next bubble to be shot */ 1575#ifndef NEXT_BB_X 1576 rb->lcd_bitmap_part(bubbles_emblem, 1577 0, EMBLEM_HEIGHT*bb->queue[(bb->nextinq+1)%NUM_QUEUE], 1578 STRIDE( SCREEN_MAIN, 1579 BMPWIDTH_bubbles_emblem, BMPHEIGHT_bubbles_emblem), 1580 XOFS/2-BUBBLE_WIDTH/2+(BUBBLE_WIDTH-EMBLEM_WIDTH)/2, 1581 SHOTY+(BUBBLE_HEIGHT-EMBLEM_HEIGHT)/2, 1582 EMBLEM_WIDTH, EMBLEM_HEIGHT); 1583 rb->lcd_set_drawmode(DRMODE_FG); 1584 rb->lcd_mono_bitmap((const unsigned char *)bubbles_bubble, 1585 XOFS/2-BUBBLE_WIDTH/2, SHOTY, 1586 BUBBLE_WIDTH, BUBBLE_HEIGHT); 1587 rb->lcd_set_drawmode(DRMODE_SOLID); 1588#else 1589 rb->lcd_bitmap_part(bubbles_emblem, 1590 0, EMBLEM_HEIGHT*bb->queue[(bb->nextinq+1)%NUM_QUEUE], 1591 STRIDE( SCREEN_MAIN, 1592 BMPWIDTH_bubbles_emblem, BMPHEIGHT_bubbles_emblem), 1593 NEXT_BB_X + NEXT_BB_WIDTH/2-BUBBLE_WIDTH/2+(BUBBLE_WIDTH-EMBLEM_WIDTH)/2, 1594 NEXT_BB_Y + (BUBBLE_HEIGHT-EMBLEM_HEIGHT)/2 + h, 1595 EMBLEM_WIDTH, EMBLEM_HEIGHT); 1596 rb->lcd_set_drawmode(DRMODE_FG); 1597 rb->lcd_mono_bitmap((const unsigned char *)bubbles_bubble, 1598 NEXT_BB_X + NEXT_BB_WIDTH/2-BUBBLE_WIDTH/2, NEXT_BB_Y + h, 1599 BUBBLE_WIDTH, BUBBLE_HEIGHT); 1600 rb->lcd_set_drawmode(DRMODE_SOLID); 1601#endif 1602 1603 /* draw bounding lines */ 1604#ifndef HAVE_LCD_COLOR 1605 rb->lcd_vline(XOFS-1, 0, LCD_HEIGHT); 1606 rb->lcd_vline(XOFS+BUBBLE_WIDTH*BB_WIDTH, 0, LCD_HEIGHT); 1607#endif 1608 rb->lcd_hline(XOFS, XOFS+BUBBLE_WIDTH*BB_WIDTH-1, YOFS+bb->compress*ROW_HEIGHT-1); 1609 rb->lcd_hline(XOFS, XOFS+BUBBLE_WIDTH*BB_WIDTH-1, 1610 YOFS+ROW_HEIGHT*(BB_HEIGHT-2)+BUBBLE_HEIGHT); 1611 1612 /* draw arrow */ 1613 tipx = SHOTX+BUBBLE_WIDTH/2+(((fp14_sin(bb->angle)>>4)*BUBBLE_WIDTH*3/2)>>10); 1614 tipy = SHOTY+BUBBLE_HEIGHT/2-(((fp14_cos(bb->angle)>>4)*BUBBLE_HEIGHT*3/2)>>10); 1615 1616 rb->lcd_drawline(SHOTX+BUBBLE_WIDTH/2+(((fp14_sin(bb->angle)>>4)*BUBBLE_WIDTH/2)>>10), 1617 SHOTY+BUBBLE_HEIGHT/2-(((fp14_cos(bb->angle)>>4)*BUBBLE_HEIGHT/2)>>10), 1618 tipx, tipy); 1619 xlcd_filltriangle(tipx, tipy, 1620 tipx+(((fp14_sin(bb->angle-135)>>4)*BUBBLE_WIDTH/3)>>10), 1621 tipy-(((fp14_cos(bb->angle-135)>>4)*BUBBLE_HEIGHT/3)>>10), 1622 tipx+(((fp14_sin(bb->angle+135)>>4)*BUBBLE_WIDTH/3)>>10), 1623 tipy-(((fp14_cos(bb->angle+135)>>4)*BUBBLE_HEIGHT/3)>>10)); 1624 1625 /* draw text */ 1626 rb->snprintf(str, 4, "%d", bb->level); 1627 rb->lcd_getstringsize(level, &w1, NULL); 1628 rb->lcd_getstringsize(str, &w2, NULL); 1629#ifndef LEVEL_TXT_X 1630 rb->lcd_putsxy(XOFS/2-w1/2, 2, level); 1631 rb->lcd_putsxy(XOFS/2-w2/2, 2+h, str); 1632#else 1633 rb->lcd_putsxy(LEVEL_TXT_X+(LEVEL_TXT_WIDTH/2-w1/2), LEVEL_TXT_Y, level); 1634 rb->lcd_putsxy(LEVEL_TXT_X+(LEVEL_TXT_WIDTH/2-w2/2), LEVEL_TXT_Y+h, str); 1635#endif 1636 1637 rb->snprintf(str, 10, "%d", bb->score); 1638 rb->lcd_getstringsize(score, &w1,NULL); 1639 rb->lcd_getstringsize(str, &w2, NULL); 1640#ifndef SCORE_TXT_X 1641 rb->lcd_putsxy(XOFS/2-w1/2, 29, score); 1642 rb->lcd_putsxy(XOFS/2-w2/2, 29+h, str); 1643#else 1644 rb->lcd_putsxy(SCORE_TXT_X+(SCORE_TXT_WIDTH/2-w1/2), SCORE_TXT_Y, score); 1645 rb->lcd_putsxy(SCORE_TXT_X+(SCORE_TXT_WIDTH/2-w2/2), SCORE_TXT_Y+h, str); 1646#endif 1647 1648 rb->lcd_getstringsize(next, &w1, NULL); 1649#ifndef NEXT_BB_X 1650 rb->lcd_putsxy(XOFS/2-w1/2, SHOTY-h, next); 1651#else 1652 rb->lcd_putsxy(NEXT_BB_X+(NEXT_BB_WIDTH/2-w1/2), NEXT_BB_Y, next); 1653#endif 1654 1655 1656 if(bb->elapsedshot >= (MAX_SHOTTIME*7)/10) { 1657 rb->lcd_getstringsize(hurry, &w1, &h); 1658 /* screen is too small for the message to be centered (Clip Zip) */ 1659 #if (LCD_WIDTH <= 96) 1660 rb->lcd_putsxy(LCD_WIDTH/2-w1/2+LCD_WIDTH/6, LCD_HEIGHT/2-h/2, hurry); 1661 #else 1662 rb->lcd_putsxy(LCD_WIDTH/2-w1/2, LCD_HEIGHT/2-h/2, hurry); 1663 #endif 1664 } 1665} 1666 1667/***************************************************************************** 1668* bubbles_fire() fires the current bubble, reloads the cannon, attaches 1669* bubble to playboard, removes appropriate bubbles, and advances the 1670* the compressor. 1671******************************************************************************/ 1672static int bubbles_fire(struct game_context* bb) { 1673 int bubblecur; 1674 long shotxinc, shotyinc; 1675 long shotxofs, shotyofs; 1676 int shotxdirec = 1; 1677 long tempxofs, tempyofs; 1678 int nearrow, nearcol; 1679 int lastrow = BB_HEIGHT-1; 1680 int lastcol = (BB_WIDTH-1)/2; 1681 int buttonres; 1682 long lasttick, currenttick; 1683 1684 /* get current bubble */ 1685 bubblecur = bb->queue[bb->nextinq]; 1686 shotxinc = ((fp14_sin(bb->angle)>>4)*BUBBLE_WIDTH)/3; 1687 shotyinc = ((-1*(fp14_cos(bb->angle)>>4))*BUBBLE_HEIGHT)/3; 1688 shotxofs = shotyofs = 0; 1689 1690 /* advance the queue */ 1691 bb->queue[bb->nextinq] = bb->onboard[rb->rand()%bb->onboardcnt]; 1692 bb->nextinq = (bb->nextinq+1)%NUM_QUEUE; 1693 bubbles_drawboard(bb); 1694 rb->lcd_update_rect(0, 0, XOFS, LCD_HEIGHT); 1695 1696 /* move the bubble across the play board */ 1697 lasttick = *rb->current_tick; 1698 1699 while(true) { 1700 /* move the bubble one step */ 1701 shotyofs += shotyinc; 1702 shotxofs += shotxinc*shotxdirec; 1703 1704 /* check for bounce off sides */ 1705 if(SHOTX+(shotxofs>>10) < XOFS) { 1706 shotxofs += 2*((XOFS<<10)-(((SHOTX)<<10)+shotxofs)); 1707 shotxdirec *= -1; 1708 } else if(SHOTX+(shotxofs>>10) > XOFS+(BB_WIDTH-1)*BUBBLE_WIDTH) { 1709 shotxofs -= 2*((((SHOTX)<<10)+shotxofs)- 1710 ((XOFS<<10)+(((BB_WIDTH-1)*BUBBLE_WIDTH)<<10))); 1711 shotxdirec *= -1; 1712 } 1713 1714 tempxofs = shotxofs>>10; 1715 tempyofs = shotyofs>>10; 1716 1717 /* display shot */ 1718 bubbles_drawboard(bb); 1719 rb->lcd_bitmap_part(bubbles_emblem, 0, EMBLEM_HEIGHT*bubblecur, 1720 STRIDE( SCREEN_MAIN, 1721 BMPWIDTH_bubbles_emblem, 1722 BMPHEIGHT_bubbles_emblem), 1723 SHOTX+tempxofs+(BUBBLE_WIDTH-EMBLEM_WIDTH)/2, 1724 SHOTY+tempyofs+(BUBBLE_HEIGHT-EMBLEM_HEIGHT)/2, 1725 EMBLEM_WIDTH, EMBLEM_HEIGHT); 1726 rb->lcd_set_drawmode(DRMODE_FG); 1727 rb->lcd_mono_bitmap((const unsigned char *)bubbles_bubble, 1728 SHOTX+tempxofs, SHOTY+tempyofs, 1729 BUBBLE_WIDTH, BUBBLE_HEIGHT); 1730 rb->lcd_set_drawmode(DRMODE_SOLID); 1731 rb->lcd_update_rect(XOFS, 0, BB_WIDTH*BUBBLE_WIDTH, LCD_HEIGHT); 1732 1733 /* find nearest position */ 1734 nearrow = ((SHOTY+tempyofs)- 1735 (YOFS+bb->compress*ROW_HEIGHT)+ 1736 (ROW_HEIGHT/2))/ROW_HEIGHT; 1737 if(nearrow >= BB_HEIGHT) nearrow = BB_HEIGHT-1; 1738 1739 if(nearrow%2) { /* odd row */ 1740 nearcol = ((SHOTX+tempxofs)- 1741 (XOFS+ROW_INDENT)+ 1742 (BUBBLE_WIDTH/2))/BUBBLE_WIDTH; 1743 if(nearcol >= BB_WIDTH-1) nearcol = BB_WIDTH-2; 1744 } else { /* even row */ 1745 nearcol = ((SHOTX+tempxofs)-XOFS+(BUBBLE_WIDTH/2))/BUBBLE_WIDTH; 1746 if(nearcol >= BB_WIDTH) nearcol = BB_WIDTH-1; 1747 } 1748 if(nearcol < 0) nearcol = 0; 1749 1750 /* if nearest position is occupied attach to last position */ 1751 if(bb->playboard[nearrow][nearcol].type >= 0) { 1752 bb->playboard[lastrow][lastcol].type = bubblecur; 1753 break; 1754 } 1755 1756 /* save last position */ 1757 lastrow = nearrow; 1758 lastcol = nearcol; 1759 1760 /* if collision with neighbor then attach shot */ 1761 if(bubbles_collision(bb, YOFS+SHOTY+tempyofs, SHOTX+tempxofs, 1762 nearrow, nearcol)) { 1763 bb->playboard[nearrow][nearcol].type = bubblecur; 1764 break; 1765 } 1766 1767 /* if at top then attach shot to the ceiling */ 1768 if(nearrow == 0 && SHOTY+tempyofs <= YOFS+bb->compress*ROW_HEIGHT) { 1769 bb->playboard[nearrow][nearcol].type = bubblecur; 1770 break; 1771 } 1772 1773 /* handle button events */ 1774 buttonres = bubbles_handlebuttons(bb, true, 0); 1775 if(buttonres != BB_NONE) return buttonres; 1776 1777 /* framerate limiting */ 1778 currenttick = *rb->current_tick; 1779 if(currenttick-lasttick < HZ/MAX_FPS) { 1780 rb->sleep((HZ/MAX_FPS)-(currenttick-lasttick)); 1781 } else { 1782 rb->yield(); 1783 } 1784 lasttick = currenttick; 1785 } 1786 1787 bubbles_drawboard(bb); 1788 rb->lcd_update(); 1789 1790 /* clear appropriate bubbles from playing board */ 1791 if(bubbles_ingroup(bb, lastrow, lastcol)) { 1792 buttonres = bubbles_remove(bb); 1793 if(buttonres != BB_NONE) return buttonres; 1794 } 1795 1796 /* update shots and compress amount */ 1797 bb->shots++; 1798 if(bb->shots >= NUM_COMPRESS) { 1799 bb->shots = 0; 1800 bb->compress++; 1801 } 1802 1803 return BB_NONE; 1804} 1805 1806/***************************************************************************** 1807* bubbles_collision() determines if a fired bubble has collided with another 1808* bubble. 1809******************************************************************************/ 1810static bool bubbles_collision(struct game_context* bb, int y, int x, 1811 int nearrow, int nearcol) { 1812 int nx, ny; 1813 int adj = nearrow%2; 1814 1815 /* check neighbors */ 1816 if(nearcol-1 >= 0) { 1817 if(bb->playboard[nearrow][nearcol-1].type >= 0) { 1818 nx = XOFS+(nearrow%2 ? ROW_INDENT : 0)+BUBBLE_WIDTH*(nearcol-1); 1819 ny = YOFS+ROW_HEIGHT*nearrow+bb->compress*ROW_HEIGHT; 1820 if((x-nx)*(x-nx)+(y-ny)*(y-ny) < MIN_DISTANCE) return true; 1821 } 1822 } 1823 1824 if(nearcol-1+adj >= 0) { 1825 if(nearrow-1 >= 0) { 1826 if(bb->playboard[nearrow-1][nearcol-1+adj].type >= 0) { 1827 nx = XOFS+((nearrow-1)%2 ? ROW_INDENT : 0)+ 1828 BUBBLE_WIDTH*(nearcol-1+adj); 1829 ny = YOFS+ROW_HEIGHT*(nearrow-1)+bb->compress*ROW_HEIGHT; 1830 if((x-nx)*(x-nx)+(y-ny)*(y-ny) < MIN_DISTANCE) return true; 1831 } 1832 } 1833 1834 if(nearrow+1 < BB_HEIGHT) { 1835 if(bb->playboard[nearrow+1][nearcol-1+adj].type >= 0) { 1836 nx = XOFS+((nearrow+1)%2 ? ROW_INDENT : 0)+ 1837 BUBBLE_WIDTH*(nearcol-1+adj); 1838 ny = YOFS+ROW_HEIGHT*(nearrow+1)+bb->compress*ROW_HEIGHT; 1839 if((x-nx)*(x-nx)+(y-ny)*(y-ny) < MIN_DISTANCE) return true; 1840 } 1841 } 1842 } 1843 1844 if(nearcol+adj >= 0) { 1845 if(nearrow-1 >= 0) { 1846 if(bb->playboard[nearrow-1][nearcol+adj].type >= 0) { 1847 nx = XOFS+((nearrow-1)%2 ? ROW_INDENT : 0)+ 1848 BUBBLE_WIDTH*(nearcol+adj); 1849 ny = YOFS+ROW_HEIGHT*(nearrow-1)+bb->compress*ROW_HEIGHT; 1850 if((x-nx)*(x-nx)+(y-ny)*(y-ny) < MIN_DISTANCE) return true; 1851 } 1852 } 1853 1854 if(nearrow+1 < BB_HEIGHT) { 1855 if(bb->playboard[nearrow+1][nearcol+adj].type >= 0) { 1856 nx = XOFS+((nearrow+1)%2 ? ROW_INDENT : 0)+ 1857 BUBBLE_WIDTH*(nearcol+adj); 1858 ny = YOFS+ROW_HEIGHT*(nearrow+1)+bb->compress*ROW_HEIGHT; 1859 if((x-nx)*(x-nx)+(y-ny)*(y-ny) < MIN_DISTANCE) return true; 1860 } 1861 } 1862 } 1863 1864 if(nearcol+1 < BB_WIDTH-adj) { 1865 if(bb->playboard[nearrow][nearcol+1].type >= 0) { 1866 nx = XOFS+(nearrow%2 ? ROW_INDENT : 0)+BUBBLE_WIDTH*(nearcol+1); 1867 ny = YOFS+ROW_HEIGHT*nearrow+bb->compress*ROW_HEIGHT; 1868 if((x-nx)*(x-nx)+(y-ny)*(y-ny) < MIN_DISTANCE) return true; 1869 } 1870 } 1871 1872 return false; 1873} 1874 1875/***************************************************************************** 1876* bubbles_ingroup() marks all bubbles that form the current group. 1877******************************************************************************/ 1878static bool bubbles_ingroup(struct game_context* bb, int row, int col) { 1879 int i, j; 1880 int count; 1881 1882 count = bubbles_searchgroup(bb, row, col); 1883 1884 /* unmark group if too small */ 1885 if(count < 3) { 1886 for(i=0; i<BB_HEIGHT; i++) { 1887 for(j=0; j<BB_WIDTH; j++) { 1888 bb->playboard[i][j].ingroup = false; 1889 } 1890 } 1891 1892 return false; 1893 } 1894 1895 return true; 1896} 1897 1898/***************************************************************************** 1899* bubbles_searchgroup() return the size of the group of bubbles of the same 1900* type that the current bubble belongs to. 1901******************************************************************************/ 1902static int bubbles_searchgroup(struct game_context* bb, int row, int col) { 1903 int i, adj; 1904 int myrow, mycol, mytype; 1905 int count = 0; 1906 1907 struct coord { 1908 int row; 1909 int col; 1910 } search[(2*BB_WIDTH-1)*(BB_HEIGHT/2)]; 1911 1912 /* search initial bubble */ 1913 bb->playboard[row][col].ingroup = true; 1914 search[count].row = row; 1915 search[count].col = col; 1916 count++; 1917 1918 /* breadth-first search neighbors */ 1919 for(i=0; i<count; i++) { 1920 myrow = search[i].row; 1921 mycol = search[i].col; 1922 mytype = bb->playboard[myrow][mycol].type; 1923 adj = myrow%2; 1924 1925 if(mycol-1 >= 0) { 1926 if(bb->playboard[myrow][mycol-1].type == mytype && 1927 !bb->playboard[myrow][mycol-1].ingroup) { 1928 bb->playboard[myrow][mycol-1].ingroup = true; 1929 search[count].row = myrow; 1930 search[count].col = mycol-1; 1931 count++; 1932 } 1933 } 1934 1935 if(mycol-1+adj >= 0) { 1936 if(myrow-1 >= 0) { 1937 if(bb->playboard[myrow-1][mycol-1+adj].type == mytype && 1938 !bb->playboard[myrow-1][mycol-1+adj].ingroup) { 1939 bb->playboard[myrow-1][mycol-1+adj].ingroup = true; 1940 search[count].row = myrow-1; 1941 search[count].col = mycol-1+adj; 1942 count++; 1943 } 1944 } 1945 1946 if(myrow+1 < BB_HEIGHT) { 1947 if(bb->playboard[myrow+1][mycol-1+adj].type == mytype && 1948 !bb->playboard[myrow+1][mycol-1+adj].ingroup) { 1949 bb->playboard[myrow+1][mycol-1+adj].ingroup = true; 1950 search[count].row = myrow+1; 1951 search[count].col = mycol-1+adj; 1952 count++; 1953 } 1954 } 1955 } 1956 1957 if(mycol+adj >= 0) { 1958 if(myrow-1 >= 0) { 1959 if(bb->playboard[myrow-1][mycol+adj].type == mytype && 1960 !bb->playboard[myrow-1][mycol+adj].ingroup) { 1961 bb->playboard[myrow-1][mycol+adj].ingroup = true; 1962 search[count].row = myrow-1; 1963 search[count].col = mycol+adj; 1964 count++; 1965 } 1966 } 1967 1968 if(myrow+1 < BB_HEIGHT) { 1969 if(bb->playboard[myrow+1][mycol+adj].type == mytype && 1970 !bb->playboard[myrow+1][mycol+adj].ingroup) { 1971 bb->playboard[myrow+1][mycol+adj].ingroup = true; 1972 search[count].row = myrow+1; 1973 search[count].col = mycol+adj; 1974 count++; 1975 } 1976 } 1977 } 1978 1979 if(mycol+1 < BB_WIDTH-adj) { 1980 if(bb->playboard[myrow][mycol+1].type == mytype && 1981 !bb->playboard[myrow][mycol+1].ingroup) { 1982 bb->playboard[myrow][mycol+1].ingroup = true; 1983 search[count].row = myrow; 1984 search[count].col = mycol+1; 1985 count++; 1986 } 1987 } 1988 } 1989 1990 return count; 1991} 1992 1993/***************************************************************************** 1994* bubbles_remove() removes all bubbles in the current group and all 1995* unanchored bubbles from the play board. 1996******************************************************************************/ 1997static int bubbles_remove(struct game_context* bb) { 1998 int i, j; 1999 int buttonres; 2000 2001 /* determine all anchored bubbles */ 2002 for(j=0; j<BB_WIDTH; j++) { 2003 if(bb->playboard[0][j].type >= 0 && !bb->playboard[0][j].ingroup) { 2004 bubbles_anchored(bb, 0, j); 2005 } 2006 } 2007 2008 /* mark bubbles to be deleted */ 2009 for(i=0; i<BB_HEIGHT; i++) { 2010 for(j=0; j<BB_WIDTH; j++) { 2011 if(bb->playboard[i][j].type >= 0 && 2012 (!bb->playboard[i][j].anchored || bb->playboard[i][j].ingroup)) { 2013 bb->playboard[i][j].delete = true; 2014 } 2015 } 2016 } 2017 2018 /* animate falling bubbles */ 2019 buttonres = bubbles_fall(bb); 2020 if(buttonres != BB_NONE) return buttonres; 2021 2022 /* remove bubbles */ 2023 for(i=0; i<BB_HEIGHT; i++) { 2024 for(j=0; j<BB_WIDTH; j++) { 2025 if(bb->playboard[i][j].delete) { 2026 bb->playboard[i][j].ingroup = false; 2027 bb->playboard[i][j].type = -1; 2028 bb->playboard[i][j].delete = false; 2029 } else { 2030 bb->playboard[i][j].anchored = false; 2031 } 2032 } 2033 } 2034 2035 bubbles_getonboard(bb); 2036 2037 return BB_NONE; 2038} 2039 2040/***************************************************************************** 2041* bubbles_anchored() marks all bubbles that are anchored in some way to the 2042* current bubble. 2043******************************************************************************/ 2044static void bubbles_anchored(struct game_context* bb, int row, int col) { 2045 int i, adj; 2046 int myrow, mycol; 2047 int count = 0; 2048 2049 struct coord { 2050 int row; 2051 int col; 2052 } search[(2*BB_WIDTH-1)*(BB_HEIGHT/2)]; 2053 2054 /* search initial bubble */ 2055 bb->playboard[row][col].anchored = true; 2056 search[count].row = row; 2057 search[count].col = col; 2058 count++; 2059 2060 /* breadth-first search neighbors */ 2061 for(i=0; i<count; i++) { 2062 myrow = search[i].row; 2063 mycol = search[i].col; 2064 adj = myrow%2; 2065 2066 if(mycol-1 >= 0) { 2067 if(bb->playboard[myrow][mycol-1].type >= 0 && 2068 !bb->playboard[myrow][mycol-1].ingroup && 2069 !bb->playboard[myrow][mycol-1].anchored) { 2070 bb->playboard[myrow][mycol-1].anchored = true; 2071 search[count].row = myrow; 2072 search[count].col = mycol-1; 2073 count++; 2074 } 2075 } 2076 2077 if(mycol-1+adj >= 0) { 2078 if(myrow-1 >= 0) { 2079 if(bb->playboard[myrow-1][mycol-1+adj].type >= 0 && 2080 !bb->playboard[myrow-1][mycol-1+adj].ingroup && 2081 !bb->playboard[myrow-1][mycol-1+adj].anchored) { 2082 bb->playboard[myrow-1][mycol-1+adj].anchored = true; 2083 search[count].row = myrow-1; 2084 search[count].col = mycol-1+adj; 2085 count++; 2086 } 2087 } 2088 2089 if(myrow+1 < BB_HEIGHT) { 2090 if(bb->playboard[myrow+1][mycol-1+adj].type >= 0 && 2091 !bb->playboard[myrow+1][mycol-1+adj].ingroup && 2092 !bb->playboard[myrow+1][mycol-1+adj].anchored) { 2093 bb->playboard[myrow+1][mycol-1+adj].anchored = true; 2094 search[count].row = myrow+1; 2095 search[count].col = mycol-1+adj; 2096 count++; 2097 } 2098 } 2099 } 2100 2101 if(mycol+adj >= 0) { 2102 if(myrow-1 >= 0) { 2103 if(bb->playboard[myrow-1][mycol+adj].type >= 0 && 2104 !bb->playboard[myrow-1][mycol+adj].ingroup && 2105 !bb->playboard[myrow-1][mycol+adj].anchored) { 2106 bb->playboard[myrow-1][mycol+adj].anchored = true; 2107 search[count].row = myrow-1; 2108 search[count].col = mycol+adj; 2109 count++; 2110 } 2111 } 2112 2113 if(myrow+1 < BB_HEIGHT) { 2114 if(bb->playboard[myrow+1][mycol+adj].type >= 0 && 2115 !bb->playboard[myrow+1][mycol+adj].ingroup && 2116 !bb->playboard[myrow+1][mycol+adj].anchored) { 2117 bb->playboard[myrow+1][mycol+adj].anchored = true; 2118 search[count].row = myrow+1; 2119 search[count].col = mycol+adj; 2120 count++; 2121 } 2122 } 2123 } 2124 2125 if(mycol+1 < BB_WIDTH-adj) { 2126 if(bb->playboard[myrow][mycol+1].type >= 0 && 2127 !bb->playboard[myrow][mycol+1].ingroup && 2128 !bb->playboard[myrow][mycol+1].anchored) { 2129 bb->playboard[myrow][mycol+1].anchored = true; 2130 search[count].row = myrow; 2131 search[count].col = mycol+1; 2132 count++; 2133 } 2134 } 2135 } 2136} 2137 2138/***************************************************************************** 2139* bubbles_fall() makes removed bubbles fall from the screen. 2140******************************************************************************/ 2141static int bubbles_fall(struct game_context* bb) { 2142 int i, j; 2143 int count; 2144 int indent; 2145 int xofs, yofs; 2146 int buttonres; 2147 bool onscreen; 2148 long lasttick, currenttick; 2149 2150 /* give all falling bubbles an x axis movement */ 2151 for(i=0; i<BB_HEIGHT; i++) { 2152 for(j=0; j<BB_WIDTH; j++) { 2153 if(bb->playboard[i][j].delete) { 2154 bb->playboard[i][j].fallx = rb->rand()%25 - 12; 2155 bb->playboard[i][j].fallvel = rb->rand()%5 + 6; 2156 } 2157 } 2158 } 2159 2160 /* draw bubbles falling off the screen 2161 * follows y=x^2-8x scaled to bubble size 2162 */ 2163 lasttick = *rb->current_tick; 2164 2165 for(count=1; ;count++) { 2166 onscreen = false; 2167 bubbles_drawboard(bb); 2168 2169 for(i=0; i<BB_HEIGHT; i++) { 2170 for(j=0; j<BB_WIDTH; j++) { 2171 if(bb->playboard[i][j].delete) { 2172 indent = (i%2 ? ROW_INDENT : 0); 2173 xofs = ((bb->playboard[i][j].fallx*count)*BUBBLE_WIDTH)/48; 2174 yofs = ((count*count - bb->playboard[i][j].fallvel*count)* 2175 BUBBLE_HEIGHT)/20; 2176 2177 /* draw bubble if it is still on the screen */ 2178 if(YOFS+ROW_HEIGHT*i+bb->compress*ROW_HEIGHT+yofs 2179 <= LCD_HEIGHT) { 2180 onscreen = true; 2181 2182 rb->lcd_bitmap_part(bubbles_emblem, 0, 2183 EMBLEM_HEIGHT*bb->playboard[i][j].type, 2184 STRIDE( SCREEN_MAIN, 2185 BMPWIDTH_bubbles_emblem, 2186 BMPHEIGHT_bubbles_emblem), 2187 XOFS+indent+BUBBLE_WIDTH*j+ 2188 (BUBBLE_WIDTH-EMBLEM_WIDTH)/2+xofs, 2189 YOFS+ROW_HEIGHT*i+(BUBBLE_HEIGHT-EMBLEM_HEIGHT)/2+ 2190 bb->compress*ROW_HEIGHT+yofs, 2191 EMBLEM_WIDTH, EMBLEM_HEIGHT); 2192 rb->lcd_set_drawmode(DRMODE_FG); 2193 rb->lcd_mono_bitmap( 2194 (const unsigned char *)bubbles_bubble, 2195 XOFS+indent+BUBBLE_WIDTH*j+xofs, 2196 YOFS+ROW_HEIGHT*i+bb->compress*ROW_HEIGHT+yofs, 2197 BUBBLE_WIDTH, BUBBLE_HEIGHT); 2198 rb->lcd_set_drawmode(DRMODE_SOLID); 2199 } 2200 } 2201 } 2202 } 2203 2204 rb->lcd_update(); 2205 2206 /* break out if all bubbles are off the screen */ 2207 if(!onscreen) break; 2208 2209 /* handle button events */ 2210 buttonres = bubbles_handlebuttons(bb, true, 0); 2211 if(buttonres != BB_NONE) return buttonres; 2212 2213 /* framerate limiting */ 2214 currenttick = *rb->current_tick; 2215 if(currenttick-lasttick < HZ/MAX_FPS) { 2216 rb->sleep((HZ/MAX_FPS)-(currenttick-lasttick)); 2217 } else { 2218 rb->yield(); 2219 } 2220 lasttick = currenttick; 2221 } 2222 2223 return BB_NONE; 2224} 2225 2226/***************************************************************************** 2227* bubbles_checklevel() checks the state of the playboard for a win or loss. 2228******************************************************************************/ 2229static int bubbles_checklevel(struct game_context* bb) { 2230 int i, j; 2231 int points; 2232 char str[13]; 2233 2234 bubbles_drawboard(bb); 2235 rb->lcd_update(); 2236 2237 /* check for bubbles below cut off point */ 2238 for(i=0; i<=bb->compress; i++) { 2239 for(j=0; j<BB_WIDTH; j++) { 2240 if(bb->playboard[BB_HEIGHT-1-i][j].type >= 0) return BB_LOSE; 2241 } 2242 } 2243 2244 /* check for bubbles above cut off point */ 2245 for(i=0; i<BB_HEIGHT-1-bb->compress; i++) { 2246 for(j=0; j<BB_WIDTH; j++) { 2247 if(bb->playboard[i][j].type >= 0) return BB_NONE; 2248 } 2249 } 2250 2251 /* level complete, record score */ 2252 points = 100 - bb->elapsedlvl/100; 2253 if(points > 0) { 2254 bb->score += points; 2255 } else { 2256 points = 0; 2257 } 2258 2259 rb->snprintf(str, 12, "%d points", points); 2260 rb->splash(HZ, str); 2261 2262 /* advance to the next level */ 2263 if(!bubbles_nextlevel(bb)) { 2264 return BB_WIN; 2265 } 2266 2267 bubbles_drawboard(bb); 2268 rb->lcd_update(); 2269 rb->snprintf(str, 12, "Level %d", bb->level); 2270 rb->splash(HZ, str); 2271 bubbles_drawboard(bb); 2272 rb->lcd_update(); 2273 2274 return BB_NONE; 2275} 2276 2277/***************************************************************************** 2278* bubbles_recordscore() inserts a high score into the high scores list and 2279* returns the high score position. 2280******************************************************************************/ 2281static void bubbles_recordscore(struct game_context* bb) { 2282 2283 int position; 2284 2285 position = highscore_update(bb->score, bb->level-1, "", 2286 highscores, NUM_SCORES); 2287 if (position != -1) 2288 { 2289 if (position == 0) 2290 rb->splash(HZ*2, "New High Score"); 2291 highscore_show(position, highscores, NUM_SCORES, true); 2292 } 2293} 2294 2295/***************************************************************************** 2296* bubbles_loaddata() loads highest level beaten. 2297******************************************************************************/ 2298static void bubbles_loaddata(void) { 2299 int fd; 2300 2301 last_highlevel = highlevel = 0; 2302 /* open data file */ 2303 fd = rb->open(DATA_FILE, O_RDONLY); 2304 if (fd < 0) return; 2305 2306 /* read in saved game */ 2307 if (rb->read(fd, &highlevel, sizeof(highlevel)) < (long)sizeof(highlevel)) 2308 { 2309 highlevel = 0; 2310 } 2311 if (highlevel >= NUM_LEVELS) 2312 highlevel = NUM_LEVELS-1; 2313 last_highlevel = highlevel; 2314 2315 rb->close(fd); 2316} 2317 2318/***************************************************************************** 2319* bubbles_savedata() saves the current game state. 2320******************************************************************************/ 2321static void bubbles_savedata(void) { 2322 int fd; 2323 2324 if (last_highlevel >= highlevel) /* no need to save */ 2325 return; 2326 2327 fd = rb->open(DATA_FILE, O_WRONLY|O_CREAT, 0666); 2328 if (fd < 0) return; 2329 2330 rb->write(fd, &highlevel, sizeof(highlevel)); 2331 2332 rb->close(fd); 2333} 2334 2335/***************************************************************************** 2336* bubbles_loadgame() loads the saved game and returns load success. 2337******************************************************************************/ 2338static bool bubbles_loadgame(struct game_context* bb) { 2339 int fd; 2340 2341 bool ret = true; 2342 /* open game file */ 2343 fd = rb->open(SAVE_FILE, O_RDONLY); 2344 if(fd < 0) return false; 2345 2346 /* read in saved game */ 2347 if(rb->read(fd, bb, sizeof(struct game_context)) 2348 < (long)sizeof(struct game_context)) 2349 { 2350 ret = false; 2351 } 2352 2353 rb->close(fd); 2354 2355 return ret; 2356} 2357 2358/***************************************************************************** 2359* bubbles_savegame() saves the current game state. 2360******************************************************************************/ 2361static void bubbles_savegame(struct game_context* bb) { 2362 int fd; 2363 2364 if (!resume) /* nothing to save */ 2365 return; 2366 /* write out the game state to the save file */ 2367 fd = rb->open(SAVE_FILE, O_WRONLY|O_CREAT, 0666); 2368 if (fd < 0) 2369 { 2370 rb->splash(HZ/2, "Failed to save game"); 2371 return; 2372 } 2373 if (rb->write(fd, bb, sizeof(struct game_context)) <= 0) 2374 { 2375 rb->splash(HZ/2, "Failed to save game"); 2376 } 2377 2378 rb->close(fd); 2379} 2380 2381/***************************************************************************** 2382* bubbles_setcolors() set the foreground and background colors. 2383******************************************************************************/ 2384static inline void bubbles_setcolors(void) { 2385#ifdef HAVE_LCD_COLOR 2386 rb->lcd_set_background(LCD_RGBPACK(181,181,222)); 2387 rb->lcd_set_foreground(LCD_BLACK); 2388#endif 2389} 2390 2391/***************************************************************************** 2392* bubbles_callback() is the default event handler callback which is called 2393* on usb connect and shutdown. 2394******************************************************************************/ 2395static void bubbles_callback(void* param) { 2396 (void) param; 2397 highscore_save(SCORE_FILE, highscores, NUM_SCORES); 2398} 2399 2400/***************************************************************************** 2401* bubbles_handlebuttons() handles button events during a game. 2402******************************************************************************/ 2403static int bubbles_handlebuttons(struct game_context* bb, bool animblock, 2404 int timeout) { 2405 int button; 2406 int buttonres; 2407 long start; 2408 const struct button_mapping *plugin_contexts[] 2409 = { pla_main_ctx, 2410#ifdef HAVE_REMOTE_LCD 2411 pla_remote_ctx, 2412#endif 2413 }; 2414 2415 if (timeout < 0) 2416 timeout = 0; 2417 button = pluginlib_getaction(timeout,plugin_contexts,ARRAYLEN(plugin_contexts)); 2418#if defined(HAS_BUTTON_HOLD) && !defined(HAVE_REMOTE_LCD_AS_MAIN) 2419 /* FIXME: Should probably check remote hold here */ 2420 if (rb->button_hold()) 2421 button = BUBBLES_PAUSE; 2422#endif 2423 2424 switch(button){ 2425 case BUBBLES_LEFT_REP: 2426 if(bb->angle > MIN_ANGLE) bb->angle -= ANGLE_STEP_REP; 2427 break; 2428 case BUBBLES_LEFT: /* change angle to the left */ 2429 if(bb->angle > MIN_ANGLE) bb->angle -= ANGLE_STEP; 2430 break; 2431 2432 case BUBBLES_RIGHT_REP: 2433 if(bb->angle < MAX_ANGLE) bb->angle += ANGLE_STEP_REP; 2434 break; 2435 case BUBBLES_RIGHT: /* change angle to the right */ 2436 if(bb->angle < MAX_ANGLE) bb->angle += ANGLE_STEP; 2437 break; 2438 2439 case BUBBLES_FIRE: /* fire the shot */ 2440 case BUBBLES_FIRE_REPEAT: 2441 if(!animblock) { 2442 bb->elapsedlvl += bb->elapsedshot; 2443 bb->elapsedshot = 0; 2444 buttonres = bubbles_fire(bb); 2445 if(buttonres != BB_NONE) return buttonres; 2446 buttonres = bubbles_checklevel(bb); 2447 if(buttonres != BB_NONE) return buttonres; 2448 bb->startedshot = *rb->current_tick; 2449 } 2450 break; 2451 2452 case BUBBLES_PAUSE: /* pause the game */ 2453 start = *rb->current_tick; 2454 rb->splash(0, "Paused"); 2455 2456 while(pluginlib_getaction(TIMEOUT_BLOCK,plugin_contexts, 2457 ARRAYLEN(plugin_contexts)) 2458 != BUBBLES_PAUSE); 2459 bb->startedshot += *rb->current_tick-start; 2460 bubbles_drawboard(bb); 2461 rb->lcd_update(); 2462 break; 2463 2464 case BUBBLES_QUIT1: 2465 case BUBBLES_QUIT2: /* end the game */ 2466 if(!animblock) { 2467 resume = true; 2468 return BB_END; 2469 } 2470 break; 2471 2472 case ACTION_UNKNOWN: 2473 case ACTION_NONE: /* no button pressed */ 2474 break; 2475 2476 default: 2477 if(rb->default_event_handler_ex(button, bubbles_callback, 2478 (void*) bb) == SYS_USB_CONNECTED) 2479 return BB_USB; 2480 break; 2481 } 2482 2483 return BB_NONE; 2484} 2485 2486static int bubbles_menu_cb(int action, 2487 const struct menu_item_ex *this_item, 2488 struct gui_synclist *this_list) 2489{ 2490 (void)this_list; 2491 int i = ((intptr_t)this_item); 2492 if(action == ACTION_REQUEST_MENUITEM 2493 && !resume && (i==0)) 2494 return ACTION_EXIT_MENUITEM; 2495 return action; 2496} 2497 2498/***************************************************************************** 2499* bubbles_menu() is the initial menu at the start of the game. 2500******************************************************************************/ 2501static int bubbles_menu(struct game_context* bb) { 2502 static unsigned int startlevel = 0; 2503 int selected = 0; 2504 bool startgame = false; 2505 2506 MENUITEM_STRINGLIST(menu,"Bubbles Menu",bubbles_menu_cb, 2507 "Resume Game", "Start New Game", 2508 "Level", "High Scores", "Playback Control", 2509 "Quit without Saving", "Quit"); 2510 2511 while(!startgame){ 2512 switch (rb->do_menu(&menu, &selected, NULL, false)) 2513 { 2514 case 0: /* resume game */ 2515 startgame = true; 2516 if(resume_file) 2517 rb->remove(SAVE_FILE); 2518 resume_file = false; 2519 break; 2520 case 1: /* new game */ 2521 bb->level = startlevel; 2522 startgame = true; 2523 resume = false; 2524 resume_file = false; 2525 break; 2526 case 2: /* choose level */ 2527 startlevel++; 2528 rb->set_int("Choose start level", "", UNIT_INT, &startlevel, 2529 NULL, 1, 1, highlevel+1, NULL); 2530 startlevel--; 2531 break; 2532 case 3: /* High scores */ 2533 highscore_show(-1, highscores, NUM_SCORES, true); 2534 break; 2535 case 4: /* Playback Control */ 2536 playback_control(NULL); 2537 break; 2538 case 5: /* quit but don't save */ 2539 return BB_QUIT_WITHOUT_SAVING; 2540 case 6: /* save and quit */ 2541 return BB_QUIT; 2542 case MENU_ATTACHED_USB: 2543 bubbles_callback(bb); 2544 return BB_USB; 2545 } 2546 } 2547 return 0; 2548} 2549 2550/***************************************************************************** 2551* bubbles() is the main game subroutine, it returns the final game status. 2552******************************************************************************/ 2553static int bubbles(struct game_context* bb) { 2554 int buttonres; 2555 long timeout; 2556 2557 /******************** 2558 * menu * 2559 ********************/ 2560 buttonres = bubbles_menu(bb); 2561 if(buttonres != 0) 2562 return buttonres; 2563 2564 /******************** 2565 * init * 2566 ********************/ 2567 bubbles_init(bb); 2568 bubbles_drawboard(bb); 2569 rb->lcd_update(); 2570 2571 /********************** 2572 * play * 2573 **********************/ 2574 bb->startedshot = *rb->current_tick; 2575 2576 while(true) { 2577 /* refresh the board */ 2578 bubbles_drawboard(bb); 2579 rb->lcd_update(); 2580 2581 /* manange idle framerate */ 2582 bb->elapsedshot = *rb->current_tick-bb->startedshot; 2583 2584 if(MAX_SHOTTIME-bb->elapsedshot < HZ/2) { 2585 timeout = MAX_SHOTTIME-bb->elapsedshot; 2586 } else { 2587 timeout = HZ/2; 2588 } 2589 2590 /* handle button events */ 2591 buttonres = bubbles_handlebuttons(bb, false, timeout); 2592 if(buttonres != BB_NONE) return buttonres; 2593 2594 /* handle timing */ 2595 bb->elapsedshot = *rb->current_tick-bb->startedshot; 2596 2597 if(bb->elapsedshot > MAX_SHOTTIME) { 2598 bb->elapsedlvl += bb->elapsedshot; 2599 bb->elapsedshot = 0; 2600 buttonres = bubbles_fire(bb); 2601 if(buttonres != BB_NONE) return buttonres; 2602 buttonres = bubbles_checklevel(bb); 2603 if(buttonres != BB_NONE) return buttonres; 2604 bb->startedshot = *rb->current_tick; 2605 } 2606 } 2607} 2608 2609/***************************************************************************** 2610* plugin entry point. 2611******************************************************************************/ 2612enum plugin_status plugin_start(const void* parameter) { 2613 static struct game_context bb; 2614 bool exit = false; 2615 enum plugin_status ret = PLUGIN_OK; 2616 2617 (void)parameter; 2618 2619 /* load files */ 2620 resume = bubbles_loadgame(&bb); 2621 resume_file = resume; 2622 bubbles_loaddata(); 2623 highscore_load(SCORE_FILE, highscores, NUM_SCORES); 2624 rb->lcd_clear_display(); 2625 2626 /* start app */ 2627#if LCD_DEPTH > 1 2628 rb->lcd_set_backdrop(NULL); 2629#endif 2630 rb->lcd_setfont(FONT_SYSFIXED); 2631 2632 while(!exit) { 2633 switch(bubbles(&bb)){ 2634 case BB_WIN: 2635 rb->splash(HZ*2, "You Win!"); 2636 /* record high level */ 2637 highlevel = NUM_LEVELS-1; 2638 /* record high score */ 2639 bubbles_recordscore(&bb); 2640 break; 2641 2642 case BB_LOSE: 2643 resume = false; 2644 rb->splash(HZ*2, "Game Over"); 2645 /* record high score */ 2646 bubbles_recordscore(&bb); 2647 /* fall through to BB_END */ 2648 2649 case BB_END: 2650 break; 2651 2652 case BB_USB: 2653 ret = PLUGIN_USB_CONNECTED; 2654 exit = true; 2655 break; 2656 2657 case BB_QUIT: 2658 rb->splash(HZ/3, "Saving game data ..."); 2659 bubbles_savegame(&bb); 2660 bubbles_savedata(); 2661 highscore_save(SCORE_FILE, highscores, NUM_SCORES); 2662 /* fall through */ 2663 2664 case BB_QUIT_WITHOUT_SAVING: 2665 exit = true; 2666 break; 2667 2668 default: 2669 break; 2670 } 2671 } 2672 rb->lcd_setfont(FONT_UI); 2673 return ret; 2674}