From ea4947a95f2478fd2d72c0af43829ebb6c4328a3 Mon Sep 17 00:00:00 2001 From: Adam Boot Date: Mon, 20 Mar 2006 03:06:07 +0000 Subject: New game plugin: bubbles, initial commit git-svn-id: svn://svn.rockbox.org/rockbox/trunk@9126 a1c6a512-1295-4272-9138-f99709370657 --- apps/plugins/SOURCES | 6 +- apps/plugins/bitmaps/mono/SOURCES | 12 + .../bitmaps/mono/bubbles_bubble.160x128x1.bmp | Bin 0 -> 110 bytes .../bitmaps/mono/bubbles_bubble.220x176x1.bmp | Bin 0 -> 126 bytes .../bitmaps/mono/bubbles_bubble.320x240x1.bmp | Bin 0 -> 150 bytes apps/plugins/bitmaps/native/SOURCES | 53 +- .../bitmaps/native/bubbles_emblem.160x128x16.bmp | Bin 0 -> 1590 bytes .../bitmaps/native/bubbles_emblem.160x128x2.bmp | Bin 0 -> 1590 bytes .../bitmaps/native/bubbles_emblem.220x176x16.bmp | Bin 0 -> 3510 bytes .../bitmaps/native/bubbles_emblem.320x240x16.bmp | Bin 0 -> 6198 bytes .../bitmaps/native/bubbles_left.160x128x16.bmp | Bin 0 -> 12854 bytes .../bitmaps/native/bubbles_left.176x132x16.bmp | Bin 0 -> 15894 bytes .../bitmaps/native/bubbles_left.220x176x16.bmp | Bin 0 -> 24694 bytes .../bitmaps/native/bubbles_left.240x320x16.bmp | Bin 0 -> 53814 bytes .../bitmaps/native/bubbles_left.320x240x16.bmp | Bin 0 -> 51894 bytes .../bitmaps/native/bubbles_right.160x128x16.bmp | Bin 0 -> 12342 bytes .../bitmaps/native/bubbles_right.176x132x16.bmp | Bin 0 -> 16422 bytes .../bitmaps/native/bubbles_right.220x176x16.bmp | Bin 0 -> 25398 bytes .../bitmaps/native/bubbles_right.240x320x16.bmp | Bin 0 -> 55094 bytes .../bitmaps/native/bubbles_right.320x240x16.bmp | Bin 0 -> 52854 bytes apps/plugins/bubbles.c | 2537 ++++++++++++++++++++ 21 files changed, 2592 insertions(+), 16 deletions(-) create mode 100755 apps/plugins/bitmaps/mono/bubbles_bubble.160x128x1.bmp create mode 100755 apps/plugins/bitmaps/mono/bubbles_bubble.220x176x1.bmp create mode 100755 apps/plugins/bitmaps/mono/bubbles_bubble.320x240x1.bmp create mode 100755 apps/plugins/bitmaps/native/bubbles_emblem.160x128x16.bmp create mode 100755 apps/plugins/bitmaps/native/bubbles_emblem.160x128x2.bmp create mode 100755 apps/plugins/bitmaps/native/bubbles_emblem.220x176x16.bmp create mode 100755 apps/plugins/bitmaps/native/bubbles_emblem.320x240x16.bmp create mode 100755 apps/plugins/bitmaps/native/bubbles_left.160x128x16.bmp create mode 100755 apps/plugins/bitmaps/native/bubbles_left.176x132x16.bmp create mode 100755 apps/plugins/bitmaps/native/bubbles_left.220x176x16.bmp create mode 100755 apps/plugins/bitmaps/native/bubbles_left.240x320x16.bmp create mode 100755 apps/plugins/bitmaps/native/bubbles_left.320x240x16.bmp create mode 100755 apps/plugins/bitmaps/native/bubbles_right.160x128x16.bmp create mode 100755 apps/plugins/bitmaps/native/bubbles_right.176x132x16.bmp create mode 100755 apps/plugins/bitmaps/native/bubbles_right.220x176x16.bmp create mode 100755 apps/plugins/bitmaps/native/bubbles_right.240x320x16.bmp create mode 100755 apps/plugins/bitmaps/native/bubbles_right.320x240x16.bmp create mode 100755 apps/plugins/bubbles.c diff --git a/apps/plugins/SOURCES b/apps/plugins/SOURCES index b01641aa17..d851d6a78a 100644 --- a/apps/plugins/SOURCES +++ b/apps/plugins/SOURCES @@ -30,9 +30,10 @@ mandelbrot.c plasma.c #endif -jewels.c bounce.c - +#if (LCD_WIDTH >= 160) && (LCD_HEIGHT >= 128) +bubbles.c +#endif #if (LCD_WIDTH != 138) && (LCD_WIDTH != 128) /* These need adjusting for the Mini's and iRiver if'p screen */ brickmania.c @@ -41,6 +42,7 @@ calculator.c chip8.c demystify.c flipit.c +jewels.c minesweeper.c oscilloscope.c pong.c diff --git a/apps/plugins/bitmaps/mono/SOURCES b/apps/plugins/bitmaps/mono/SOURCES index 0ee98f9c0f..34f0f4254b 100644 --- a/apps/plugins/bitmaps/mono/SOURCES +++ b/apps/plugins/bitmaps/mono/SOURCES @@ -1,5 +1,17 @@ #ifdef HAVE_LCD_BITMAP +/* Bubbles */ +#if (LCD_WIDTH == 160) && (LCD_HEIGHT == 128) +bubbles_bubble.160x128x1.bmp +#elif (LCD_WIDTH == 176) && (LCD_HEIGHT == 132) +bubbles_bubble.160x128x1.bmp +#elif ((LCD_WIDTH == 220) && (LCD_HEIGHT == 176)) || \ + ((LCD_WIDTH == 240) && (LCD_HEIGHT == 320)) +bubbles_bubble.220x176x1.bmp +#elif (LCD_WIDTH == 320) && (LCD_HEIGHT == 240) +bubbles_bubble.320x240x1.bmp +#endif + /* BrickMania */ #if (LCD_WIDTH == 112) && (LCD_HEIGHT == 64) diff --git a/apps/plugins/bitmaps/mono/bubbles_bubble.160x128x1.bmp b/apps/plugins/bitmaps/mono/bubbles_bubble.160x128x1.bmp new file mode 100755 index 0000000000..8a3a514247 Binary files /dev/null and b/apps/plugins/bitmaps/mono/bubbles_bubble.160x128x1.bmp differ diff --git a/apps/plugins/bitmaps/mono/bubbles_bubble.220x176x1.bmp b/apps/plugins/bitmaps/mono/bubbles_bubble.220x176x1.bmp new file mode 100755 index 0000000000..da84ba796c Binary files /dev/null and b/apps/plugins/bitmaps/mono/bubbles_bubble.220x176x1.bmp differ diff --git a/apps/plugins/bitmaps/mono/bubbles_bubble.320x240x1.bmp b/apps/plugins/bitmaps/mono/bubbles_bubble.320x240x1.bmp new file mode 100755 index 0000000000..2ba692b178 Binary files /dev/null and b/apps/plugins/bitmaps/mono/bubbles_bubble.320x240x1.bmp differ diff --git a/apps/plugins/bitmaps/native/SOURCES b/apps/plugins/bitmaps/native/SOURCES index 6b6896d263..b267fc9dfa 100644 --- a/apps/plugins/bitmaps/native/SOURCES +++ b/apps/plugins/bitmaps/native/SOURCES @@ -1,24 +1,28 @@ #ifdef HAVE_LCD_BITMAP -/* Bejeweled */ -#if (LCD_WIDTH == 112) && (LCD_HEIGHT == 64) -jewels.112x64x1.bmp -#elif (LCD_WIDTH == 128) && (LCD_HEIGHT == 64) -jewels.112x64x1.bmp -#elif (LCD_WIDTH == 138) && (LCD_HEIGHT == 110) -jewels.138x110x1.bmp -#elif (LCD_WIDTH == 160) && (LCD_HEIGHT == 128) && !defined(HAVE_LCD_COLOR) -jewels.160x128x1.bmp +/* Bubbles */ +#if (LCD_WIDTH == 160) && (LCD_HEIGHT == 128) && !defined(HAVE_LCD_COLOR) +bubbles_emblem.160x128x2.bmp #elif (LCD_WIDTH == 160) && (LCD_HEIGHT == 128) && defined(HAVE_LCD_COLOR) -jewels.160x128x16.bmp +bubbles_emblem.160x128x16.bmp +bubbles_left.160x128x16.bmp +bubbles_right.160x128x16.bmp #elif (LCD_WIDTH == 176) && (LCD_HEIGHT == 132) -jewels.160x128x16.bmp +bubbles_emblem.160x128x16.bmp +bubbles_left.176x132x16.bmp +bubbles_right.176x132x16.bmp #elif (LCD_WIDTH == 220) && (LCD_HEIGHT == 176) -jewels.220x176x16.bmp +bubbles_emblem.220x176x16.bmp +bubbles_left.220x176x16.bmp +bubbles_right.220x176x16.bmp #elif (LCD_WIDTH == 240) && (LCD_HEIGHT == 320) -jewels.220x176x16.bmp +bubbles_emblem.220x176x16.bmp +bubbles_left.240x320x16.bmp +bubbles_right.240x320x16.bmp #elif (LCD_WIDTH == 320) && (LCD_HEIGHT == 240) -jewels.320x240x16.bmp +bubbles_emblem.320x240x16.bmp +bubbles_left.320x240x16.bmp +bubbles_right.320x240x16.bmp #endif /* ChessBox */ @@ -34,6 +38,27 @@ chessbox_pieces.128x128x1.bmp chessbox_pieces.64x64x1.bmp #endif +/* Jewels */ +#if (LCD_WIDTH == 112) && (LCD_HEIGHT == 64) +jewels.112x64x1.bmp +#elif (LCD_WIDTH == 128) && (LCD_HEIGHT == 64) +jewels.112x64x1.bmp +#elif (LCD_WIDTH == 138) && (LCD_HEIGHT == 110) +jewels.138x110x1.bmp +#elif (LCD_WIDTH == 160) && (LCD_HEIGHT == 128) && !defined(HAVE_LCD_COLOR) +jewels.160x128x1.bmp +#elif (LCD_WIDTH == 160) && (LCD_HEIGHT == 128) && defined(HAVE_LCD_COLOR) +jewels.160x128x16.bmp +#elif (LCD_WIDTH == 176) && (LCD_HEIGHT == 132) +jewels.160x128x16.bmp +#elif (LCD_WIDTH == 220) && (LCD_HEIGHT == 176) +jewels.220x176x16.bmp +#elif (LCD_WIDTH == 240) && (LCD_HEIGHT == 320) +jewels.220x176x16.bmp +#elif (LCD_WIDTH == 320) && (LCD_HEIGHT == 240) +jewels.320x240x16.bmp +#endif + /* Solitaire */ #ifdef HAVE_LCD_COLOR solitaire_cardback.220x176x16.bmp diff --git a/apps/plugins/bitmaps/native/bubbles_emblem.160x128x16.bmp b/apps/plugins/bitmaps/native/bubbles_emblem.160x128x16.bmp new file mode 100755 index 0000000000..cda6ef4f74 Binary files /dev/null and b/apps/plugins/bitmaps/native/bubbles_emblem.160x128x16.bmp differ diff --git a/apps/plugins/bitmaps/native/bubbles_emblem.160x128x2.bmp b/apps/plugins/bitmaps/native/bubbles_emblem.160x128x2.bmp new file mode 100755 index 0000000000..ea803f6da7 Binary files /dev/null and b/apps/plugins/bitmaps/native/bubbles_emblem.160x128x2.bmp differ diff --git a/apps/plugins/bitmaps/native/bubbles_emblem.220x176x16.bmp b/apps/plugins/bitmaps/native/bubbles_emblem.220x176x16.bmp new file mode 100755 index 0000000000..92cb7d1be1 Binary files /dev/null and b/apps/plugins/bitmaps/native/bubbles_emblem.220x176x16.bmp differ diff --git a/apps/plugins/bitmaps/native/bubbles_emblem.320x240x16.bmp b/apps/plugins/bitmaps/native/bubbles_emblem.320x240x16.bmp new file mode 100755 index 0000000000..f32aff410b Binary files /dev/null and b/apps/plugins/bitmaps/native/bubbles_emblem.320x240x16.bmp differ diff --git a/apps/plugins/bitmaps/native/bubbles_left.160x128x16.bmp b/apps/plugins/bitmaps/native/bubbles_left.160x128x16.bmp new file mode 100755 index 0000000000..15f78cfdf2 Binary files /dev/null and b/apps/plugins/bitmaps/native/bubbles_left.160x128x16.bmp differ diff --git a/apps/plugins/bitmaps/native/bubbles_left.176x132x16.bmp b/apps/plugins/bitmaps/native/bubbles_left.176x132x16.bmp new file mode 100755 index 0000000000..dbad0543a3 Binary files /dev/null and b/apps/plugins/bitmaps/native/bubbles_left.176x132x16.bmp differ diff --git a/apps/plugins/bitmaps/native/bubbles_left.220x176x16.bmp b/apps/plugins/bitmaps/native/bubbles_left.220x176x16.bmp new file mode 100755 index 0000000000..cbe38ca53c Binary files /dev/null and b/apps/plugins/bitmaps/native/bubbles_left.220x176x16.bmp differ diff --git a/apps/plugins/bitmaps/native/bubbles_left.240x320x16.bmp b/apps/plugins/bitmaps/native/bubbles_left.240x320x16.bmp new file mode 100755 index 0000000000..25cf12ddbf Binary files /dev/null and b/apps/plugins/bitmaps/native/bubbles_left.240x320x16.bmp differ diff --git a/apps/plugins/bitmaps/native/bubbles_left.320x240x16.bmp b/apps/plugins/bitmaps/native/bubbles_left.320x240x16.bmp new file mode 100755 index 0000000000..194bea0ff0 Binary files /dev/null and b/apps/plugins/bitmaps/native/bubbles_left.320x240x16.bmp differ diff --git a/apps/plugins/bitmaps/native/bubbles_right.160x128x16.bmp b/apps/plugins/bitmaps/native/bubbles_right.160x128x16.bmp new file mode 100755 index 0000000000..d065365e82 Binary files /dev/null and b/apps/plugins/bitmaps/native/bubbles_right.160x128x16.bmp differ diff --git a/apps/plugins/bitmaps/native/bubbles_right.176x132x16.bmp b/apps/plugins/bitmaps/native/bubbles_right.176x132x16.bmp new file mode 100755 index 0000000000..1093c17b2b Binary files /dev/null and b/apps/plugins/bitmaps/native/bubbles_right.176x132x16.bmp differ diff --git a/apps/plugins/bitmaps/native/bubbles_right.220x176x16.bmp b/apps/plugins/bitmaps/native/bubbles_right.220x176x16.bmp new file mode 100755 index 0000000000..c0d8bef8ab Binary files /dev/null and b/apps/plugins/bitmaps/native/bubbles_right.220x176x16.bmp differ diff --git a/apps/plugins/bitmaps/native/bubbles_right.240x320x16.bmp b/apps/plugins/bitmaps/native/bubbles_right.240x320x16.bmp new file mode 100755 index 0000000000..7f08389cc0 Binary files /dev/null and b/apps/plugins/bitmaps/native/bubbles_right.240x320x16.bmp differ diff --git a/apps/plugins/bitmaps/native/bubbles_right.320x240x16.bmp b/apps/plugins/bitmaps/native/bubbles_right.320x240x16.bmp new file mode 100755 index 0000000000..5872fdc8ec Binary files /dev/null and b/apps/plugins/bitmaps/native/bubbles_right.320x240x16.bmp differ diff --git a/apps/plugins/bubbles.c b/apps/plugins/bubbles.c new file mode 100755 index 0000000000..9e523fa744 --- /dev/null +++ b/apps/plugins/bubbles.c @@ -0,0 +1,2537 @@ +/*************************************************************************** +* __________ __ ___. +* 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 BB_HEIGHT-2 + +/* animation fps */ +#define MAX_FPS 20 + +/* various amount */ +#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 + +#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 + +#else + #error BUBBLES: Unsupported keypad +#endif + +/* bubbles will consume height of 10*ROW_HEIGHT+2*(BUBBLE_SZ-1)+BUBBLE_SZ/2 */ +/* 24x24 bubbles (iPod Video) */ +#if (LCD_HEIGHT == 240) && (LCD_WIDTH == 320) +#define BUBBLE_SZ 22 +#define EMBLEM_SZ 16 +#define XOFS 72 +#define ROW_HEIGHT 18 +#define ROW_INDENT 13 + +/* 16x16 bubbles (H300, iPod Color) */ +#elif (LCD_HEIGHT == 176) && (LCD_WIDTH == 220) +#define BUBBLE_SZ 16 +#define EMBLEM_SZ 12 +#define XOFS 46 +#define ROW_HEIGHT 14 +#define ROW_INDENT 8 + +/* 16x16 bubbles (Gigabeat) */ +#elif (LCD_HEIGHT == 320) && (LCD_WIDTH == 240) +#define BUBBLE_SZ 16 +#define EMBLEM_SZ 12 +#define XOFS 56 +#define ROW_HEIGHT 14 +#define ROW_INDENT 8 + +/* 12x12 bubbles (iPod Nano) */ +#elif (LCD_HEIGHT == 132) && (LCD_WIDTH == 176) +#define BUBBLE_SZ 12 +#define EMBLEM_SZ 8 +#define XOFS 40 +#define ROW_HEIGHT 10 +#define ROW_INDENT 6 + +/* 12x12 bubbles (H100, iAudio X5, iPod 3G, iPod 4G grayscale) */ +#elif (LCD_HEIGHT == 128) && (LCD_WIDTH == 160) +#define BUBBLE_SZ 12 +#define EMBLEM_SZ 8 +#define XOFS 33 +#define ROW_HEIGHT 10 +#define ROW_INDENT 6 + +#else + #error BUBBLES: Unsupported LCD type +#endif + +/* shot position */ +#define SHOTX XOFS+ROW_INDENT+BUBBLE_SZ*3 +#define SHOTY ROW_HEIGHT*(BB_HEIGHT-1)+BUBBLE_SZ/2 + +/* collision distance squared */ +#define MIN_DISTANCE ((BUBBLE_SZ*8)/10)*((BUBBLE_SZ*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 + * 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; + 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 + * 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; + 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); +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; ilevel-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; iplayboard[i][j].type = -1; + } + } + + /* fill first bubbles in shot queue */ + bubbles_getonboard(bb); + for(i=0; iqueue[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; iplayboard[i][j].type >= 0) { + found = false; + + for(k=0; konboardcnt; 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_SZ, 0, + LCD_WIDTH-(XOFS-1+BB_WIDTH*BUBBLE_SZ), LCD_HEIGHT); +#endif + + /* display play board */ + for(i=0; iplayboard[i][j].type >= 0 && !bb->playboard[i][j].delete) { + rb->lcd_bitmap_part(bubbles_emblem, + 0, EMBLEM_SZ*bb->playboard[i][j].type, EMBLEM_SZ, + XOFS+indent+BUBBLE_SZ*j+(BUBBLE_SZ-EMBLEM_SZ)/2, + ROW_HEIGHT*i+(BUBBLE_SZ-EMBLEM_SZ)/2+bb->compress*ROW_HEIGHT, + EMBLEM_SZ, EMBLEM_SZ); + rb->lcd_set_drawmode(DRMODE_FG); + rb->lcd_mono_bitmap((const unsigned char *)bubbles_bubble, + XOFS+indent+BUBBLE_SZ*j, + ROW_HEIGHT*i+bb->compress*ROW_HEIGHT, + BUBBLE_SZ, BUBBLE_SZ); + rb->lcd_set_drawmode(DRMODE_SOLID); + } + } + } + + /* display bubble to be shot */ + rb->lcd_bitmap_part(bubbles_emblem, + 0, EMBLEM_SZ*bb->queue[bb->nextinq], EMBLEM_SZ, + SHOTX+(BUBBLE_SZ-EMBLEM_SZ)/2, + SHOTY+(BUBBLE_SZ-EMBLEM_SZ)/2, + EMBLEM_SZ, EMBLEM_SZ); + rb->lcd_set_drawmode(DRMODE_FG); + rb->lcd_mono_bitmap((const unsigned char *)bubbles_bubble, + SHOTX, SHOTY, + BUBBLE_SZ, BUBBLE_SZ); + rb->lcd_set_drawmode(DRMODE_SOLID); + + /* display next bubble to be shot */ + rb->lcd_bitmap_part(bubbles_emblem, + 0, EMBLEM_SZ*bb->queue[(bb->nextinq+1)%NUM_QUEUE], EMBLEM_SZ, + XOFS/2-BUBBLE_SZ/2+(BUBBLE_SZ-EMBLEM_SZ)/2, + SHOTY+(BUBBLE_SZ-EMBLEM_SZ)/2, + EMBLEM_SZ, EMBLEM_SZ); + rb->lcd_set_drawmode(DRMODE_FG); + rb->lcd_mono_bitmap((const unsigned char *)bubbles_bubble, + XOFS/2-BUBBLE_SZ/2, SHOTY, + BUBBLE_SZ, BUBBLE_SZ); + 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_SZ*BB_WIDTH, 0, LCD_HEIGHT); +#endif + rb->lcd_hline(XOFS, XOFS+BUBBLE_SZ*BB_WIDTH-1, bb->compress*ROW_HEIGHT-1); + rb->lcd_hline(XOFS, XOFS+BUBBLE_SZ*BB_WIDTH-1, + ROW_HEIGHT*(BB_HEIGHT-2)+BUBBLE_SZ); + + /* draw arrow */ + tipx = SHOTX+BUBBLE_SZ/2+(((sin(bb->angle)>>4)*BUBBLE_SZ*3/2)>>10); + tipy = SHOTY+BUBBLE_SZ/2-(((cos(bb->angle)>>4)*BUBBLE_SZ*3/2)>>10); + + rb->lcd_drawline(SHOTX+BUBBLE_SZ/2+(((sin(bb->angle)>>4)*BUBBLE_SZ/2)>>10), + SHOTY+BUBBLE_SZ/2-(((cos(bb->angle)>>4)*BUBBLE_SZ/2)>>10), + tipx, tipy); + xlcd_filltriangle(tipx, tipy, + tipx+(((sin(bb->angle-135)>>4)*BUBBLE_SZ/3)>>10), + tipy-(((cos(bb->angle-135)>>4)*BUBBLE_SZ/3)>>10), + tipx+(((sin(bb->angle+135)>>4)*BUBBLE_SZ/3)>>10), + tipy-(((cos(bb->angle+135)>>4)*BUBBLE_SZ/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_SZ)/3; + shotyinc = ((-1*(cos(bb->angle)>>4))*BUBBLE_SZ)/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_SZ) { + shotxofs -= 2*((((SHOTX)<<10)+shotxofs)-((XOFS<<10)+(((BB_WIDTH-1)*BUBBLE_SZ)<<10))); + shotxdirec *= -1; + } + + tempxofs = shotxofs>>10; + tempyofs = shotyofs>>10; + + /* display shot */ + bubbles_drawboard(bb); + rb->lcd_bitmap_part(bubbles_emblem, 0, EMBLEM_SZ*bubblecur, EMBLEM_SZ, + SHOTX+tempxofs+(BUBBLE_SZ-EMBLEM_SZ)/2, + SHOTY+tempyofs+(BUBBLE_SZ-EMBLEM_SZ)/2, + EMBLEM_SZ, EMBLEM_SZ); + rb->lcd_set_drawmode(DRMODE_FG); + rb->lcd_mono_bitmap((const unsigned char *)bubbles_bubble, + SHOTX+tempxofs, SHOTY+tempyofs, + BUBBLE_SZ, BUBBLE_SZ); + rb->lcd_set_drawmode(DRMODE_SOLID); + rb->lcd_update_rect(XOFS, 0, BB_WIDTH*BUBBLE_SZ, 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_SZ/2))/BUBBLE_SZ; + if(nearcol >= BB_WIDTH-1) nearcol = BB_WIDTH-2; + } else { /* even row */ + nearcol = ((SHOTX+tempxofs)-XOFS+(BUBBLE_SZ/2))/BUBBLE_SZ; + 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); + 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_SZ*(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_SZ*(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_SZ*(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_SZ*(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_SZ*(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_SZ*(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; iplayboard[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 count = 1; + int adj = row%2; + int mytype = bb->playboard[row][col].type; + + bb->playboard[row][col].ingroup = true; + + /* recursively call neighbors */ + if(col-1 >= 0) { + if(bb->playboard[row][col-1].type == mytype && + !bb->playboard[row][col-1].ingroup) { + count += bubbles_searchgroup(bb, row, col-1); + } + } + + if(col-1+adj >= 0) { + if(row-1 >= 0) { + if(bb->playboard[row-1][col-1+adj].type == mytype && + !bb->playboard[row-1][col-1+adj].ingroup) { + count += bubbles_searchgroup(bb, row-1, col-1+adj); + } + } + + if(row+1 < BB_HEIGHT) { + if(bb->playboard[row+1][col-1+adj].type == mytype && + !bb->playboard[row+1][col-1+adj].ingroup) { + count += bubbles_searchgroup(bb, row+1, col-1+adj); + } + } + } + + if(col+adj >= 0) { + if(row-1 >= 0) { + if(bb->playboard[row-1][col+adj].type == mytype && + !bb->playboard[row-1][col+adj].ingroup) { + count += bubbles_searchgroup(bb, row-1, col+adj); + } + } + + if(row+1 < BB_HEIGHT) { + if(bb->playboard[row+1][col+adj].type == mytype && + !bb->playboard[row+1][col+adj].ingroup) { + count += bubbles_searchgroup(bb, row+1, col+adj); + } + } + } + + if(col+1 < BB_WIDTH-adj) { + if(bb->playboard[row][col+1].type == mytype && + !bb->playboard[row][col+1].ingroup) { + count += bubbles_searchgroup(bb, row, col+1); + } + } + + 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; jplayboard[0][j].type >= 0 && !bb->playboard[0][j].ingroup) { + bubbles_anchored(bb, 0, j); + } + } + + /* mark bubbles to be deleted */ + for(i=0; iplayboard[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; iplayboard[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 adj = row%2; + + /* mark bubble */ + bb->playboard[row][col].anchored = true; + + /* recursively call neighbors */ + if(col-1 >= 0) { + if(bb->playboard[row][col-1].type >= 0 && + !bb->playboard[row][col-1].ingroup && + !bb->playboard[row][col-1].anchored) { + bubbles_anchored(bb, row, col-1); + } + } + + if(col-1+adj >= 0) { + if(row-1 >= 0) { + if(bb->playboard[row-1][col-1+adj].type >= 0 && + !bb->playboard[row-1][col-1+adj].ingroup && + !bb->playboard[row-1][col-1+adj].anchored) { + bubbles_anchored(bb, row-1, col-1+adj); + } + } + + if(row+1 < BB_HEIGHT) { + if(bb->playboard[row+1][col-1+adj].type >= 0 && + !bb->playboard[row+1][col-1+adj].ingroup && + !bb->playboard[row+1][col-1+adj].anchored) { + bubbles_anchored(bb, row+1, col-1+adj); + } + } + } + + if(col+adj >= 0) { + if(row-1 >= 0) { + if(bb->playboard[row-1][col+adj].type >= 0 && + !bb->playboard[row-1][col+adj].ingroup && + !bb->playboard[row-1][col+adj].anchored) { + bubbles_anchored(bb, row-1, col+adj); + } + } + + if(row+1 < BB_HEIGHT) { + if(bb->playboard[row+1][col+adj].type >= 0 && + !bb->playboard[row+1][col+adj].ingroup && + !bb->playboard[row+1][col+adj].anchored) { + bubbles_anchored(bb, row+1, col+adj); + } + } + } + + if(col+1 < BB_WIDTH-adj) { + if(bb->playboard[row][col+1].type >= 0 && + !bb->playboard[row][col+1].ingroup && + !bb->playboard[row][col+1].anchored) { + bubbles_anchored(bb, row, col+1); + } + } +} + +/***************************************************************************** +* 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; iplayboard[i][j].delete) { + bb->playboard[i][j].fallx = rb->rand()%25 - 12; + } + } + } + + /* 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; iplayboard[i][j].delete) { + indent = (i%2 ? ROW_INDENT : 0); + xofs = ((bb->playboard[i][j].fallx*count)*BUBBLE_SZ)/48; + yofs = ((count*count - 8*count)*BUBBLE_SZ)/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_SZ*bb->playboard[i][j].type, EMBLEM_SZ, + XOFS+indent+BUBBLE_SZ*j+(BUBBLE_SZ-EMBLEM_SZ)/2+xofs, + ROW_HEIGHT*i+(BUBBLE_SZ-EMBLEM_SZ)/2+bb->compress*ROW_HEIGHT+yofs, + EMBLEM_SZ, EMBLEM_SZ); + rb->lcd_set_drawmode(DRMODE_FG); + rb->lcd_mono_bitmap( + (const unsigned char *)bubbles_bubble, + XOFS+indent+BUBBLE_SZ*j+xofs, + ROW_HEIGHT*i+bb->compress*ROW_HEIGHT+yofs, + BUBBLE_SZ, BUBBLE_SZ); + 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); + 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; jplayboard[BB_HEIGHT-1-i][j].type >= 0) return BB_LOSE; + } + } + + /* check for bubbles above cut off point */ + for(i=0; icompress; i++) { + for(j=0; jplayboard[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= 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 button; + int buttonres; + + button = rb->button_get(false); + 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->elapsedshot = 0; + buttonres = bubbles_fire(bb); + if(buttonres != BB_NONE) return buttonres; + buttonres = bubbles_checklevel(bb); + if(buttonres != BB_NONE) return buttonres; + } + break; + + case BUBBLES_START: /* pause the game */ + rb->splash(1, true, "Paused"); + while(rb->button_get(true) != (BUBBLES_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; + + 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 str[30]; + char *title = "Bubbles"; + bool startgame = false; + bool showscores = false; + long lasttick, currenttick; + + bubbles_setcolors(); + + /* don't resume by default */ + bb->resume = false; + + /******************** + * menu * + ********************/ + while(!startgame){ + 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"); +#endif + rb->snprintf(str, 28, "Start on level %d of %d", startlevel+1, bb->highlevel+1); + rb->lcd_puts(0, 10, str); + rb->lcd_puts(0, 12, "High Score:"); + rb->snprintf(str, 30, "%d, Lvl %d", + bb->highscores[0].score, bb->highscores[0].level); + rb->lcd_puts(2, 13, str); + } else { + /* show high scores */ + rb->snprintf(str, 12, "%s", "High Scores"); + rb->lcd_getstringsize(str, &w, &h); + rb->lcd_putsxy((LCD_WIDTH-w)/2, 0, str); + + for(i=0; isnprintf(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; + + 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 * + **********************/ + lasttick = *rb->current_tick; + + while(true) { + /* refresh the board */ + bubbles_drawboard(bb); + rb->lcd_update(); + + /* handle button events */ + buttonres = bubbles_handlebuttons(bb, false); + if(buttonres != BB_NONE) return buttonres; + + /* handle timing */ + bb->elapsedlvl += (HZ*3)/(MAX_FPS*4); + bb->elapsedshot += (HZ*3)/(MAX_FPS*4); + + if(bb->elapsedshot > MAX_SHOTTIME) { + bb->elapsedshot = 0; + buttonres = bubbles_fire(bb); + if(buttonres != BB_NONE) return buttonres; + buttonres = bubbles_checklevel(bb); + 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)); + } + lasttick = currenttick; + } +} + +/***************************************************************************** +* plugin entry point. +******************************************************************************/ +enum plugin_status plugin_start(struct plugin_api* api, void* parameter) { + struct game_context bb; + bool exit = false; + int position; + char str[19]; + + /* 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)){ + 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 -- cgit v1.2.3