rockbox/apps/plugins/bubbles.c
Shachar Liberman 5360df96ef accept patch FS#4761 - putting the player on hold will now pause games. this should be
fitted to pong and rockblox as well. credit Lukas Sabota for the initial work, and, my very
own first commit!


git-svn-id: svn://svn.rockbox.org/rockbox/trunk@10365 a1c6a512-1295-4272-9138-f99709370657
2006-07-30 03:10:09 +00:00

2717 lines
95 KiB
C
Executable file

/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2005 Adam Boot
*
* Color graphics from Frozen Bubble (http://www.frozen-bubble.org/)
*
* All files in this archive are subject to the GNU General Public License.
* See the file COPYING in the source tree root for full license agreement.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#include "plugin.h"
#include "xlcd.h"
#ifdef HAVE_LCD_BITMAP
PLUGIN_HEADER
/* files */
#define SCORE_FILE PLUGIN_DIR "/bubbles.score"
#define SAVE_FILE PLUGIN_DIR "/bubbles.save"
/* final game return status */
#define BB_NONE 5
#define BB_WIN 4
#define BB_END 3
#define BB_USB 2
#define BB_QUIT 1
#define BB_LOSE 0
/* play board dimension */
#define BB_HEIGHT 12
#define BB_WIDTH 8
#define BB_LEVEL_HEIGHT 10
/* various amounts */
#define NUM_SCORES 10
#define NUM_LEVELS 100
#define NUM_QUEUE 2
#define NUM_BUBBLES 8
#define MIN_ANGLE -76
#define MAX_ANGLE 76
#define NUM_COMPRESS 9
#define MAX_SHOTTIME 1000
/* button definitions */
#if (CONFIG_KEYPAD == IRIVER_H100_PAD) || (CONFIG_KEYPAD == IRIVER_H300_PAD)
#define BUBBLES_LEFT BUTTON_LEFT
#define BUBBLES_RIGHT BUTTON_RIGHT
#define BUBBLES_UP BUTTON_UP
#define BUBBLES_DOWN BUTTON_DOWN
#define BUBBLES_QUIT BUTTON_OFF
#define BUBBLES_START BUTTON_ON
#define BUBBLES_SELECT BUTTON_SELECT
#define BUBBLES_RESUME BUTTON_MODE
#define BUBBLES_RC_QUIT BUTTON_RC_STOP
#elif (CONFIG_KEYPAD == IPOD_3G_PAD) || (CONFIG_KEYPAD == IPOD_4G_PAD)
#define BUBBLES_LEFT BUTTON_SCROLL_BACK
#define BUBBLES_RIGHT BUTTON_SCROLL_FWD
#define BUBBLES_UP BUTTON_SCROLL_FWD
#define BUBBLES_DOWN BUTTON_SCROLL_BACK
#define BUBBLES_QUIT BUTTON_MENU|BUTTON_REL
#define BUBBLES_START BUTTON_PLAY|BUTTON_REL
#define BUBBLES_SELECT BUTTON_SELECT
#define BUBBLES_RESUME BUTTON_RIGHT|BUTTON_LEFT
#elif CONFIG_KEYPAD == IAUDIO_X5_PAD
#define BUBBLES_LEFT BUTTON_LEFT
#define BUBBLES_RIGHT BUTTON_RIGHT
#define BUBBLES_UP BUTTON_UP
#define BUBBLES_DOWN BUTTON_DOWN
#define BUBBLES_QUIT BUTTON_POWER
#define BUBBLES_START BUTTON_PLAY
#define BUBBLES_SELECT BUTTON_SELECT
#define BUBBLES_RESUME BUTTON_REC
#elif CONFIG_KEYPAD == GIGABEAT_PAD
#define BUBBLES_LEFT BUTTON_LEFT
#define BUBBLES_RIGHT BUTTON_RIGHT
#define BUBBLES_UP BUTTON_UP
#define BUBBLES_DOWN BUTTON_DOWN
#define BUBBLES_QUIT BUTTON_A
#define BUBBLES_START BUTTON_POWER
#define BUBBLES_SELECT BUTTON_SELECT
#define BUBBLES_RESUME BUTTON_MENU
#elif CONFIG_KEYPAD == RECORDER_PAD
#define BUBBLES_LEFT BUTTON_LEFT
#define BUBBLES_RIGHT BUTTON_RIGHT
#define BUBBLES_UP BUTTON_UP
#define BUBBLES_DOWN BUTTON_DOWN
#define BUBBLES_QUIT BUTTON_OFF
#define BUBBLES_START BUTTON_ON
#define BUBBLES_SELECT BUTTON_PLAY
#define BUBBLES_RESUME BUTTON_F1
#elif CONFIG_KEYPAD == ONDIO_PAD
#define BUBBLES_LEFT BUTTON_LEFT
#define BUBBLES_RIGHT BUTTON_RIGHT
#define BUBBLES_UP BUTTON_RIGHT
#define BUBBLES_DOWN BUTTON_LEFT
#define BUBBLES_QUIT BUTTON_OFF
#define BUBBLES_START BUTTON_MENU
#define BUBBLES_SELECT BUTTON_UP
#define BUBBLES_RESUME BUTTON_DOWN
#else
#error BUBBLES: Unsupported keypad
#endif
/* bubbles will consume height of 10*ROW_HEIGHT+2*(BUBBLE_HEIGHT-1)+BUBBLE_HEIGHT/2 */
/* 24x24 bubbles (iPod Video) */
#if (LCD_HEIGHT == 240) && (LCD_WIDTH == 320)
#define BUBBLE_WIDTH 22
#define BUBBLE_HEIGHT 22
#define EMBLEM_WIDTH 16
#define EMBLEM_HEIGHT 16
#define XOFS 72
#define ROW_HEIGHT 18
#define ROW_INDENT 11
#define MAX_FPS 40
/* 16x16 bubbles (H300, iPod Color) */
#elif (LCD_HEIGHT == 176) && (LCD_WIDTH == 220)
#define BUBBLE_WIDTH 16
#define BUBBLE_HEIGHT 16
#define EMBLEM_WIDTH 12
#define EMBLEM_HEIGHT 12
#define XOFS 46
#define ROW_HEIGHT 14
#define ROW_INDENT 8
#define MAX_FPS 30
/* 16x16 bubbles (Gigabeat) */
#elif (LCD_HEIGHT == 320) && (LCD_WIDTH == 240)
#define BUBBLE_WIDTH 16
#define BUBBLE_HEIGHT 16
#define EMBLEM_WIDTH 12
#define EMBLEM_HEIGHT 12
#define XOFS 56
#define ROW_HEIGHT 14
#define ROW_INDENT 8
#define MAX_FPS 20
/* 12x12 bubbles (iPod Nano) */
#elif (LCD_HEIGHT == 132) && (LCD_WIDTH == 176)
#define BUBBLE_WIDTH 12
#define BUBBLE_HEIGHT 12
#define EMBLEM_WIDTH 8
#define EMBLEM_HEIGHT 8
#define XOFS 40
#define ROW_HEIGHT 10
#define ROW_INDENT 6
#define MAX_FPS 40
/* 12x12 bubbles (H100, iAudio X5, iPod 3G, iPod 4G grayscale) */
#elif (LCD_HEIGHT == 128) && (LCD_WIDTH == 160)
#define BUBBLE_WIDTH 12
#define BUBBLE_HEIGHT 12
#define EMBLEM_WIDTH 8
#define EMBLEM_HEIGHT 8
#define XOFS 33
#define ROW_HEIGHT 10
#define ROW_INDENT 6
#define MAX_FPS 30
/* 10x10 bubbles (iPod Mini) */
#elif (LCD_HEIGHT == 110) && (LCD_WIDTH == 138)
#define BUBBLE_WIDTH 10
#define BUBBLE_HEIGHT 10
#define EMBLEM_WIDTH 6
#define EMBLEM_HEIGHT 6
#define XOFS 33
#define ROW_HEIGHT 8
#define ROW_INDENT 5
#define MAX_FPS 30
/* 8x7 bubbles (Archos recorder, Ondio) */
#elif (LCD_HEIGHT == 64) && (LCD_WIDTH == 112)
#define BUBBLE_WIDTH 8
#define BUBBLE_HEIGHT 7
#define EMBLEM_WIDTH 7
#define EMBLEM_HEIGHT 5
#define XOFS 33
#define ROW_HEIGHT 5
#define ROW_INDENT 4
#define MAX_FPS 20
#else
#error BUBBLES: Unsupported LCD type
#endif
#define TEXT_LINES (LCD_HEIGHT/8)
/* shot position */
#define SHOTX XOFS+ROW_INDENT+BUBBLE_WIDTH*3
#define SHOTY ROW_HEIGHT*(BB_HEIGHT-1)+BUBBLE_HEIGHT/2
/* collision distance squared */
#define MIN_DISTANCE ((BUBBLE_WIDTH*8)/10)*((BUBBLE_HEIGHT*8)/10)
/* external bitmaps */
extern const fb_data bubbles_bubble[];
extern const fb_data bubbles_emblem[];
#ifdef HAVE_LCD_COLOR
extern const fb_data bubbles_left[];
extern const fb_data bubbles_right[];
#endif
/* global rockbox api */
static struct plugin_api* rb;
/* levels */
char level[NUM_LEVELS][BB_LEVEL_HEIGHT][BB_WIDTH] = {
{{ 6, 6, 4, 4, 2, 2, 3, 3},
{ 6, 6, 4, 4, 2, 2, 3, -1},
{ 2, 2, 3, 3, 6, 6, 4, 4},
{ 2, 3, 3, 6, 6, 4, 4, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{-1, 7, 7, 7, 7, 7, 7, -1},
{-1, 1, 1, 1, 1, 1, -1, -1},
{-1, -1, 2, 2, 2, 2, -1, -1},
{-1, -1, -1, 2, -1, -1, -1, -1},
{-1, -1, -1, 2, 2, -1, -1, -1},
{-1, -1, -1, 5, -1, -1, -1, -1},
{-1, -1, -1, 5, 5, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{-1, -1, 7, -1, -1, 7, -1, -1},
{-1, -1, 7, 1, 7, -1, -1, -1},
{-1, -1, -1, 1, 2, -1, -1, -1},
{-1, -1, 1, 2, 1, -1, -1, -1},
{-1, -1, -1, 2, 5, -1, -1, -1},
{-1, -1, 3, 5, 3, -1, -1, -1},
{-1, -1, -1, 5, 3, -1, -1, -1},
{-1, -1, -1, 3, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{-1, -1, -1, 0, 0, -1, -1, -1},
{-1, -1, 5, 0, 1, -1, -1, -1},
{-1, -1, 3, 5, 1, 6, -1, -1},
{-1, 4, 3, -1, 6, 7, -1, -1},
{-1, 7, 4, -1, -1, 7, 4, -1},
{ 6, 7, -1, -1, -1, 4, 3, -1},
{ 1, 6, -1, -1, -1, -1, 3, 5},
{ 1, -1, -1, -1, -1, -1, 5, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{-1, -1, 0, 0, 0, 0, -1, -1},
{-1, 0, 1, 1, 1, 0, -1, -1},
{-1, 0, 1, 0, 0, 1, 0, -1},
{-1, 0, 1, 1, 1, 0, -1, -1},
{-1, -1, 0, 0, 0, 0, -1, -1},
{-1, -1, 7, -1, 7, -1, -1, -1},
{-1, -1, 7, 7, 7, 7, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{-1, 4, 4, 4, 6, 6, 6, -1},
{ 4, -1, -1, -1, -1, -1, 6, -1},
{-1, 4, -1, -1, -1, -1, 6, -1},
{ 4, 2, 3, 1, 2, 3, 6, -1},
{-1, 3, 1, 2, 3, 1, 2, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{-1, 4, 4, 4, 6, 6, 6, -1},
{ 4, -1, -1, -1, -1, -1, 6, -1},
{-1, 4, -1, -1, -1, -1, 6, -1},
{ 4, 2, 3, 1, 2, 3, 6, -1},
{-1, 3, 1, 2, 3, 1, 2, -1},
{-1, 2, 3, 1, 2, 3, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{-1, 0, 0, -1, -1, 2, 2, -1},
{-1, 5, -1, -1, -1, 3, -1, -1},
{-1, 0, -1, -1, -1, 6, -1, -1},
{-1, 3, -1, -1, -1, 0, -1, -1},
{-1, 4, -1, -1, -1, 5, -1, -1},
{-1, 2, -1, -1, -1, 3, -1, -1},
{-1, 2, -1, -1, -1, 1, -1, -1},
{-1, 3, -1, -1, -1, 4, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{ 3, -1, -1, -1, -1, -1, -1, 3},
{ 6, 3, 2, 4, 6, 3, 2, -1},
{ 4, -1, -1, -1, -1, -1, -1, 4},
{ 2, 4, 6, 3, 2, 4, 6, -1},
{-1, -1, -1, 6, -1, -1, -1, -1},
{-1, -1, -1, 3, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{-1, 2, -1, 1, -1, 1, -1, 2},
{ 1, 2, -1, 2, 1, -1, 1, -1},
{ 1, -1, 1, -1, 2, -1, 2, -1},
{ 2, 1, -1, 1, 2, -1, 2, -1},
{-1, 2, -1, 2, -1, 2, -1, 2},
{ 1, 2, -1, 2, 1, -1, 1, -1},
{ 1, -1, 1, -1, 2, -1, 1, -1},
{ 2, 2, -1, 1, 1, -1, 2, -1},
{-1, 2, -1, 1, -1, 1, -1, 1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{-1, 7, 7, -1, -1, 5, 5, -1},
{ 1, -1, -1, -1, -1, -1, 4, -1},
{ 2, 1, -1, -1, -1, -1, 4, 3},
{ 2, -1, -1, -1, -1, -1, 3, -1},
{ 1, 2, -1, -1, -1, -1, 3, 4},
{ 1, -1, -1, -1, -1, -1, 4, -1},
{ 7, 1, -1, -1, -1, -1, 4, 5},
{ 7, 7, -1, -1, -1, 5, 5, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{ 7, 7, -1, -1, -1, -1, 5, 5},
{ 1, 5, -1, -1, -1, 7, 4, -1},
{ 2, 1, -1, -1, -1, -1, 4, 3},
{ 2, -1, -1, -1, -1, -1, 3, -1},
{ 1, 5, -1, -1, -1, -1, 7, 4},
{ 1, -1, -1, -1, -1, -1, 4, -1},
{ 7, 1, -1, -1, -1, -1, 4, 5},
{ 7, 5, -1, -1, -1, 7, 5, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{-1, -1, -1, 0, 0, -1, -1, -1},
{-1, -1, 5, 0, 1, -1, -1, -1},
{-1, -1, 3, 5, 1, 6, -1, -1},
{-1, 4, 3, 2, 6, 2, -1, -1},
{-1, 7, 4, 7, 2, 2, 4, -1},
{ 6, 7, 7, 3, 3, 4, 3, -1},
{ 1, 6, 1, 1, 1, 3, 3, 5},
{ 1, 1, -1, -1, -1, -1, 5, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{-1, -1, 0, -1, -1, 0, -1, -1},
{-1, 3, 3, -1, 3, 3, -1, -1},
{-1, 0, 2, 0, 0, 2, 0, -1},
{-1, 3, 3, -1, 3, 3, -1, -1},
{-1, -1, 0, -1, -1, 0, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{-1, -1, -1, 1, 1, -1, -1, -1},
{-1, -1, 2, 2, 2, -1, -1, -1},
{-1, -1, 3, 3, 3, 3, -1, -1},
{-1, 4, 4, 4, 4, 4, -1, -1},
{-1, 5, 5, 5, 5, 5, 5, -1},
{-1, -1, -1, 6, -1, -1, -1, -1},
{-1, -1, -1, 7, 7, -1, -1, -1},
{-1, -1, -1, 0, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{-1, -1, -1, 2, 5, -1, -1, -1},
{-1, 4, 3, -1, -1, -1, -1, -1},
{ 6, 7, -1, 5, 2, -1, -1, -1},
{-1, -1, -1, -1, 3, 4, -1, -1},
{-1, -1, -1, 2, 5, -1, 7, 6},
{-1, 4, 3, -1, -1, -1, -1, -1},
{ 6, 7, -1, 5, 2, -1, -1, -1},
{-1, -1, -1, -1, 3, 4, -1, -1},
{-1, -1, -1, -1, -1, -1, 7, 6},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{-1, -1, -1, 5, 5, -1, -1, -1},
{-1, -1, -1, 3, -1, -1, -1, -1},
{-1, -1, -1, 1, -1, -1, -1, -1},
{-1, -1, -1, 7, -1, -1, -1, -1},
{-1, -1, -1, 2, -1, -1, -1, -1},
{-1, -1, -1, 4, -1, -1, -1, -1},
{-1, -1, -1, 5, -1, -1, -1, -1},
{-1, -1, -1, 3, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{-1, -1, -1, 0, 1, -1, -1, -1},
{-1, -1, 0, 2, 7, 7, -1, -1},
{-1, -1, -1, 0, 1, 7, -1, -1},
{-1, 0, 0, 0, 0, -1, -1, -1},
{-1, 0, 0, 0, 1, 1, -1, -1},
{ 0, 0, 0, 1, 1, 1, -1, -1},
{-1, 0, 0, 1, 1, 1, -1, -1},
{-1, 0, 0, 0, 7, 7, -1, -1},
{-1, -1, 7, 7, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{-1, 1, -1, -1, -1, -1, -1, -1},
{ 1, -1, -1, -1, -1, -1, -1, -1},
{-1, 2, 3, 4, 7, 6, 5, -1},
{-1, -1, -1, -1, -1, -1, 1, -1},
{-1, -1, -1, -1, -1, -1, 1, -1},
{-1, 2, 3, 4, 7, 6, -1, -1},
{-1, 1, -1, -1, -1, -1, -1, -1},
{ 1, -1, -1, -1, -1, -1, -1, -1},
{-1, 2, 3, 4, 7, 6, 5, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{-1, 6, -1, -1, -1, -1, -1, -1},
{ 5, -1, -1, -1, -1, -1, -1, -1},
{ 2, 3, 4, 7, 6, 5, 2, 3},
{-1, -1, -1, -1, -1, -1, 4, -1},
{-1, -1, -1, -1, -1, -1, 7, -1},
{-1, 4, 3, 2, 5, 6, -1, -1},
{-1, 7, -1, -1, -1, -1, -1, -1},
{ 6, -1, -1, -1, -1, -1, -1, -1},
{ 5, 2, 3, 4, 7, 6, 5, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{ 3, 2, 1, 0, 0, 1, 2, 3},
{ 3, 2, 1, 0, 1, 2, 3, -1},
{ 4, 3, 2, 1, 1, 2, 3, 4},
{ 4, 3, 2, 1, 2, 3, 4, -1},
{ 5, 4, 3, 2, 2, 3, 4, 5},
{ 5, 4, 3, 2, 3, 4, 5, -1},
{ 6, 5, 4, 3, 3, 4, 5, 6},
{ 6, 5, 4, 3, 4, 5, 6, -1},
{ 7, 6, 5, 4, 4, 5, 6, 7},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{-1, -1, -1, 5, 5, -1, -1, -1},
{-1, -1, -1, 3, -1, -1, -1, -1},
{-1, -1, -1, 2, 4, -1, -1, -1},
{-1, -1, -1, 6, -1, -1, -1, -1},
{-1, -1, -1, 2, 4, -1, -1, -1},
{-1, 2, -1, 5, -1, 4, -1, -1},
{ 1, 0, 1, 0, 1, 0, 1, 0},
{ 3, -1, 3, -1, 2, -1, 6, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{-1, -1, -1, -1, 1, -1, -1, -1},
{ 7, 4, 3, 5, -1, -1, -1, -1},
{ 6, -1, -1, 1, -1, -1, -1, -1},
{-1, -1, -1, 5, 3, 4, 7, -1},
{ 6, -1, -1, -1, 1, -1, -1, 6},
{ 7, 4, 3, 5, -1, -1, -1, -1},
{-1, -1, -1, 1, -1, -1, -1, 6},
{-1, -1, -1, 5, 3, 4, 7, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{-1, -1, -1, -1, 7, 3, 6, -1},
{-1, -1, 3, 7, 3, 6, 3, -1},
{-1, -1, 5, 7, 3, 6, 3, -1},
{-1, 6, 7, 3, 6, 7, -1, -1},
{-1, 7, 7, 3, 6, 1, -1, -1},
{ 3, 7, 3, 6, 3, -1, -1, -1},
{ 5, 6, 2, 7, 1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{ 5, -1, -1, -1, -1, -1, -1, 5},
{ 5, -1, 6, 6, 6, -1, 5, -1},
{-1, 5, 4, -1, -1, 4, 5, -1},
{-1, 3, -1, -1, -1, 3, -1, -1},
{-1, 6, 0, -1, -1, 0, 6, -1},
{-1, 3, -1, -1, -1, 3, -1, -1},
{-1, -1, 4, -1, -1, 4, -1, -1},
{-1, -1, 6, 6, 6, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{-1, 7, 0, -1, -1, 0, 7, -1},
{ 7, -1, 0, -1, 0, -1, 7, -1},
{ 7, 1, -1, 0, 0, -1, 1, 7},
{ 7, 1, 2, 0, 2, 1, 7, -1},
{ 7, 6, 3, 2, 2, 3, 6, 7},
{ 7, -1, 3, 2, 3, -1, 7, -1},
{-1, 7, 7, 3, 3, 7, 7, -1},
{-1, -1, -1, 3, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{-1, 3, -1, 1, -1, 7, -1, 6},
{ 5, -1, 7, -1, 7, -1, 6, -1},
{ 6, -1, 0, -1, 5, -1, 3, -1},
{-1, 2, -1, 1, -1, 5, -1, -1},
{-1, 4, -1, 3, -1, 4, -1, -1},
{ 2, -1, 3, -1, 2, -1, -1, -1},
{-1, -1, 4, -1, 6, -1, -1, -1},
{-1, -1, -1, 5, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{-1, -1, -1, -1, 1, -1, -1, -1},
{-1, -1, -1, -1, 3, -1, -1, -1},
{ 6, 1, 3, 1, 2, 1, 4, 1},
{-1, -1, -1, -1, 6, -1, -1, -1},
{-1, -1, -1, 4, 1, -1, -1, -1},
{-1, -1, 1, -1, 3, -1, -1, -1},
{-1, -1, -1, 2, 1, -1, -1, -1},
{-1, -1, -1, -1, 4, -1, -1, -1},
{-1, -1, -1, 6, 1, -1, -1, -1},
{-1, -1, -1, 6, -1, -1, -1, -1}},
{{-1, -1, -1, 5, 4, -1, -1, -1},
{-1, -1, 4, 1, 0, -1, -1, -1},
{-1, -1, -1, 2, 3, -1, -1, -1},
{-1, 1, 4, -1, 2, 2, -1, -1},
{-1, 3, 1, 2, 5, 1, 4, -1},
{-1, 4, 2, -1, 0, 4, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{-1, -1, -1, -1, 1, -1, -1, -1},
{-1, -1, -1, 1, -1, -1, -1, -1},
{-1, 2, -1, -1, 1, -1, 5, -1},
{ 5, -1, -1, 1, -1, -1, 0, -1},
{-1, 6, -1, -1, 1, -1, 4, -1},
{-1, 0, -1, 1, -1, 5, -1, -1},
{-1, -1, 5, 5, 0, 1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{-1, -1, -1, 6, 3, -1, -1, -1},
{-1, -1, 3, 2, 6, -1, -1, -1},
{-1, -1, 2, 6, 3, 2, -1, -1},
{-1, 6, 3, 2, 6, 3, -1, -1},
{-1, 3, 2, 6, 3, 2, 6, -1},
{ 2, 6, 3, 2, 6, 3, 2, -1},
{ 6, 3, 2, 6, 3, 2, 6, 3},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{ 6, 6, 6, 6, 6, 6, 6, 6},
{ 4, -1, -1, -1, -1, -1, -1, -1},
{-1, 3, 2, 5, 7, 6, 4, 3},
{-1, 5, -1, -1, -1, -1, -1, -1},
{-1, -1, 7, 6, 4, 3, 2, 5},
{-1, -1, 4, -1, -1, -1, -1, -1},
{-1, -1, -1, 3, 2, 5, 7, 6},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{ 1, -1, 7, -1, -1, 6, -1, 2},
{ 6, -1, 1, -1, 6, 1, 3, -1},
{-1, 4, -1, 7, 2, -1, 7, -1},
{ 2, 7, -1, -1, -1, 4, -1, -1},
{ 6, -1, 3, 5, 0, 2, -1, 7},
{ 1, -1, -1, -1, -1, -1, 1, -1},
{-1, 1, 4, 5, 7, 5, 1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{ 6, 6, 6, -1, -1, 6, 6, 6},
{-1, -1, 6, -1, 6, -1, -1, -1},
{-1, -1, 2, 3, 3, 2, -1, -1},
{-1, 3, -1, 5, -1, 3, -1, -1},
{-1, -1, 5, 3, 3, 5, -1, -1},
{-1, -1, 6, 1, 6, -1, -1, -1},
{-1, 4, 2, -1, -1, 2, 4, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{-1, -1, -1, 5, 5, -1, -1, -1},
{-1, -1, 5, -1, -1, -1, -1, -1},
{-1, 3, 4, 6, 6, -1, -1, 5},
{ 3, 3, 4, 6, 5, -1, 5, -1},
{ 3, 2, 3, 6, 6, 5, 5, -1},
{ 3, 3, 4, 6, 5, -1, 5, -1},
{-1, 3, 4, 6, 6, -1, -1, 5},
{-1, -1, 5, -1, -1, -1, -1, -1},
{-1, -1, -1, 5, 5, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{ 1, -1, -1, -1, -1, -1, -1, 1},
{ 1, -1, 2, 2, 2, -1, 1, -1},
{-1, 1, 2, 3, 3, 2, 1, -1},
{ 6, 2, 3, -1, 3, 2, 6, -1},
{ 6, 2, 3, -1, -1, 3, 2, 6},
{ 6, 2, 3, -1, 3, 2, 6, -1},
{ 3, 3, 3, 7, 7, 3, 3, 3},
{ 0, 5, 0, 2, 0, 5, 0, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{-1, -1, 7, 7, 7, -1, -1, -1},
{-1, 7, 2, 2, 7, -1, -1, -1},
{-1, 7, 5, 5, 5, 7, -1, -1},
{ 7, 7, 7, 7, 7, 7, -1, -1},
{-1, -1, 6, -1, 6, -1, -1, -1},
{-1, 6, -1, -1, 6, -1, -1, -1},
{-1, 6, 4, 4, -1, 6, 4, 4},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{-1, 3, 3, -1, 3, 3, 3, -1},
{ 3, 7, 5, 4, 6, 5, 3, -1},
{ 1, 3, 3, 3, -1, 3, 3, 1},
{ 2, 1, 2, 1, 2, 1, 2, -1},
{ 1, 3, 3, -1, 3, 3, 3, 1},
{ 3, 5, 6, 4, 5, 7, 3, -1},
{ 2, 3, 3, 3, -1, 3, 3, 2},
{ 1, 1, 2, 2, 2, 1, 1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{-1, 6, 5, -1, -1, -1, -1, -1},
{ 3, 1, 3, -1, -1, -1, -1, -1},
{-1, 5, 6, -1, -1, -1, -1, -1},
{-1, -1, 5, 3, -1, -1, -1, -1},
{-1, -1, 6, 1, 6, -1, -1, -1},
{-1, -1, 3, 5, -1, -1, -1, -1},
{-1, -1, -1, -1, 3, 6, -1, -1},
{-1, -1, -1, 5, 6, 5, -1, -1},
{-1, -1, -1, -1, 6, 3, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{ 6, 3, 7, 4, 5, 1, 6, 3},
{ 5, 1, 6, 3, 7, 4, 5, -1},
{ 6, 3, 7, 4, 5, 1, 6, 3},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{-1, -1, -1, -1, -1, -1, 4, 4},
{-1, -1, 7, 7, 7, 4, 4, -1},
{-1, -1, -1, -1, -1, -1, 4, 4},
{-1, 1, -1, -1, -1, 7, -1, -1},
{-1, 1, 1, -1, -1, 7, -1, -1},
{ 3, 3, 3, -1, 7, -1, -1, -1},
{ 3, -1, 2, 3, 3, 3, -1, 3},
{-1, 2, -1, 3, -1, 3, 3, -1},
{-1, 2, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{-1, -1, 4, -1, -1, -1, -1, -1},
{-1, 7, 4, -1, -1, -1, -1, -1},
{-1, -1, 7, 4, -1, -1, -1, -1},
{-1, 4, 7, 4, -1, -1, -1, -1},
{ 1, 1, 1, 1, 1, 1, 1, -1},
{ 1, 2, 1, 2, 1, 1, -1, -1},
{ 2, 2, 2, 2, 2, 2, 2, 2},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{ 0, -1, -1, -1, -1, -1, -1, 6},
{ 6, 1, 4, 3, 7, 5, 0, -1},
{ 0, -1, -1, -1, -1, -1, -1, 6},
{ 6, 1, 4, 3, 7, 5, 0, -1},
{ 0, -1, -1, -1, -1, -1, -1, 6},
{ 6, 1, 4, 3, 7, 5, 0, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{ 3, 3, 4, 6, 6, 4, 3, 3},
{ 0, 3, 4, 6, 4, 3, 1, -1},
{ 5, 1, 3, 4, 4, 3, 0, 1},
{ 0, 1, 3, 4, 3, 1, 0, -1},
{ 2, 1, 6, 3, 3, 0, 0, 1},
{ 0, 3, 4, 3, 6, 1, 5, -1},
{ 6, 1, 2, 6, 4, 0, 0, 2},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{ 6, 6, -1, -1, -1, -1, 4, 4},
{ 4, 0, -1, -1, -1, 3, 6, -1},
{ 0, 6, -1, -1, -1, -1, 4, 2},
{ 7, -1, -1, -1, -1, -1, 7, -1},
{ 4, 4, -1, -1, -1, -1, 5, 6},
{ 6, 4, 7, 7, 5, 6, 4, -1},
{-1, 7, 6, 4, 6, 4, 7, -1},
{-1, 0, -1, 7, -1, 7, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{-1, 5, -1, -1, -1, -1, 4, -1},
{-1, 5, -1, -1, -1, 4, -1, -1},
{-1, -1, 5, 6, 6, 4, -1, -1},
{-1, -1, 2, -1, 2, -1, -1, -1},
{ 0, 0, 6, -1, -1, 6, 1, 1},
{-1, -1, 2, -1, 2, -1, -1, -1},
{-1, -1, 7, 6, 6, 3, -1, -1},
{-1, 7, -1, -1, -1, 3, -1, -1},
{-1, 7, -1, -1, -1, -1, 3, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{-1, 6, -1, -1, -1, -1, 2, -1},
{ 1, 7, 1, 1, 1, 3, 1, -1},
{-1, -1, 4, 1, 1, 4, -1, -1},
{-1, 1, 3, 1, 7, 1, -1, -1},
{-1, -1, -1, 2, 6, -1, -1, -1},
{-1, -1, 1, 5, 1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{ 7, 7, 7, 7, 7, 7, 7, 7},
{ 7, -1, -1, -1, -1, -1, 7, -1},
{ 7, -1, -1, 2, 0, 5, 2, 2},
{ 7, -1, -1, -1, 0, 3, 6, -1},
{ 7, -1, -1, -1, -1, -1, 4, 0},
{ 5, 5, -1, -1, -1, -1, -1, -1},
{ 4, 3, 6, 2, -1, -1, -1, -1},
{ 0, 2, 0, 4, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{-1, -1, 1, -1, -1, 1, -1, -1},
{-1, 4, -1, -1, 5, -1, -1, -1},
{-1, 7, -1, -1, 1, 1, 1, -1},
{ 6, -1, -1, -1, -1, 7, -1, -1},
{ 1, 1, 1, 1, -1, 4, -1, -1},
{-1, -1, 5, -1, -1, -1, -1, -1},
{-1, -1, 0, -1, -1, -1, -1, -1},
{-1, 3, -1, -1, -1, -1, -1, -1},
{-1, 1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{-1, 7, 7, -1, -1, 7, 7, -1},
{ 6, -1, 4, -1, 4, -1, 6, -1},
{ 5, -1, -1, 3, 3, -1, -1, 5},
{ 6, -1, -1, -1, -1, -1, 6, -1},
{-1, 7, -1, -1, -1, -1, 7, -1},
{-1, 4, -1, -1, -1, 4, -1, -1},
{-1, -1, 3, -1, -1, 3, -1, -1},
{-1, -1, 2, -1, 2, -1, -1, -1},
{-1, -1, -1, 5, 5, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{-1, 0, 0, -1, -1, 0, 0, -1},
{ 7, 4, 6, 6, 6, 4, 3, -1},
{ 5, 6, 6, 6, 2, 6, 6, 3},
{ 7, 4, 6, 6, 6, 4, 3, -1},
{-1, 0, 0, -1, -1, 0, 0, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{-1, -1, -1, -1, -1, 7, 7, 7},
{-1, -1, -1, -1, 2, 7, 7, -1},
{-1, 0, 7, 7, 7, -1, 7, 7},
{ 6, 7, 7, 7, -1, -1, -1, -1},
{ 6, -1, -1, -1, 7, 7, 7, 7},
{ 6, -1, -1, -1, -1, -1, -1, -1},
{ 4, 2, 2, 2, 4, -1, 3, -1},
{ 4, 4, 4, 4, 3, 3, 3, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{ 4, -1, -1, 7, -1, 6, -1, 7},
{ 7, 6, 7, -1, -1, 7, 4, -1},
{-1, -1, 7, -1, -1, 7, -1, -1},
{-1, 0, 0, 0, 0, 0, 3, -1},
{-1, -1, 0, 2, 2, 0, 6, 4},
{-1, -1, 0, 0, 0, 1, 3, -1},
{-1, -1, -1, 0, 0, -1, 3, 4},
{-1, -1, -1, 6, -1, 5, 6, -1},
{-1, -1, -1, -1, -1, -1, 1, 0},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{-1, 5, -1, -1, -1, -1, 5, -1},
{ 0, -1, -1, 0, -1, -1, 0, -1},
{ 0, 0, 0, 2, 2, 0, 0, 0},
{ 0, -1, -1, 0, -1, -1, 0, -1},
{-1, 7, -1, 3, -1, -1, 7, -1},
{-1, -1, 3, 6, -1, -1, -1, -1},
{-1, -1, -1, 6, -1, -1, -1, -1},
{-1, 3, 6, -1, -1, -1, -1, -1},
{-1, 3, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{-1, -1, -1, 6, 5, -1, -1, -1},
{-1, -1, 2, 6, 3, -1, -1, -1},
{-1, -1, 5, 4, 7, 1, -1, -1},
{-1, 6, 2, 2, 3, 4, -1, -1},
{-1, -1, 3, 7, 3, 6, -1, -1},
{-1, -1, 1, 3, 2, -1, -1, -1},
{-1, -1, -1, 4, 5, -1, -1, -1},
{-1, -1, -1, 4, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{ 7, 7, -1, 2, 2, -1, 6, 6},
{ 6, -1, -1, 6, -1, -1, 3, -1},
{ 2, -1, -1, 1, -1, -1, 2, -1},
{ 5, -1, -1, 3, -1, -1, 2, -1},
{ 1, -1, -1, 2, -1, -1, 1, -1},
{ 5, -1, -1, 2, -1, -1, 2, -1},
{ 6, -1, -1, 1, -1, -1, 7, -1},
{ 5, -1, -1, 5, -1, -1, 4, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{-1, -1, -1, 6, 6, -1, -1, -1},
{-1, 0, 4, 4, 4, 0, -1, -1},
{-1, -1, -1, 6, 6, -1, -1, -1},
{-1, -1, 2, 7, 2, -1, -1, -1},
{-1, -1, -1, 6, 6, -1, -1, -1},
{-1, 0, 5, 5, 5, 0, -1, -1},
{-1, -1, -1, 3, 3, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{-1, -1, 4, 1, 3, -1, -1, -1},
{-1, 1, -1, -1, 1, -1, -1, -1},
{-1, -1, 4, 1, 3, 4, 1, -1},
{-1, 1, 3, 4, -1, -1, 4, -1},
{-1, 3, -1, -1, 3, 4, 1, -1},
{-1, 1, 3, 4, 1, 3, -1, -1},
{-1, -1, 4, 1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{-1, 6, 4, -1, 3, 2, 5, -1},
{ 0, -1, -1, -1, -1, -1, 1, -1},
{-1, 2, 3, 5, -1, 4, 6, -1},
{ 0, -1, -1, -1, -1, -1, 1, -1},
{-1, 4, 6, -1, 2, 5, 3, -1},
{ 0, -1, -1, -1, -1, -1, 1, -1},
{-1, 5, 2, 3, -1, 4, 6, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{-1, -1, -1, 6, 6, -1, -1, -1},
{-1, -1, 7, 6, 4, -1, -1, -1},
{-1, 2, 1, 7, 4, 1, 3, -1},
{ 2, 1, 1, 1, 1, 1, 3, -1},
{-1, 2, 2, 2, 3, 3, 3, -1},
{-1, -1, -1, 5, -1, -1, -1, -1},
{-1, -1, -1, 2, 3, -1, -1, -1},
{-1, -1, -1, 5, -1, -1, -1, -1},
{-1, -1, 2, 2, 3, 3, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{ 4, -1, 5, -1, -1, 3, -1, 6},
{ 2, -1, 3, -1, 2, -1, 4, -1},
{ 4, -1, -1, 1, 0, -1, -1, 6},
{ 6, -1, 2, 3, 5, -1, 4, -1},
{ 4, -1, -1, 0, 1, -1, -1, 6},
{ 2, -1, 5, -1, 3, -1, 4, -1},
{ 4, -1, 3, -1, -1, 2, -1, 6},
{ 6, -1, -1, -1, -1, -1, 4, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{ 2, 6, 0, 5, 5, 1, 3, 4},
{ 1, -1, -1, 2, -1, -1, 0, -1},
{ 4, -1, -1, 3, 6, -1, -1, 2},
{-1, -1, -1, 0, -1, -1, -1, -1},
{-1, -1, -1, 1, 4, -1, -1, -1},
{-1, -1, -1, 2, -1, -1, -1, -1},
{-1, -1, -1, 6, 3, -1, -1, -1},
{-1, -1, -1, 5, -1, -1, -1, -1},
{-1, -1, -1, 4, 1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{-1, -1, -1, -1, 5, 1, 1, 3},
{ 0, 5, 1, 0, 5, 3, 3, -1},
{ 5, 1, 0, 5, 1, 0, 5, 1},
{ 0, 5, 1, 0, 5, 1, 6, -1},
{-1, -1, -1, -1, 1, 6, 5, 1},
{-1, -1, -1, -1, 5, 1, 6, -1},
{-1, -1, -1, -1, 1, 0, 5, 1},
{-1, -1, -1, -1, 5, 1, 0, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{-1, 0, 7, 3, -1, -1, 2, 2},
{-1, 0, 7, 3, -1, -1, 2, -1},
{-1, 0, 7, 3, -1, -1, 2, 2},
{-1, 0, 7, 3, -1, 3, 1, -1},
{-1, 0, 7, 3, -1, 6, 4, 5},
{-1, 0, 7, 3, -1, 7, 0, -1},
{-1, 0, 7, 3, -1, 2, 3, 4},
{-1, 0, 7, 3, -1, 5, 6, -1},
{-1, -1, -1, -1, -1, 7, 0, 1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{-1, -1, -1, 7, 7, 7, 7, -1},
{ 3, 4, 5, -1, -1, -1, 7, -1},
{ 2, -1, -1, -1, -1, -1, -1, 3},
{ 7, -1, -1, -1, -1, -1, 4, -1},
{ 7, -1, -1, -1, 3, 4, 5, 6},
{ 7, -1, -1, 2, 0, 1, 2, -1},
{ 6, -1, -1, -1, 3, 4, 5, 6},
{ 0, 1, -1, -1, -1, -1, -1, -1},
{ 2, 3, 4, -1, -1, -1, -1, -1},
{ 5, 6, 0, -1, -1, -1, -1, -1}},
{{-1, 7, -1, -1, -1, -1, 2, -1},
{ 1, 1, -1, -1, -1, 3, 3, -1},
{-1, 2, -1, -1, -1, -1, 4, -1},
{ 3, 3, -1, -1, -1, 5, 5, -1},
{-1, 4, -1, -1, -1, -1, 6, -1},
{ 5, 5, -1, -1, -1, 1, 1, -1},
{-1, 6, -1, -1, -1, -1, 7, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{-1, 4, -1, -1, -1, -1, 4, -1},
{ 2, -1, -1, 1, -1, -1, 2, -1},
{ 5, -1, -1, 0, 0, -1, -1, 5},
{ 5, -1, -1, 1, -1, -1, 6, -1},
{-1, 4, 2, 7, 7, 5, 4, -1},
{-1, -1, -1, 6, -1, -1, -1, -1},
{-1, -1, -1, 3, 3, -1, -1, -1},
{-1, -1, -1, 7, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{-1, 1, -1, -1, 2, 3, 4, -1},
{ 2, -1, -1, 3, 0, 4, -1, -1},
{ 4, -1, -1, 2, 3, 1, -1, -1},
{ 3, -1, 4, 3, 0, -1, -1, -1},
{ 4, -1, -1, 2, 5, 1, -1, -1},
{ 3, -1, 4, 5, 0, 4, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{ 2, -1, -1, 1, 1, -1, -1, 2},
{ 2, -1, 3, 3, 3, -1, 2, -1},
{-1, 2, -1, 4, 4, -1, 2, -1},
{-1, 7, 7, 0, 7, 7, -1, -1},
{-1, -1, -1, 4, 4, -1, -1, -1},
{-1, -1, 5, 7, 5, -1, -1, -1},
{ 6, 3, 2, 6, 4, 2, 3, 6},
{ 5, -1, -1, -1, -1, -1, 1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{ 4, 2, 3, 5, 7, 1, 3, 6},
{ 1, -1, -1, 1, -1, -1, 1, -1},
{ 3, 0, 1, 3, 2, 4, 3, 5},
{ 4, -1, -1, 4, -1, -1, 4, -1},
{-1, 5, -1, -1, 5, -1, -1, 5},
{ 0, 3, 2, 0, 4, 5, 0, -1},
{-1, 6, -1, -1, 6, -1, -1, 6},
{ 7, -1, -1, 7, -1, -1, 7, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{-1, 5, 4, -1, 1, 1, -1, -1},
{ 5, -1, 4, 1, -1, 1, -1, -1},
{ 0, -1, -1, -1, -1, -1, 0, -1},
{ 0, 6, 4, -1, -1, 4, 2, -1},
{-1, 4, 3, 5, 2, 6, 3, 6},
{-1, 2, 6, -1, -1, 5, 4, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{-1, -1, -1, 6, 6, -1, -1, -1},
{-1, -1, 5, 5, 4, -1, -1, -1},
{-1, -1, 1, 6, 6, 4, -1, -1},
{-1, 1, 7, 2, 5, 3, -1, -1},
{-1, 2, 7, 2, 1, 5, 3, -1},
{ 2, 1, 3, 1, 4, 2, 7, -1},
{-1, 3, 1, 3, 4, 2, 7, -1},
{-1, 3, 5, 5, 6, 6, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{-1, -1, 7, 3, -1, -1, -1, -1},
{-1, 1, 7, 6, -1, -1, -1, -1},
{-1, 3, 7, 5, 1, 5, -1, -1},
{ 7, 7, 0, 2, 4, 0, 4, -1},
{ 7, 1, 4, 6, 5, 6, 5, 7},
{ 1, 7, 7, 1, 7, 7, 1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{-1, -1, 1, -1, -1, 1, -1, -1},
{-1, 5, 6, 1, 5, 6, -1, -1},
{-1, 1, 1, 2, 2, 1, 1, -1},
{ 4, 7, 1, 0, 1, 7, 4, -1},
{-1, 3, 7, 5, 7, 5, 3, -1},
{-1, 1, 1, 1, 1, 1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{ 4, -1, -1, -1, 5, -1, -1, 4},
{ 6, 6, 7, 6, -1, 4, 5, -1},
{ 4, 2, 7, 5, 2, 2, 6, 4},
{-1, -1, 4, 1, -1, 5, 2, -1},
{-1, 5, 2, 7, 7, -1, 7, 4},
{ 4, 6, 5, 4, -1, 4, 2, -1},
{-1, -1, -1, 4, -1, 4, 1, -1},
{ 0, 0, 0, 5, -1, -1, -1, -1},
{-1, -1, -1, -1, 0, 0, 0, 0},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{ 1, -1, -1, -1, 0, 0, -1, -1},
{ 2, -1, -1, 0, 1, 0, -1, -1},
{ 3, -1, -1, 0, 2, 2, 0, -1},
{ 4, -1, 0, 1, 1, 1, 0, -1},
{ 5, -1, -1, 0, 4, 4, 0, -1},
{ 6, -1, -1, 4, 4, 4, -1, -1},
{ 7, -1, -1, -1, 4, 4, -1, -1},
{-1, -1, -1, 0, 1, 0, -1, -1},
{-1, -1, -1, 0, 1, 1, 0, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{-1, -1, 3, -1, -1, 1, 7, -1},
{-1, 7, 4, -1, -1, 4, 3, -1},
{ 1, -1, -1, 0, 2, 0, -1, -1},
{ 5, 4, -1, 3, -1, -1, -1, -1},
{ 4, -1, 3, 6, 1, 1, 6, -1},
{-1, 1, -1, -1, 4, -1, 1, -1},
{-1, 7, 5, -1, -1, -1, 3, -1},
{-1, -1, 3, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{ 1, -1, -1, -1, 1, -1, -1, -1},
{ 2, -1, -1, -1, 2, -1, -1, -1},
{-1, 3, -1, -1, 3, 3, -1, -1},
{-1, 4, -1, 4, -1, 4, -1, -1},
{-1, 5, -1, -1, 5, 5, -1, -1},
{ 6, -1, -1, 7, 1, 7, -1, -1},
{ 7, -1, -1, -1, 6, 6, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{ 2, -1, -1, 6, -1, 2, 5, 1},
{ 5, -1, 4, -1, 4, -1, 4, -1},
{ 6, -1, -1, 3, -1, -1, -1, 3},
{ 4, 2, 0, -1, -1, -1, 5, -1},
{-1, -1, -1, 6, -1, 3, 6, -1},
{-1, -1, 5, -1, 5, -1, -1, -1},
{-1, -1, -1, 3, -1, 4, 2, 5},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{ 6, -1, -1, -1, 4, -1, -1, 3},
{ 0, 3, -1, -1, 6, -1, 0, -1},
{-1, -1, 7, -1, 1, -1, 3, -1},
{ 7, -1, 4, 7, -1, 2, -1, -1},
{ 5, 2, 3, 2, 1, 6, -1, 3},
{-1, -1, 0, 4, 3, 5, 4, -1},
{-1, 7, 6, -1, -1, 0, -1, -1},
{ 4, 3, -1, -1, -1, 4, 2, -1},
{ 0, -1, -1, -1, -1, -1, 6, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{ 6, 1, 2, 5, 1, 6, 3, 0},
{-1, -1, -1, -1, -1, -1, 4, -1},
{ 0, 5, 2, 7, 1, 6, 2, -1},
{ 3, -1, -1, -1, -1, -1, -1, -1},
{ 6, 7, 6, 4, 0, 5, 2, 6},
{-1, -1, -1, -1, -1, -1, 1, -1},
{ 6, 1, 4, 0, 6, 2, 3, -1},
{ 0, -1, -1, -1, -1, -1, -1, -1},
{-1, 0, 4, 5, 3, 7, 6, 0},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{-1, -1, -1, 0, 1, -1, -1, -1},
{-1, -1, 0, 7, 0, -1, -1, -1},
{-1, -1, 1, 2, 2, 0, -1, -1},
{-1, 0, 7, 0, 7, 0, -1, -1},
{-1, 6, -1, 7, 7, -1, 6, -1},
{ 4, 1, 6, 6, 6, 4, 1, -1},
{-1, 5, -1, 7, 7, -1, 5, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{-1, -1, -1, 5, 6, -1, -1, -1},
{-1, -1, 3, 3, 3, -1, -1, -1},
{-1, -1, 7, 5, 3, 7, -1, -1},
{-1, 3, -1, 6, -1, 3, -1, -1},
{ 2, -1, -1, 3, 7, -1, -1, 1},
{ 2, 2, -1, 3, -1, 1, 1, -1},
{-1, 0, 2, 5, 6, 1, 0, -1},
{-1, -1, -1, 3, -1, -1, -1, -1},
{-1, -1, -1, 3, 7, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{-1, 6, -1, -1, -1, -1, 2, -1},
{-1, 2, 6, 0, 6, 0, -1, -1},
{-1, 0, -1, -1, -1, -1, -1, -1},
{ 6, -1, -1, -1, -1, -1, -1, -1},
{-1, 3, 3, 2, 0, 6, 0, 0},
{-1, 6, -1, -1, -1, -1, 0, -1},
{-1, -1, -1, 6, 0, 2, 6, -1},
{-1, 2, 0, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{ 0, 7, -1, -1, -1, -1, -1, -1},
{ 1, 5, -1, -1, -1, -1, -1, -1},
{ 7, 2, 5, -1, -1, -1, -1, -1},
{ 6, 3, 4, -1, -1, -1, -1, -1},
{ 5, 5, 4, 4, -1, -1, -1, -1},
{ 3, 3, 5, 3, -1, -1, -1, -1},
{ 1, 2, 2, 5, 3, -1, -1, -1},
{ 1, 0, 0, 7, 6, -1, -1, -1},
{ 3, 3, 5, 5, 7, 6, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{-1, -1, 2, 6, 6, 2, -1, -1},
{-1, 2, 1, 1, 0, 2, -1, -1},
{-1, 2, 3, 2, 2, 0, 2, -1},
{ 2, 3, 2, 5, 2, 7, 2, -1},
{ 2, 4, 2, 5, 2, 7, 2, 0},
{ 2, 4, 2, 6, 6, 2, 0, -1},
{-1, 2, 5, 2, 2, 2, 7, 2},
{-1, 2, 5, 6, 6, 7, 2, -1},
{-1, -1, 2, 2, 2, 2, 2, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{-1, -1, 0, -1, -1, 0, -1, -1},
{ 1, 0, 0, 1, 0, 0, 1, -1},
{ 1, 7, 7, 5, 5, 7, 7, 1},
{ 3, 2, -1, 2, -1, 2, 3, -1},
{ 3, 7, -1, 6, 6, -1, 7, 3},
{ 7, -1, -1, 6, -1, -1, 7, -1},
{ 4, 4, 5, -1, -1, 5, 4, 4},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{-1, 6, 3, -1, -1, 3, 6, -1},
{ 6, -1, 2, -1, 2, -1, 6, -1},
{ 2, -1, 0, 1, 1, 0, -1, 2},
{ 5, 0, -1, 7, -1, 0, 5, -1},
{-1, 5, -1, 6, 6, -1, 5, -1},
{ 7, 1, 4, -1, 4, 1, 7, -1},
{ 7, -1, 4, -1, -1, 4, -1, 7},
{ 2, 0, -1, -1, -1, 0, 2, -1},
{-1, 2, -1, -1, -1, -1, 2, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{ 6, 1, -1, -1, -1, -1, 4, 0},
{ 2, 7, 5, 5, 5, 7, 3, -1},
{ 6, 1, -1, -1, -1, -1, 4, 0},
{ 2, 5, 7, 7, 7, 5, 3, -1},
{ 6, 1, -1, -1, -1, -1, 4, 0},
{ 2, 0, 6, 6, 6, 0, 3, -1},
{ 6, 1, -1, -1, -1, -1, 4, 0},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{ 5, -1, -1, 1, 1, -1, -1, 5},
{ 5, -1, 4, -1, 4, -1, 5, -1},
{-1, 2, 4, -1, -1, 4, 2, -1},
{ 7, 2, -1, -1, -1, 2, 7, -1},
{ 0, -1, 0, 4, 4, 0, -1, 0},
{ 7, 2, -1, -1, -1, 2, 7, -1},
{-1, 2, 3, -1, -1, 3, 2, -1},
{ 5, -1, 3, -1, 3, -1, 5, -1},
{ 5, -1, -1, 6, 6, -1, -1, 5},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{ 2, 2, -1, -1, -1, -1, 5, 5},
{ 5, -1, -1, -1, -1, -1, 2, -1},
{ 5, -1, -1, -1, -1, -1, -1, 2},
{ 1, -1, 1, 5, 1, -1, 3, -1},
{ 5, 2, 5, 3, 1, 2, 5, 2},
{ 2, 0, 5, -1, 2, 0, 5, -1},
{-1, 3, 7, -1, -1, 3, 7, -1},
{-1, -1, 2, 0, 5, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{ 0, 6, 5, 2, 3, 4, 1, 7},
{-1, -1, -1, -1, 1, -1, -1, -1},
{-1, -1, -1, 1, 1, -1, -1, -1},
{-1, -1, 1, -1, -1, -1, -1, -1},
{ 7, 1, 4, 3, 2, 5, 6, 0},
{-1, -1, -1, -1, 1, -1, -1, -1},
{-1, -1, -1, 1, 1, -1, -1, -1},
{-1, -1, 1, -1, -1, -1, -1, -1},
{ 0, 6, 5, 2, 3, 4, 1, 7},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{-1, -1, 1, -1, -1, 1, -1, -1},
{-1, 2, 4, -1, 2, 4, -1, -1},
{-1, 2, 3, 6, 5, 3, 2, -1},
{-1, 6, 5, -1, 6, 5, -1, -1},
{-1, -1, -1, 7, 7, -1, -1, -1},
{-1, -1, -1, 7, -1, -1, -1, -1},
{ 1, -1, -1, 7, 7, -1, -1, 3},
{ 2, -1, -1, 7, -1, -1, 2, -1},
{-1, 3, 4, 5, 6, 4, 1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{ 1, -1, -1, 2, 2, -1, -1, 2},
{ 1, 3, 7, 3, 7, 4, 2, -1},
{-1, 1, 6, -1, -1, 6, 2, -1},
{ 6, -1, 7, 3, 7, -1, 6, -1},
{-1, 4, 2, -1, -1, 1, 3, -1},
{-1, -1, 2, 6, 1, -1, -1, -1},
{-1, 4, 3, 3, 4, 4, 3, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{-1, -1, -1, 5, 6, -1, -1, -1},
{-1, -1, -1, 3, -1, -1, -1, -1},
{-1, -1, -1, 1, 2, -1, -1, -1},
{-1, -1, -1, 4, -1, -1, -1, -1},
{-1, -1, -1, 5, 7, -1, -1, -1},
{-1, -1, -1, 2, -1, -1, -1, -1},
{ 6, 5, 4, 3, 2, 1, 7, 5},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{-1, 0, -1, 1, -1, 2, -1, -1},
{-1, 4, -1, 5, -1, 6, -1, -1},
{-1, 7, -1, 0, -1, 2, -1, -1},
{-1, 6, -1, 3, -1, 6, -1, -1},
{-1, 1, -1, 1, -1, 2, -1, -1},
{-1, 3, -1, 5, -1, 0, -1, -1},
{-1, 2, -1, 4, -1, 6, -1, -1},
{-1, 3, -1, 6, -1, 7, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{ 1, 1, 2, 2, 3, 3, 4, 4},
{ 5, 5, 6, 7, 6, 5, 5, -1},
{ 6, 4, 3, 3, 2, 2, 1, 6},
{ 4, 6, 5, 7, 6, 3, 1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{ 7, 4, -1, 1, 2, -1, 4, 7},
{ 5, 5, -1, 2, -1, 4, 4, -1},
{-1, 5, -1, 7, 7, -1, 4, -1},
{ 1, 0, 6, 7, 6, 0, 2, -1},
{-1, 2, -1, 5, 3, -1, 1, -1},
{ 1, 1, -1, -1, -1, 2, 2, -1},
{ 6, 1, 4, -1, -1, 4, 2, 6},
{ 5, 3, -1, -1, -1, 3, 5, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{ 1, 5, 1, 0, 0, 1, 5, 1},
{ 1, 2, 5, -1, 5, 2, 1, -1},
{ 3, 6, 1, 2, 2, 1, 6, 3},
{ 4, 3, 4, -1, 4, 3, 4, -1},
{ 3, 4, 6, 5, 5, 6, 4, 3},
{ 0, 2, 3, -1, 3, 2, 0, -1},
{ 2, 3, 1, 5, 5, 1, 3, 2},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}},
{{ 3, 0, 2, 7, 5, 7, 6, 5},
{ 6, -1, 1, -1, 2, -1, 1, -1},
{-1, 6, 4, 0, 3, 4, 5, -1},
{-1, 5, -1, 1, -1, 4, -1, -1},
{-1, 7, 3, 5, 6, 5, 3, -1},
{ 1, -1, 2, -1, 4, -1, 2, -1},
{ 6, 4, 4, 6, 6, 5, 5, 1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}}
};
/* the tile struct
* type is the bubble number 0-7
* fallx is the x axis movement for the falling bubble
* fallvel is the initial upward velocity for the falling bubble
* ingroup denotes a bubble that is part of a group to be removed
* anchored denotes a bubble that is anchored to the ceiling
*/
struct tile {
int type;
int fallx;
int fallvel;
bool ingroup;
bool anchored;
bool delete;
};
/* the highscore struct
* level is the highscore level
* score is the highscore score
*/
struct highscore {
unsigned int level;
unsigned int score;
};
/* the game context struct
* score is the current score
* level is the current level
* highlevel is the highest level beaten
* highscores is the list of high scores
* angle is the current cannon direction
* shots is the number of shots fired since last compression
* compress is the height of the compressor
* onboardcnt is the number of unique bubbles on the playing board
* onboard is the unique bubbles on the playing board
* nextinq is the pointer to the next bubble in the firing queue
* queue is the circular buffer of bubbles to be fired
* elapsedlvl is level elapsed time in 1/100s of seconds
* elapsedshot is the shot elapsed time in 1/100s of seconds
* startedshot is when the current shot began
* resume denotes whether to resume the currently loaded game
* dirty denotes whether the high scores are out of sync with the saved file
* playboard is the game playing board
*/
struct game_context {
unsigned int score;
unsigned int level;
unsigned int highlevel;
struct highscore highscores[NUM_SCORES];
int angle;
int shots;
int compress;
int onboardcnt;
int onboard[NUM_BUBBLES];
int nextinq;
int queue[NUM_QUEUE];
long elapsedlvl;
long elapsedshot;
long startedshot;
bool resume;
bool dirty;
struct tile playboard[BB_HEIGHT][BB_WIDTH];
};
/*
* Precalculated sine and cosine * 16384 (fixed point 18.14)
* Borrowed from cube.c plugin
*/
static const short sin_table[91] = {
0, 285, 571, 857, 1142, 1427, 1712, 1996, 2280, 2563,
2845, 3126, 3406, 3685, 3963, 4240, 4516, 4790, 5062, 5334,
5603, 5871, 6137, 6401, 6663, 6924, 7182, 7438, 7691, 7943,
8191, 8438, 8682, 8923, 9161, 9397, 9630, 9860, 10086, 10310,
10531, 10748, 10963, 11173, 11381, 11585, 11785, 11982, 12175, 12365,
12550, 12732, 12910, 13084, 13254, 13420, 13582, 13740, 13894, 14043,
14188, 14329, 14466, 14598, 14725, 14848, 14967, 15081, 15190, 15295,
15395, 15491, 15582, 15668, 15749, 15825, 15897, 15964, 16025, 16082,
16135, 16182, 16224, 16261, 16294, 16321, 16344, 16361, 16374, 16381,
16384
};
static long sin(int val) {
val = (val+360)%360;
if(val < 181) {
if(val < 91) {
/* phase 0-90 degree */
return (long)sin_table[val];
} else {
/* phase 91-180 degree */
return (long)sin_table[180-val];
}
} else {
if(val < 271) {
/* phase 181-270 degree */
return -(long)sin_table[val-180];
} else {
/* phase 270-359 degree */
return -(long)sin_table[360-val];
}
}
return 0;
}
static long cos(int val) {
val = (val+360)%360;
if(val < 181) {
if(val < 91) {
/* phase 0-90 degree */
return (long)sin_table[90-val];
} else {
/* phase 91-180 degree */
return -(long)sin_table[val-90];
}
} else {
if(val < 271) {
/* phase 181-270 degree */
return -(long)sin_table[270-val];
} else {
/* phase 270-359 degree */
return (long)sin_table[val-270];
}
}
return 0;
}
static void bubbles_init(struct game_context* bb);
static bool bubbles_nextlevel(struct game_context* bb);
static void bubbles_getonboard(struct game_context* bb);
static void bubbles_drawboard(struct game_context* bb);
static int bubbles_fire(struct game_context* bb);
static bool bubbles_collision(struct game_context* bb, int y, int x,
int nearrow, int nearcol);
static bool bubbles_ingroup(struct game_context* bb, int row, int col);
static int bubbles_searchgroup(struct game_context* bb, int row, int col);
static int bubbles_remove(struct game_context* bb);
static void bubbles_anchored(struct game_context* bb, int row, int col);
static int bubbles_fall(struct game_context* bb);
static int bubbles_checklevel(struct game_context* bb);
static int bubbles_recordscore(struct game_context* bb);
static void bubbles_savescores(struct game_context* bb);
static bool bubbles_loadgame(struct game_context* bb);
static void bubbles_savegame(struct game_context* bb);
static void bubbles_setcolors(void);
static void bubbles_callback(void* param);
static int bubbles_handlebuttons(struct game_context* bb, bool animblock,
int timeout);
static int bubbles(struct game_context* bb);
/*****************************************************************************
* bubbles_init() initializes bubbles data structures.
******************************************************************************/
static void bubbles_init(struct game_context* bb) {
/* seed the rand generator */
rb->srand(*rb->current_tick);
/* check for resumed game */
if(bb->resume) {
bb->resume = false;
return;
}
bb->score = 0;
bubbles_nextlevel(bb);
}
/*****************************************************************************
* bubbles_nextlevel() sets up the game for the next level, returns false if
* there are no more levels.
******************************************************************************/
static bool bubbles_nextlevel(struct game_context* bb) {
int i, j, pos;
bb->level++;
/* check if there are no more levels */
if(bb->level > NUM_LEVELS) return false;
/* set up the play board */
rb->memset(bb->playboard, 0, sizeof(bb->playboard));
for(i=0; i<BB_LEVEL_HEIGHT; i++) {
for(j=0; j<BB_WIDTH; j++) {
pos = (int)level[bb->level-1][i][j];
if(pos >=0 && pos < NUM_BUBBLES) {
bb->playboard[i][j].type = pos;
} else {
bb->playboard[i][j].type = -1;
}
}
}
for(i=BB_LEVEL_HEIGHT; i<BB_HEIGHT; i++) {
for(j=0; j<BB_WIDTH; j++) {
bb->playboard[i][j].type = -1;
}
}
/* fill first bubbles in shot queue */
bubbles_getonboard(bb);
for(i=0; i<NUM_QUEUE; i++) {
bb->queue[i] = bb->onboard[rb->rand()%bb->onboardcnt];
}
bb->angle = 0;
bb->shots = 0;
bb->compress = 0;
bb->nextinq = 0;
bb->elapsedlvl = 0;
bb->elapsedshot = 0;
return true;
}
/*****************************************************************************
* bubbles_getonboard() determines which bubble types are on the play board.
******************************************************************************/
static void bubbles_getonboard(struct game_context* bb) {
int i, j, k;
bool found;
bb->onboardcnt = 0;
rb->memset(bb->onboard, -1, sizeof(bb->onboard));
for(i=0; i<BB_HEIGHT; i++) {
for(j=0; j<BB_WIDTH; j++) {
if(bb->playboard[i][j].type >= 0) {
found = false;
for(k=0; k<bb->onboardcnt; k++) {
if(bb->playboard[i][j].type == bb->onboard[k]) {
found = true;
break;
}
}
if(!found) {
bb->onboard[bb->onboardcnt] = bb->playboard[i][j].type;
bb->onboardcnt++;
}
if(bb->onboardcnt == NUM_BUBBLES) return;
}
}
}
}
/*****************************************************************************
* bubbles_drawboard() draws the game board to the buffer but does not update
* the lcd.
******************************************************************************/
static void bubbles_drawboard(struct game_context* bb) {
int i, j;
int w, h;
int colmax, indent;
int tipx, tipy;
bool evenline = false;
char *level = "Level";
char *score = "Score";
char *next = "Next";
char *hurry = "HURRY!";
char str[11];
/* clear screen */
rb->lcd_clear_display();
/* draw sidebars */
#ifdef HAVE_LCD_COLOR
rb->lcd_bitmap(bubbles_left, 0, 0, XOFS, LCD_HEIGHT);
rb->lcd_bitmap(bubbles_right, XOFS-1+BB_WIDTH*BUBBLE_WIDTH, 0,
LCD_WIDTH-(XOFS-1+BB_WIDTH*BUBBLE_WIDTH), LCD_HEIGHT);
#endif
/* display play board */
for(i=0; i<BB_HEIGHT; i++) {
colmax = BB_WIDTH;
if(evenline) {
colmax--;
indent = ROW_INDENT;
} else {
indent = 0;
}
evenline = !evenline;
for(j=0; j<colmax; j++) {
if(bb->playboard[i][j].type >= 0 && !bb->playboard[i][j].delete) {
rb->lcd_bitmap_part(bubbles_emblem,
0, EMBLEM_HEIGHT*bb->playboard[i][j].type, EMBLEM_WIDTH,
XOFS+indent+BUBBLE_WIDTH*j+(BUBBLE_WIDTH-EMBLEM_WIDTH)/2,
ROW_HEIGHT*i+(BUBBLE_HEIGHT-EMBLEM_HEIGHT)/2+bb->compress*ROW_HEIGHT,
EMBLEM_WIDTH, EMBLEM_HEIGHT);
rb->lcd_set_drawmode(DRMODE_FG);
rb->lcd_mono_bitmap((const unsigned char *)bubbles_bubble,
XOFS+indent+BUBBLE_WIDTH*j,
ROW_HEIGHT*i+bb->compress*ROW_HEIGHT,
BUBBLE_WIDTH, BUBBLE_HEIGHT);
rb->lcd_set_drawmode(DRMODE_SOLID);
}
}
}
/* display bubble to be shot */
rb->lcd_bitmap_part(bubbles_emblem,
0, EMBLEM_HEIGHT*bb->queue[bb->nextinq], EMBLEM_WIDTH,
SHOTX+(BUBBLE_WIDTH-EMBLEM_WIDTH)/2,
SHOTY+(BUBBLE_HEIGHT-EMBLEM_HEIGHT)/2,
EMBLEM_WIDTH, EMBLEM_HEIGHT);
rb->lcd_set_drawmode(DRMODE_FG);
rb->lcd_mono_bitmap((const unsigned char *)bubbles_bubble,
SHOTX, SHOTY,
BUBBLE_WIDTH, BUBBLE_HEIGHT);
rb->lcd_set_drawmode(DRMODE_SOLID);
/* display next bubble to be shot */
rb->lcd_bitmap_part(bubbles_emblem,
0, EMBLEM_HEIGHT*bb->queue[(bb->nextinq+1)%NUM_QUEUE], EMBLEM_WIDTH,
XOFS/2-BUBBLE_WIDTH/2+(BUBBLE_WIDTH-EMBLEM_WIDTH)/2,
SHOTY+(BUBBLE_HEIGHT-EMBLEM_HEIGHT)/2,
EMBLEM_WIDTH, EMBLEM_HEIGHT);
rb->lcd_set_drawmode(DRMODE_FG);
rb->lcd_mono_bitmap((const unsigned char *)bubbles_bubble,
XOFS/2-BUBBLE_WIDTH/2, SHOTY,
BUBBLE_WIDTH, BUBBLE_HEIGHT);
rb->lcd_set_drawmode(DRMODE_SOLID);
/* draw bounding lines */
#ifndef HAVE_LCD_COLOR
rb->lcd_vline(XOFS-1, 0, LCD_HEIGHT);
rb->lcd_vline(XOFS+BUBBLE_WIDTH*BB_WIDTH, 0, LCD_HEIGHT);
#endif
rb->lcd_hline(XOFS, XOFS+BUBBLE_WIDTH*BB_WIDTH-1, bb->compress*ROW_HEIGHT-1);
rb->lcd_hline(XOFS, XOFS+BUBBLE_WIDTH*BB_WIDTH-1,
ROW_HEIGHT*(BB_HEIGHT-2)+BUBBLE_HEIGHT);
/* draw arrow */
tipx = SHOTX+BUBBLE_WIDTH/2+(((sin(bb->angle)>>4)*BUBBLE_WIDTH*3/2)>>10);
tipy = SHOTY+BUBBLE_HEIGHT/2-(((cos(bb->angle)>>4)*BUBBLE_HEIGHT*3/2)>>10);
rb->lcd_drawline(SHOTX+BUBBLE_WIDTH/2+(((sin(bb->angle)>>4)*BUBBLE_WIDTH/2)>>10),
SHOTY+BUBBLE_HEIGHT/2-(((cos(bb->angle)>>4)*BUBBLE_HEIGHT/2)>>10),
tipx, tipy);
xlcd_filltriangle(tipx, tipy,
tipx+(((sin(bb->angle-135)>>4)*BUBBLE_WIDTH/3)>>10),
tipy-(((cos(bb->angle-135)>>4)*BUBBLE_HEIGHT/3)>>10),
tipx+(((sin(bb->angle+135)>>4)*BUBBLE_WIDTH/3)>>10),
tipy-(((cos(bb->angle+135)>>4)*BUBBLE_HEIGHT/3)>>10));
/* draw text */
rb->lcd_getstringsize(level, &w, &h);
rb->lcd_putsxy(XOFS/2-w/2, 2, level);
rb->snprintf(str, 4, "%d", bb->level);
rb->lcd_getstringsize(str, &w, &h);
rb->lcd_putsxy(XOFS/2-w/2, 11, str);
rb->lcd_getstringsize(score, &w, &h);
rb->lcd_putsxy(XOFS/2-w/2, 29, score);
rb->snprintf(str, 10, "%d", bb->score);
rb->lcd_getstringsize(str, &w, &h);
rb->lcd_putsxy(XOFS/2-w/2, 38, str);
rb->lcd_getstringsize(next, &w, &h);
rb->lcd_putsxy(XOFS/2-w/2, SHOTY-9, next);
if(bb->elapsedshot >= (MAX_SHOTTIME*7)/10) {
rb->lcd_getstringsize(hurry, &w, &h);
rb->lcd_putsxy(LCD_WIDTH/2-w/2, LCD_HEIGHT/2-h/2, hurry);
}
}
/*****************************************************************************
* bubbles_fire() fires the current bubble, reloads the cannon, attaches
* bubble to playboard, removes appropriate bubbles, and advances the
* the compressor.
******************************************************************************/
static int bubbles_fire(struct game_context* bb) {
int bubblecur;
long shotxinc, shotyinc;
long shotxofs, shotyofs;
int shotxdirec = 1;
long tempxofs, tempyofs;
int nearrow, nearcol;
int lastrow = BB_HEIGHT-1;
int lastcol = (BB_WIDTH-1)/2;
int buttonres;
long lasttick, currenttick;
/* get current bubble */
bubblecur = bb->queue[bb->nextinq];
shotxinc = ((sin(bb->angle)>>4)*BUBBLE_WIDTH)/3;
shotyinc = ((-1*(cos(bb->angle)>>4))*BUBBLE_HEIGHT)/3;
shotxofs = shotyofs = 0;
/* advance the queue */
bb->queue[bb->nextinq] = bb->onboard[rb->rand()%bb->onboardcnt];
bb->nextinq = (bb->nextinq+1)%NUM_QUEUE;
bubbles_drawboard(bb);
rb->lcd_update_rect(0, 0, XOFS, LCD_HEIGHT);
/* move the bubble across the play board */
lasttick = *rb->current_tick;
while(true) {
/* move the bubble one step */
shotyofs += shotyinc;
shotxofs += shotxinc*shotxdirec;
/* check for bounce off sides */
if(SHOTX+(shotxofs>>10) < XOFS) {
shotxofs += 2*((XOFS<<10)-(((SHOTX)<<10)+shotxofs));
shotxdirec *= -1;
} else if(SHOTX+(shotxofs>>10) > XOFS+(BB_WIDTH-1)*BUBBLE_WIDTH) {
shotxofs -= 2*((((SHOTX)<<10)+shotxofs)-
((XOFS<<10)+(((BB_WIDTH-1)*BUBBLE_WIDTH)<<10)));
shotxdirec *= -1;
}
tempxofs = shotxofs>>10;
tempyofs = shotyofs>>10;
/* display shot */
bubbles_drawboard(bb);
rb->lcd_bitmap_part(bubbles_emblem, 0, EMBLEM_HEIGHT*bubblecur, EMBLEM_WIDTH,
SHOTX+tempxofs+(BUBBLE_WIDTH-EMBLEM_WIDTH)/2,
SHOTY+tempyofs+(BUBBLE_HEIGHT-EMBLEM_HEIGHT)/2,
EMBLEM_WIDTH, EMBLEM_HEIGHT);
rb->lcd_set_drawmode(DRMODE_FG);
rb->lcd_mono_bitmap((const unsigned char *)bubbles_bubble,
SHOTX+tempxofs, SHOTY+tempyofs,
BUBBLE_WIDTH, BUBBLE_HEIGHT);
rb->lcd_set_drawmode(DRMODE_SOLID);
rb->lcd_update_rect(XOFS, 0, BB_WIDTH*BUBBLE_WIDTH, LCD_HEIGHT);
/* find nearest position */
nearrow = ((SHOTY+tempyofs)-
(bb->compress*ROW_HEIGHT)+
(ROW_HEIGHT/2))/ROW_HEIGHT;
if(nearrow >= BB_HEIGHT) nearrow = BB_HEIGHT-1;
if(nearrow%2) { /* odd row */
nearcol = ((SHOTX+tempxofs)-
(XOFS+ROW_INDENT)+
(BUBBLE_WIDTH/2))/BUBBLE_WIDTH;
if(nearcol >= BB_WIDTH-1) nearcol = BB_WIDTH-2;
} else { /* even row */
nearcol = ((SHOTX+tempxofs)-XOFS+(BUBBLE_WIDTH/2))/BUBBLE_WIDTH;
if(nearcol >= BB_WIDTH) nearcol = BB_WIDTH-1;
}
if(nearcol < 0) nearcol = 0;
/* if nearest position is occupied attach to last position */
if(bb->playboard[nearrow][nearcol].type >= 0) {
bb->playboard[lastrow][lastcol].type = bubblecur;
break;
}
/* save last position */
lastrow = nearrow;
lastcol = nearcol;
/* if collision with neighbor then attach shot */
if(bubbles_collision(bb, SHOTY+tempyofs, SHOTX+tempxofs,
nearrow, nearcol)) {
bb->playboard[nearrow][nearcol].type = bubblecur;
break;
}
/* if at top then attach shot to the ceiling */
if(nearrow == 0 && SHOTY+tempyofs <= bb->compress*ROW_HEIGHT) {
bb->playboard[nearrow][nearcol].type = bubblecur;
break;
}
/* handle button events */
buttonres = bubbles_handlebuttons(bb, true, 0);
if(buttonres != BB_NONE) return buttonres;
/* framerate limiting */
currenttick = *rb->current_tick;
if(currenttick-lasttick < HZ/MAX_FPS) {
rb->sleep((HZ/MAX_FPS)-(currenttick-lasttick));
} else {
rb->yield();
}
lasttick = currenttick;
}
bubbles_drawboard(bb);
rb->lcd_update();
/* clear appropriate bubbles from playing board */
if(bubbles_ingroup(bb, lastrow, lastcol)) {
buttonres = bubbles_remove(bb);
if(buttonres != BB_NONE) return buttonres;
}
/* update shots and compress amount */
bb->shots++;
if(bb->shots >= NUM_COMPRESS) {
bb->shots = 0;
bb->compress++;
}
return BB_NONE;
}
/*****************************************************************************
* bubbles_collision() determines if a fired bubble has collided with another
* bubble.
******************************************************************************/
static bool bubbles_collision(struct game_context* bb, int y, int x,
int nearrow, int nearcol) {
int nx, ny;
int adj = nearrow%2;
/* check neighbors */
if(nearcol-1 >= 0) {
if(bb->playboard[nearrow][nearcol-1].type >= 0) {
nx = XOFS+(nearrow%2 ? ROW_INDENT : 0)+BUBBLE_WIDTH*(nearcol-1);
ny = ROW_HEIGHT*nearrow+bb->compress*ROW_HEIGHT;
if((x-nx)*(x-nx)+(y-ny)*(y-ny) < MIN_DISTANCE) return true;
}
}
if(nearcol-1+adj >= 0) {
if(nearrow-1 >= 0) {
if(bb->playboard[nearrow-1][nearcol-1+adj].type >= 0) {
nx = XOFS+((nearrow-1)%2 ? ROW_INDENT : 0)+
BUBBLE_WIDTH*(nearcol-1+adj);
ny = ROW_HEIGHT*(nearrow-1)+bb->compress*ROW_HEIGHT;
if((x-nx)*(x-nx)+(y-ny)*(y-ny) < MIN_DISTANCE) return true;
}
}
if(nearrow+1 < BB_HEIGHT) {
if(bb->playboard[nearrow+1][nearcol-1+adj].type >= 0) {
nx = XOFS+((nearrow+1)%2 ? ROW_INDENT : 0)+
BUBBLE_WIDTH*(nearcol-1+adj);
ny = ROW_HEIGHT*(nearrow+1)+bb->compress*ROW_HEIGHT;
if((x-nx)*(x-nx)+(y-ny)*(y-ny) < MIN_DISTANCE) return true;
}
}
}
if(nearcol+adj >= 0) {
if(nearrow-1 >= 0) {
if(bb->playboard[nearrow-1][nearcol+adj].type >= 0) {
nx = XOFS+((nearrow-1)%2 ? ROW_INDENT : 0)+
BUBBLE_WIDTH*(nearcol+adj);
ny = ROW_HEIGHT*(nearrow-1)+bb->compress*ROW_HEIGHT;
if((x-nx)*(x-nx)+(y-ny)*(y-ny) < MIN_DISTANCE) return true;
}
}
if(nearrow+1 < BB_HEIGHT) {
if(bb->playboard[nearrow+1][nearcol+adj].type >= 0) {
nx = XOFS+((nearrow+1)%2 ? ROW_INDENT : 0)+
BUBBLE_WIDTH*(nearcol+adj);
ny = ROW_HEIGHT*(nearrow+1)+bb->compress*ROW_HEIGHT;
if((x-nx)*(x-nx)+(y-ny)*(y-ny) < MIN_DISTANCE) return true;
}
}
}
if(nearcol+1 < BB_WIDTH-adj) {
if(bb->playboard[nearrow][nearcol+1].type >= 0) {
nx = XOFS+(nearrow%2 ? ROW_INDENT : 0)+BUBBLE_WIDTH*(nearcol+1);
ny = ROW_HEIGHT*nearrow+bb->compress*ROW_HEIGHT;
if((x-nx)*(x-nx)+(y-ny)*(y-ny) < MIN_DISTANCE) return true;
}
}
return false;
}
/*****************************************************************************
* bubbles_ingroup() marks all bubbles that form the current group.
******************************************************************************/
static bool bubbles_ingroup(struct game_context* bb, int row, int col) {
int i, j;
int count;
count = bubbles_searchgroup(bb, row, col);
/* unmark group if too small */
if(count < 3) {
for(i=0; i<BB_HEIGHT; i++) {
for(j=0; j<BB_WIDTH; j++) {
bb->playboard[i][j].ingroup = false;
}
}
return false;
}
return true;
}
/*****************************************************************************
* bubbles_searchgroup() return the size of the group of bubbles of the same
* type that the current bubble belongs to.
******************************************************************************/
static int bubbles_searchgroup(struct game_context* bb, int row, int col) {
int i, adj;
int myrow, mycol, mytype;
int count = 0;
struct coord {
int row;
int col;
} search[(2*BB_WIDTH-1)*(BB_HEIGHT/2)];
/* search initial bubble */
bb->playboard[row][col].ingroup = true;
search[count].row = row;
search[count].col = col;
count++;
/* breadth-first search neighbors */
for(i=0; i<count; i++) {
myrow = search[i].row;
mycol = search[i].col;
mytype = bb->playboard[myrow][mycol].type;
adj = myrow%2;
if(mycol-1 >= 0) {
if(bb->playboard[myrow][mycol-1].type == mytype &&
!bb->playboard[myrow][mycol-1].ingroup) {
bb->playboard[myrow][mycol-1].ingroup = true;
search[count].row = myrow;
search[count].col = mycol-1;
count++;
}
}
if(mycol-1+adj >= 0) {
if(myrow-1 >= 0) {
if(bb->playboard[myrow-1][mycol-1+adj].type == mytype &&
!bb->playboard[myrow-1][mycol-1+adj].ingroup) {
bb->playboard[myrow-1][mycol-1+adj].ingroup = true;
search[count].row = myrow-1;
search[count].col = mycol-1+adj;
count++;
}
}
if(myrow+1 < BB_HEIGHT) {
if(bb->playboard[myrow+1][mycol-1+adj].type == mytype &&
!bb->playboard[myrow+1][mycol-1+adj].ingroup) {
bb->playboard[myrow+1][mycol-1+adj].ingroup = true;
search[count].row = myrow+1;
search[count].col = mycol-1+adj;
count++;
}
}
}
if(mycol+adj >= 0) {
if(myrow-1 >= 0) {
if(bb->playboard[myrow-1][mycol+adj].type == mytype &&
!bb->playboard[myrow-1][mycol+adj].ingroup) {
bb->playboard[myrow-1][mycol+adj].ingroup = true;
search[count].row = myrow-1;
search[count].col = mycol+adj;
count++;
}
}
if(myrow+1 < BB_HEIGHT) {
if(bb->playboard[myrow+1][mycol+adj].type == mytype &&
!bb->playboard[myrow+1][mycol+adj].ingroup) {
bb->playboard[myrow+1][mycol+adj].ingroup = true;
search[count].row = myrow+1;
search[count].col = mycol+adj;
count++;
}
}
}
if(mycol+1 < BB_WIDTH-adj) {
if(bb->playboard[myrow][mycol+1].type == mytype &&
!bb->playboard[myrow][mycol+1].ingroup) {
bb->playboard[myrow][mycol+1].ingroup = true;
search[count].row = myrow;
search[count].col = mycol+1;
count++;
}
}
}
return count;
}
/*****************************************************************************
* bubbles_remove() removes all bubbles in the current group and all
* unanchored bubbles from the play board.
******************************************************************************/
static int bubbles_remove(struct game_context* bb) {
int i, j;
int buttonres;
/* determine all anchored bubbles */
for(j=0; j<BB_WIDTH; j++) {
if(bb->playboard[0][j].type >= 0 && !bb->playboard[0][j].ingroup) {
bubbles_anchored(bb, 0, j);
}
}
/* mark bubbles to be deleted */
for(i=0; i<BB_HEIGHT; i++) {
for(j=0; j<BB_WIDTH; j++) {
if(bb->playboard[i][j].type >= 0 &&
(!bb->playboard[i][j].anchored || bb->playboard[i][j].ingroup)) {
bb->playboard[i][j].delete = true;
}
}
}
/* animate falling bubbles */
buttonres = bubbles_fall(bb);
if(buttonres != BB_NONE) return buttonres;
/* remove bubbles */
for(i=0; i<BB_HEIGHT; i++) {
for(j=0; j<BB_WIDTH; j++) {
if(bb->playboard[i][j].delete) {
bb->playboard[i][j].ingroup = false;
bb->playboard[i][j].type = -1;
bb->playboard[i][j].delete = false;
} else {
bb->playboard[i][j].anchored = false;
}
}
}
bubbles_getonboard(bb);
return BB_NONE;
}
/*****************************************************************************
* bubbles_anchored() marks all bubbles that are anchored in some way to the
* current bubble.
******************************************************************************/
static void bubbles_anchored(struct game_context* bb, int row, int col) {
int i, adj;
int myrow, mycol, mytype;
int count = 0;
struct coord {
int row;
int col;
} search[(2*BB_WIDTH-1)*(BB_HEIGHT/2)];
/* search initial bubble */
bb->playboard[row][col].anchored = true;
search[count].row = row;
search[count].col = col;
count++;
/* breadth-first search neighbors */
for(i=0; i<count; i++) {
myrow = search[i].row;
mycol = search[i].col;
mytype = bb->playboard[myrow][mycol].type;
adj = myrow%2;
if(mycol-1 >= 0) {
if(bb->playboard[myrow][mycol-1].type >= 0 &&
!bb->playboard[myrow][mycol-1].ingroup &&
!bb->playboard[myrow][mycol-1].anchored) {
bb->playboard[myrow][mycol-1].anchored = true;
search[count].row = myrow;
search[count].col = mycol-1;
count++;
}
}
if(mycol-1+adj >= 0) {
if(myrow-1 >= 0) {
if(bb->playboard[myrow-1][mycol-1+adj].type >= 0 &&
!bb->playboard[myrow-1][mycol-1+adj].ingroup &&
!bb->playboard[myrow-1][mycol-1+adj].anchored) {
bb->playboard[myrow-1][mycol-1+adj].anchored = true;
search[count].row = myrow-1;
search[count].col = mycol-1+adj;
count++;
}
}
if(myrow+1 < BB_HEIGHT) {
if(bb->playboard[myrow+1][mycol-1+adj].type >= 0 &&
!bb->playboard[myrow+1][mycol-1+adj].ingroup &&
!bb->playboard[myrow+1][mycol-1+adj].anchored) {
bb->playboard[myrow+1][mycol-1+adj].anchored = true;
search[count].row = myrow+1;
search[count].col = mycol-1+adj;
count++;
}
}
}
if(mycol+adj >= 0) {
if(myrow-1 >= 0) {
if(bb->playboard[myrow-1][mycol+adj].type >= 0 &&
!bb->playboard[myrow-1][mycol+adj].ingroup &&
!bb->playboard[myrow-1][mycol+adj].anchored) {
bb->playboard[myrow-1][mycol+adj].anchored = true;
search[count].row = myrow-1;
search[count].col = mycol+adj;
count++;
}
}
if(myrow+1 < BB_HEIGHT) {
if(bb->playboard[myrow+1][mycol+adj].type >= 0 &&
!bb->playboard[myrow+1][mycol+adj].ingroup &&
!bb->playboard[myrow+1][mycol+adj].anchored) {
bb->playboard[myrow+1][mycol+adj].anchored = true;
search[count].row = myrow+1;
search[count].col = mycol+adj;
count++;
}
}
}
if(mycol+1 < BB_WIDTH-adj) {
if(bb->playboard[myrow][mycol+1].type >= 0 &&
!bb->playboard[myrow][mycol+1].ingroup &&
!bb->playboard[myrow][mycol+1].anchored) {
bb->playboard[myrow][mycol+1].anchored = true;
search[count].row = myrow;
search[count].col = mycol+1;
count++;
}
}
}
}
/*****************************************************************************
* bubbles_fall() makes removed bubbles fall from the screen.
******************************************************************************/
static int bubbles_fall(struct game_context* bb) {
int i, j;
int count;
int indent;
int xofs, yofs;
int buttonres;
bool onscreen;
long lasttick, currenttick;
/* give all falling bubbles an x axis movement */
for(i=0; i<BB_HEIGHT; i++) {
for(j=0; j<BB_WIDTH; j++) {
if(bb->playboard[i][j].delete) {
bb->playboard[i][j].fallx = rb->rand()%25 - 12;
bb->playboard[i][j].fallvel = rb->rand()%5 + 6;
}
}
}
/* draw bubbles falling off the screen
* follows y=x^2-8x scaled to bubble size
*/
lasttick = *rb->current_tick;
for(count=1; ;count++) {
onscreen = false;
bubbles_drawboard(bb);
for(i=0; i<BB_HEIGHT; i++) {
for(j=0; j<BB_WIDTH; j++) {
if(bb->playboard[i][j].delete) {
indent = (i%2 ? ROW_INDENT : 0);
xofs = ((bb->playboard[i][j].fallx*count)*BUBBLE_WIDTH)/48;
yofs = ((count*count - bb->playboard[i][j].fallvel*count)*
BUBBLE_HEIGHT)/20;
/* draw bubble if it is still on the screen */
if(ROW_HEIGHT*i+bb->compress*ROW_HEIGHT+yofs
<= LCD_HEIGHT) {
onscreen = true;
rb->lcd_bitmap_part(bubbles_emblem, 0,
EMBLEM_HEIGHT*bb->playboard[i][j].type, EMBLEM_WIDTH,
XOFS+indent+BUBBLE_WIDTH*j+
(BUBBLE_WIDTH-EMBLEM_WIDTH)/2+xofs,
ROW_HEIGHT*i+(BUBBLE_HEIGHT-EMBLEM_HEIGHT)/2+
bb->compress*ROW_HEIGHT+yofs,
EMBLEM_WIDTH, EMBLEM_HEIGHT);
rb->lcd_set_drawmode(DRMODE_FG);
rb->lcd_mono_bitmap(
(const unsigned char *)bubbles_bubble,
XOFS+indent+BUBBLE_WIDTH*j+xofs,
ROW_HEIGHT*i+bb->compress*ROW_HEIGHT+yofs,
BUBBLE_WIDTH, BUBBLE_HEIGHT);
rb->lcd_set_drawmode(DRMODE_SOLID);
}
}
}
}
rb->lcd_update();
/* break out if all bubbles are off the screen */
if(!onscreen) break;
/* handle button events */
buttonres = bubbles_handlebuttons(bb, true, 0);
if(buttonres != BB_NONE) return buttonres;
/* framerate limiting */
currenttick = *rb->current_tick;
if(currenttick-lasttick < HZ/MAX_FPS) {
rb->sleep((HZ/MAX_FPS)-(currenttick-lasttick));
} else {
rb->yield();
}
lasttick = currenttick;
}
return BB_NONE;
}
/*****************************************************************************
* bubbles_checklevel() checks the state of the playboard for a win or loss.
******************************************************************************/
static int bubbles_checklevel(struct game_context* bb) {
int i, j;
int points;
char str[13];
bubbles_drawboard(bb);
rb->lcd_update();
/* check for bubbles below cut off point */
for(i=0; i<=bb->compress; i++) {
for(j=0; j<BB_WIDTH; j++) {
if(bb->playboard[BB_HEIGHT-1-i][j].type >= 0) return BB_LOSE;
}
}
/* check for bubbles above cut off point */
for(i=0; i<BB_HEIGHT-1-bb->compress; i++) {
for(j=0; j<BB_WIDTH; j++) {
if(bb->playboard[i][j].type >= 0) return BB_NONE;
}
}
/* level complete, record score */
points = 100 - bb->elapsedlvl/100;
if(points > 0) {
bb->score += points;
} else {
points = 0;
}
rb->snprintf(str, 12, "%d points", points);
rb->splash(HZ, true, str);
/* advance to the next level */
if(!bubbles_nextlevel(bb)) {
return BB_WIN;
}
bubbles_drawboard(bb);
rb->lcd_update();
rb->snprintf(str, 12, "Level %d", bb->level);
rb->splash(HZ, true, str);
bubbles_drawboard(bb);
rb->lcd_update();
return BB_NONE;
}
/*****************************************************************************
* bubbles_recordscore() inserts a high score into the high scores list and
* returns the high score position.
******************************************************************************/
static int bubbles_recordscore(struct game_context* bb) {
int i;
int position = 0;
unsigned int currentscore, currentlevel;
unsigned int tempscore, templevel;
if(bb->score > 0) {
currentlevel = bb->level-1;
currentscore = bb->score;
for(i=0; i<NUM_SCORES; i++) {
if(currentscore >= bb->highscores[i].score) {
if(!position) {
position = i+1;
bb->dirty = true;
}
templevel = bb->highscores[i].level;
tempscore = bb->highscores[i].score;
bb->highscores[i].level = currentlevel;
bb->highscores[i].score = currentscore;
currentlevel = templevel;
currentscore = tempscore;
}
}
}
return position;
}
/*****************************************************************************
* bubbles_loadscores() loads the high scores saved file.
******************************************************************************/
static void bubbles_loadscores(struct game_context* bb) {
int fd;
bb->dirty = false;
/* clear high scores */
bb->highlevel = 0;
rb->memset(bb->highscores, 0, sizeof(bb->highscores));
/* open scores file */
fd = rb->open(SCORE_FILE, O_RDONLY);
if(fd < 0) return;
/* read in high scores */
rb->read(fd, &bb->highlevel, sizeof(bb->highlevel));
if(rb->read(fd, bb->highscores, sizeof(bb->highscores)) <= 0) {
/* scores are bad, reset */
rb->memset(bb->highscores, 0, sizeof(bb->highscores));
}
rb->close(fd);
}
/*****************************************************************************
* bubbles_savescores() saves the high scores saved file.
******************************************************************************/
static void bubbles_savescores(struct game_context* bb) {
int fd;
/* write out the high scores to the save file */
fd = rb->open(SCORE_FILE, O_WRONLY|O_CREAT);
rb->write(fd, &bb->highlevel, sizeof(bb->highlevel));
rb->write(fd, bb->highscores, sizeof(bb->highscores));
rb->close(fd);
bb->dirty = false;
}
/*****************************************************************************
* bubbles_loadgame() loads the saved game and returns load success.
******************************************************************************/
static bool bubbles_loadgame(struct game_context* bb) {
int fd;
bool loaded = false;
/* open game file */
fd = rb->open(SAVE_FILE, O_RDONLY);
if(fd < 0) return loaded;
/* read in saved game */
while(true) {
if(rb->read(fd, &bb->score, sizeof(bb->score)) <= 0) break;
if(rb->read(fd, &bb->level, sizeof(bb->level)) <= 0) break;
if(rb->read(fd, &bb->angle, sizeof(bb->angle)) <= 0) break;
if(rb->read(fd, &bb->shots, sizeof(bb->shots)) <= 0) break;
if(rb->read(fd, &bb->compress, sizeof(bb->compress)) <= 0) break;
if(rb->read(fd, &bb->onboardcnt, sizeof(bb->onboardcnt)) <= 0) break;
if(rb->read(fd, bb->onboard, sizeof(bb->onboard)) <= 0) break;
if(rb->read(fd, &bb->nextinq, sizeof(bb->nextinq)) <= 0) break;
if(rb->read(fd, bb->queue, sizeof(bb->queue)) <= 0) break;
if(rb->read(fd, &bb->elapsedlvl, sizeof(bb->elapsedlvl)) <= 0) break;
if(rb->read(fd, bb->playboard, sizeof(bb->playboard)) <= 0) break;
bb->resume = true;
loaded = true;
break;
}
rb->close(fd);
/* delete saved file */
rb->remove(SAVE_FILE);
return loaded;
}
/*****************************************************************************
* bubbles_savegame() saves the current game state.
******************************************************************************/
static void bubbles_savegame(struct game_context* bb) {
int fd;
/* write out the game state to the save file */
fd = rb->open(SAVE_FILE, O_WRONLY|O_CREAT);
rb->write(fd, &bb->score, sizeof(bb->score));
rb->write(fd, &bb->level, sizeof(bb->level));
rb->write(fd, &bb->angle, sizeof(bb->angle));
rb->write(fd, &bb->shots, sizeof(bb->shots));
rb->write(fd, &bb->compress, sizeof(bb->compress));
rb->write(fd, &bb->onboardcnt, sizeof(bb->onboardcnt));
rb->write(fd, bb->onboard, sizeof(bb->onboard));
rb->write(fd, &bb->nextinq, sizeof(bb->nextinq));
rb->write(fd, bb->queue, sizeof(bb->queue));
rb->write(fd, &bb->elapsedlvl, sizeof(bb->elapsedlvl));
rb->write(fd, bb->playboard, sizeof(bb->playboard));
rb->close(fd);
bb->resume = true;
}
/*****************************************************************************
* bubbles_setcolors() set the foreground and background colors.
******************************************************************************/
static inline void bubbles_setcolors(void) {
#ifdef HAVE_LCD_COLOR
rb->lcd_set_background(LCD_RGBPACK(181,181,222));
rb->lcd_set_foreground(LCD_BLACK);
#endif
}
/*****************************************************************************
* bubbles_callback() is the default event handler callback which is called
* on usb connect and shutdown.
******************************************************************************/
static void bubbles_callback(void* param) {
struct game_context* bb = (struct game_context*) param;
if(bb->dirty) {
rb->splash(HZ/2, true, "Saving high scores...");
bubbles_savescores(bb);
}
}
/*****************************************************************************
* bubbles_handlebuttons() handles button events during a game.
******************************************************************************/
static int bubbles_handlebuttons(struct game_context* bb, bool animblock,
int timeout) {
int button;
int buttonres;
long start;
button = rb->button_get_w_tmo(timeout);
#ifdef HAS_BUTTON_HOLD
if (rb->button_hold())
button = BUBBLES_START;
#endif
switch(button){
case (BUBBLES_LEFT|BUTTON_REPEAT):
if(bb->angle > MIN_ANGLE) bb->angle -= 4;
case BUBBLES_LEFT: /* change angle to the left */
if(bb->angle > MIN_ANGLE) bb->angle -= 2;
break;
case (BUBBLES_RIGHT|BUTTON_REPEAT):
if(bb->angle < MAX_ANGLE) bb->angle += 4;
case BUBBLES_RIGHT: /* change angle to the right */
if(bb->angle < MAX_ANGLE) bb->angle += 2;
break;
case BUBBLES_SELECT: /* fire the shot */
if(!animblock) {
bb->elapsedlvl += bb->elapsedshot;
bb->elapsedshot = 0;
buttonres = bubbles_fire(bb);
if(buttonres != BB_NONE) return buttonres;
buttonres = bubbles_checklevel(bb);
if(buttonres != BB_NONE) return buttonres;
bb->startedshot = *rb->current_tick;
}
break;
case BUBBLES_START: /* pause the game */
start = *rb->current_tick;
rb->splash(1, true, "Paused");
while(rb->button_get(true) != (BUBBLES_START));
bb->startedshot += *rb->current_tick-start;
bubbles_drawboard(bb);
rb->lcd_update();
break;
case BUBBLES_RESUME: /* save and end the game */
if(!animblock) {
rb->splash(HZ/2, true, "Saving game...");
bubbles_savegame(bb);
return BB_END;
}
break;
#ifdef BUBBLES_RC_QUIT
case BUBBLES_RC_QUIT:
#endif
case BUBBLES_QUIT: /* end the game */
return BB_END;
case BUTTON_NONE: /* no button pressed */
break;
default:
if(rb->default_event_handler_ex(button, bubbles_callback,
(void*) bb) == SYS_USB_CONNECTED)
return BB_USB;
break;
}
return BB_NONE;
}
/*****************************************************************************
* bubbles() is the main game subroutine, it returns the final game status.
******************************************************************************/
static int bubbles(struct game_context* bb) {
int i;
int w, h;
int button;
int buttonres;
unsigned int startlevel = 0;
char *title = "Bubbles";
bool startgame = false;
bool showscores = false;
long timeout;
bubbles_setcolors();
/* don't resume by default */
bb->resume = false;
/********************
* menu *
********************/
while(!startgame){
char str[30];
rb->lcd_clear_display();
if(!showscores) {
/* welcome screen to display key bindings */
rb->lcd_getstringsize(title, &w, &h);
rb->lcd_putsxy((LCD_WIDTH-w)/2, 0, title);
#if (CONFIG_KEYPAD == IRIVER_H100_PAD) || (CONFIG_KEYPAD == IRIVER_H300_PAD)
rb->lcd_puts(0, 2, "ON to start/pause");
rb->lcd_puts(0, 3, "MODE to save/resume");
rb->lcd_puts(0, 4, "OFF to exit");
rb->lcd_puts(0, 5, "SELECT to fire");
rb->lcd_puts(0, 6, " and show high scores");
rb->lcd_puts(0, 7, "LEFT/RIGHT to aim");
rb->lcd_puts(0, 8, "UP/DOWN to change level");
#elif (CONFIG_KEYPAD == IPOD_3G_PAD) || (CONFIG_KEYPAD == IPOD_4G_PAD)
rb->lcd_puts(0, 2, "PLAY to start/pause");
rb->lcd_puts(0, 3, "LEFT+RIGHT to save/resume");
rb->lcd_puts(0, 4, "MENU to exit");
rb->lcd_puts(0, 5, "SELECT to fire");
rb->lcd_puts(0, 6, " and show high scores");
rb->lcd_puts(0, 7, "SCROLL to aim");
rb->lcd_puts(0, 8, " and to change level");
#elif CONFIG_KEYPAD == IAUDIO_X5_PAD
rb->lcd_puts(0, 2, "PLAY to start/pause");
rb->lcd_puts(0, 3, "REC to save/resume");
rb->lcd_puts(0, 4, "POWER to exit");
rb->lcd_puts(0, 5, "SELECT to fire");
rb->lcd_puts(0, 6, " and show high scores");
rb->lcd_puts(0, 7, "LEFT/RIGHT to aim");
rb->lcd_puts(0, 8, "UP/DOWN to change level");
#elif CONFIG_KEYPAD == GIGABEAT_PAD
rb->lcd_puts(0, 2, "POWER to start/pause");
rb->lcd_puts(0, 3, "MENU to save/resume");
rb->lcd_puts(0, 4, "A to exit");
rb->lcd_puts(0, 5, "SELECT to fire");
rb->lcd_puts(0, 6, " and show high scores");
rb->lcd_puts(0, 7, "LEFT/RIGHT to aim");
rb->lcd_puts(0, 8, "UP/DOWN to change level");
#elif CONFIG_KEYPAD == RECORDER_PAD
rb->lcd_puts_scroll(0, 2, "ON to start/pause, "
"F1 to save/resume, "
"OFF to exit, "
"PLAY to fire and show high scores, "
"LEFT/RIGHT to aim, "
"UP/DOWN to change level.");
#elif CONFIG_KEYPAD == ONDIO_PAD
rb->lcd_puts_scroll(0, 2, "MODE to start/pause, "
"DOWN to save/resume, "
"OFF to exit, "
"UP to fire and show high scores, "
"LEFT/RIGHT to aim and to change level.");
#endif
#if LCD_WIDTH >= 138
rb->snprintf(str, 28, "Start on level %d of %d", startlevel+1,
bb->highlevel+1);
#else
rb->snprintf(str, 28, "Start on lvl %d/%d", startlevel+1,
bb->highlevel+1);
#endif
rb->lcd_puts(0, MIN(TEXT_LINES-3,10), str);
rb->lcd_puts(0, MIN(TEXT_LINES-2,12), "High Score:");
rb->snprintf(str, 30, "%d, Lvl %d",
bb->highscores[0].score, bb->highscores[0].level);
rb->lcd_puts(2, MIN(TEXT_LINES-1,13), str);
} else {
/* show high scores */
rb->snprintf(str, 12, "High Scores");
rb->lcd_getstringsize(str, &w, &h);
rb->lcd_putsxy((LCD_WIDTH-w)/2, 0, str);
for(i=0; i<NUM_SCORES; i++) {
rb->snprintf(str, 30, "#%02d: %d, Lvl %d", i+1,
bb->highscores[i].score, bb->highscores[i].level);
rb->lcd_puts(0, i+2, str);
}
}
rb->lcd_update();
/* handle menu button presses */
button = rb->button_get(true);
switch(button){
case BUBBLES_START: /* start playing */
bb->level = startlevel;
startgame = true;
break;
#ifdef BUBBLES_RC_QUIT
case BUBBLES_RC_QUIT:
#endif
case BUBBLES_QUIT: /* quit program */
if(showscores) {
showscores = false;
break;
}
return BB_QUIT;
case BUBBLES_RESUME: /* resume game */
if(!bubbles_loadgame(bb)) {
rb->splash(HZ*2, true, "Nothing to resume");
} else {
startgame = true;
}
break;
case BUBBLES_SELECT: /* toggle high scores */
showscores = !showscores;
break;
case (BUBBLES_UP|BUTTON_REPEAT):
case BUBBLES_UP: /* increase starting level */
if(startlevel >= bb->highlevel) {
startlevel = 0;
} else {
startlevel++;
}
break;
case (BUBBLES_DOWN|BUTTON_REPEAT):
case BUBBLES_DOWN: /* decrease starting level */
if(startlevel <= 0) {
startlevel = bb->highlevel;
} else {
startlevel--;
}
break;
default:
if(rb->default_event_handler_ex(button, bubbles_callback,
(void*) bb) == SYS_USB_CONNECTED)
return BB_USB;
break;
}
}
/********************
* init *
********************/
bubbles_init(bb);
bubbles_drawboard(bb);
rb->lcd_update();
/**********************
* play *
**********************/
bb->startedshot = *rb->current_tick;
while(true) {
/* refresh the board */
bubbles_drawboard(bb);
rb->lcd_update();
/* manange idle framerate */
bb->elapsedshot = *rb->current_tick-bb->startedshot;
if(MAX_SHOTTIME-bb->elapsedshot < HZ/2) {
timeout = MAX_SHOTTIME-bb->elapsedshot;
} else {
timeout = HZ/2;
}
/* handle button events */
buttonres = bubbles_handlebuttons(bb, false, timeout);
if(buttonres != BB_NONE) return buttonres;
/* handle timing */
bb->elapsedshot = *rb->current_tick-bb->startedshot;
if(bb->elapsedshot > MAX_SHOTTIME) {
bb->elapsedlvl += bb->elapsedshot;
bb->elapsedshot = 0;
buttonres = bubbles_fire(bb);
if(buttonres != BB_NONE) return buttonres;
buttonres = bubbles_checklevel(bb);
if(buttonres != BB_NONE) return buttonres;
bb->startedshot = *rb->current_tick;
}
}
}
/*****************************************************************************
* plugin entry point.
******************************************************************************/
enum plugin_status plugin_start(struct plugin_api* api, void* parameter) {
struct game_context bb;
bool exit = false;
int position;
/* plugin init */
(void)parameter;
rb = api;
/* end of plugin init */
/* more init */
xlcd_init(rb);
/* load files */
rb->splash(0, true, "Loading...");
bubbles_loadscores(&bb);
rb->lcd_clear_display();
/* start app */
rb->lcd_setfont(FONT_SYSFIXED);
while(!exit) {
switch(bubbles(&bb)){
char str[19];
case BB_WIN:
rb->splash(HZ*2, true, "You Win!");
if((position = bubbles_recordscore(&bb))) {
rb->snprintf(str, 19, "New high score #%d!", position);
rb->splash(HZ*2, true, str);
}
break;
case BB_LOSE:
rb->splash(HZ*2, true, "Game Over");
/* fall through to BB_END */
case BB_END:
if(!bb.resume) {
/* record high level */
if(bb.level-1 > bb.highlevel) {
bb.highlevel = bb.level-1;
bb.dirty = true;
}
/* record high score */
if((position = bubbles_recordscore(&bb))) {
rb->snprintf(str, 19, "New high score #%d!", position);
rb->splash(HZ*2, true, str);
}
}
break;
case BB_USB:
rb->lcd_setfont(FONT_UI);
return PLUGIN_USB_CONNECTED;
case BB_QUIT:
if(bb.dirty) {
rb->splash(HZ/2, true, "Saving high scores...");
bubbles_savescores(&bb);
}
exit = true;
break;
default:
break;
}
}
rb->lcd_setfont(FONT_UI);
return PLUGIN_OK;
}
#endif