summaryrefslogtreecommitdiff
path: root/apps/plugins/bubbles.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/bubbles.c')
-rwxr-xr-xapps/plugins/bubbles.c2537
1 files changed, 2537 insertions, 0 deletions
diff --git a/apps/plugins/bubbles.c b/apps/plugins/bubbles.c
new file mode 100755
index 0000000..9e523fa
--- /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; 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_SZ, 0,
+ LCD_WIDTH-(XOFS-1+BB_WIDTH*BUBBLE_SZ), 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_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; 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 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; 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 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; 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;
+ }
+ }
+ }
+
+ /* 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_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; 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 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; 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;
+
+ 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