dd61702fb0
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@28712 a1c6a512-1295-4272-9138-f99709370657
1618 lines
54 KiB
C
1618 lines
54 KiB
C
/***************************************************************************
|
|
* __________ __ ___.
|
|
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
|
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
|
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
|
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
|
* \/ \/ \/ \/ \/
|
|
* $Id$
|
|
*
|
|
* Copyright (C) 2005 Adam Boot
|
|
*
|
|
* Color graphics from Gweled (http://sebdelestaing.free.fr/gweled/)
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
|
* KIND, either express or implied.
|
|
*
|
|
****************************************************************************/
|
|
|
|
#include "plugin.h"
|
|
#include "lib/display_text.h"
|
|
#include "lib/highscore.h"
|
|
#include "lib/playback_control.h"
|
|
#include "pluginbitmaps/jewels.h"
|
|
|
|
/* button definitions */
|
|
#if CONFIG_KEYPAD == RECORDER_PAD
|
|
#define JEWELS_UP BUTTON_UP
|
|
#define JEWELS_DOWN BUTTON_DOWN
|
|
#define JEWELS_LEFT BUTTON_LEFT
|
|
#define JEWELS_RIGHT BUTTON_RIGHT
|
|
#define JEWELS_SELECT BUTTON_PLAY
|
|
#define JEWELS_CANCEL BUTTON_OFF
|
|
#define HK_SELECT "PLAY"
|
|
#define HK_CANCEL "OFF"
|
|
|
|
#elif CONFIG_KEYPAD == ARCHOS_AV300_PAD
|
|
#define JEWELS_UP BUTTON_UP
|
|
#define JEWELS_DOWN BUTTON_DOWN
|
|
#define JEWELS_LEFT BUTTON_LEFT
|
|
#define JEWELS_RIGHT BUTTON_RIGHT
|
|
#define JEWELS_SELECT BUTTON_SELECT
|
|
#define JEWELS_CANCEL BUTTON_OFF
|
|
#define HK_SELECT "SELECT"
|
|
#define HK_CANCEL "OFF"
|
|
|
|
#elif CONFIG_KEYPAD == ONDIO_PAD
|
|
#define JEWELS_UP BUTTON_UP
|
|
#define JEWELS_DOWN BUTTON_DOWN
|
|
#define JEWELS_LEFT BUTTON_LEFT
|
|
#define JEWELS_RIGHT BUTTON_RIGHT
|
|
#define JEWELS_SELECT BUTTON_MENU
|
|
#define JEWELS_CANCEL BUTTON_OFF
|
|
#define HK_SELECT "MENU"
|
|
#define HK_CANCEL "OFF"
|
|
|
|
#elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || (CONFIG_KEYPAD == IRIVER_H300_PAD)
|
|
#define JEWELS_UP BUTTON_UP
|
|
#define JEWELS_DOWN BUTTON_DOWN
|
|
#define JEWELS_LEFT BUTTON_LEFT
|
|
#define JEWELS_RIGHT BUTTON_RIGHT
|
|
#define JEWELS_SELECT BUTTON_SELECT
|
|
#define JEWELS_CANCEL BUTTON_OFF
|
|
#define JEWELS_RC_CANCEL BUTTON_RC_STOP
|
|
#define HK_SELECT "SELECT"
|
|
#define HK_CANCEL "OFF"
|
|
|
|
#elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
|
|
(CONFIG_KEYPAD == IPOD_1G2G_PAD)
|
|
#define JEWELS_SCROLLWHEEL
|
|
#define JEWELS_UP BUTTON_MENU
|
|
#define JEWELS_DOWN BUTTON_PLAY
|
|
#define JEWELS_LEFT BUTTON_LEFT
|
|
#define JEWELS_RIGHT BUTTON_RIGHT
|
|
#define JEWELS_PREV BUTTON_SCROLL_BACK
|
|
#define JEWELS_NEXT BUTTON_SCROLL_FWD
|
|
#define JEWELS_SELECT BUTTON_SELECT
|
|
#define JEWELS_CANCEL (BUTTON_SELECT | BUTTON_MENU)
|
|
#define HK_SELECT "SELECT"
|
|
#define HK_CANCEL "SEL + MENU"
|
|
|
|
#elif (CONFIG_KEYPAD == IPOD_3G_PAD)
|
|
#define JEWELS_LEFT BUTTON_LEFT
|
|
#define JEWELS_RIGHT BUTTON_RIGHT
|
|
#define JEWELS_UP BUTTON_SCROLL_BACK
|
|
#define JEWELS_DOWN BUTTON_SCROLL_FWD
|
|
#define JEWELS_SELECT BUTTON_SELECT
|
|
#define JEWELS_CANCEL BUTTON_MENU
|
|
#define HK_SELECT "SELECT"
|
|
#define HK_CANCEL "MENU"
|
|
|
|
#elif CONFIG_KEYPAD == IRIVER_IFP7XX_PAD
|
|
#define JEWELS_UP BUTTON_UP
|
|
#define JEWELS_DOWN BUTTON_DOWN
|
|
#define JEWELS_LEFT BUTTON_LEFT
|
|
#define JEWELS_RIGHT BUTTON_RIGHT
|
|
#define JEWELS_SELECT BUTTON_SELECT
|
|
#define JEWELS_CANCEL BUTTON_PLAY
|
|
#define HK_SELECT "SELECT"
|
|
#define HK_CANCEL "PLAY"
|
|
|
|
#elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
|
|
#define JEWELS_UP BUTTON_UP
|
|
#define JEWELS_DOWN BUTTON_DOWN
|
|
#define JEWELS_LEFT BUTTON_LEFT
|
|
#define JEWELS_RIGHT BUTTON_RIGHT
|
|
#define JEWELS_SELECT BUTTON_SELECT
|
|
#define JEWELS_CANCEL BUTTON_POWER
|
|
#define HK_SELECT "SELECT"
|
|
#define HK_CANCEL "POWER"
|
|
|
|
#elif CONFIG_KEYPAD == GIGABEAT_PAD
|
|
#define JEWELS_UP BUTTON_UP
|
|
#define JEWELS_DOWN BUTTON_DOWN
|
|
#define JEWELS_LEFT BUTTON_LEFT
|
|
#define JEWELS_RIGHT BUTTON_RIGHT
|
|
#define JEWELS_SELECT BUTTON_SELECT
|
|
#define JEWELS_CANCEL BUTTON_POWER
|
|
#define HK_SELECT "SELECT"
|
|
#define HK_CANCEL "POWER"
|
|
|
|
#elif CONFIG_KEYPAD == SANSA_E200_PAD
|
|
#define JEWELS_SCROLLWHEEL
|
|
#define JEWELS_UP BUTTON_UP
|
|
#define JEWELS_DOWN BUTTON_DOWN
|
|
#define JEWELS_LEFT BUTTON_LEFT
|
|
#define JEWELS_RIGHT BUTTON_RIGHT
|
|
#define JEWELS_PREV BUTTON_SCROLL_BACK
|
|
#define JEWELS_NEXT BUTTON_SCROLL_FWD
|
|
#define JEWELS_SELECT BUTTON_SELECT
|
|
#define JEWELS_CANCEL BUTTON_POWER
|
|
#define HK_SELECT "SELECT"
|
|
#define HK_CANCEL "POWER"
|
|
|
|
#elif (CONFIG_KEYPAD == SANSA_FUZE_PAD)
|
|
#define JEWELS_SCROLLWHEEL
|
|
#define JEWELS_UP BUTTON_UP
|
|
#define JEWELS_DOWN BUTTON_DOWN
|
|
#define JEWELS_LEFT BUTTON_LEFT
|
|
#define JEWELS_RIGHT BUTTON_RIGHT
|
|
#define JEWELS_PREV BUTTON_SCROLL_BACK
|
|
#define JEWELS_NEXT BUTTON_SCROLL_FWD
|
|
#define JEWELS_SELECT BUTTON_SELECT
|
|
#define JEWELS_CANCEL (BUTTON_HOME|BUTTON_REPEAT)
|
|
#define HK_SELECT "SELECT"
|
|
#define HK_CANCEL "HOME"
|
|
|
|
#elif CONFIG_KEYPAD == SANSA_C200_PAD || \
|
|
CONFIG_KEYPAD == SANSA_CLIP_PAD || \
|
|
CONFIG_KEYPAD == SANSA_M200_PAD
|
|
#define JEWELS_UP BUTTON_UP
|
|
#define JEWELS_DOWN BUTTON_DOWN
|
|
#define JEWELS_LEFT BUTTON_LEFT
|
|
#define JEWELS_RIGHT BUTTON_RIGHT
|
|
#define JEWELS_SELECT BUTTON_SELECT
|
|
#define JEWELS_CANCEL BUTTON_POWER
|
|
#define HK_SELECT "SELECT"
|
|
#define HK_CANCEL "POWER"
|
|
|
|
#elif CONFIG_KEYPAD == IRIVER_H10_PAD
|
|
#define JEWELS_UP BUTTON_SCROLL_UP
|
|
#define JEWELS_DOWN BUTTON_SCROLL_DOWN
|
|
#define JEWELS_LEFT BUTTON_LEFT
|
|
#define JEWELS_RIGHT BUTTON_RIGHT
|
|
#define JEWELS_SELECT BUTTON_PLAY
|
|
#define JEWELS_CANCEL BUTTON_POWER
|
|
#define HK_SELECT "PLAY"
|
|
#define HK_CANCEL "POWER"
|
|
|
|
#elif CONFIG_KEYPAD == GIGABEAT_S_PAD
|
|
#define JEWELS_UP BUTTON_UP
|
|
#define JEWELS_DOWN BUTTON_DOWN
|
|
#define JEWELS_LEFT BUTTON_LEFT
|
|
#define JEWELS_RIGHT BUTTON_RIGHT
|
|
#define JEWELS_SELECT BUTTON_SELECT
|
|
#define JEWELS_CANCEL BUTTON_BACK
|
|
#define HK_SELECT "SELECT"
|
|
#define HK_CANCEL "BACK"
|
|
|
|
#elif CONFIG_KEYPAD == MROBE100_PAD
|
|
#define JEWELS_UP BUTTON_UP
|
|
#define JEWELS_DOWN BUTTON_DOWN
|
|
#define JEWELS_LEFT BUTTON_LEFT
|
|
#define JEWELS_RIGHT BUTTON_RIGHT
|
|
#define JEWELS_SELECT BUTTON_SELECT
|
|
#define JEWELS_CANCEL BUTTON_POWER
|
|
#define HK_SELECT "SELECT"
|
|
#define HK_CANCEL "POWER"
|
|
|
|
#elif CONFIG_KEYPAD == IAUDIO_M3_PAD
|
|
#define JEWELS_UP BUTTON_RC_VOL_UP
|
|
#define JEWELS_DOWN BUTTON_RC_VOL_DOWN
|
|
#define JEWELS_LEFT BUTTON_RC_REW
|
|
#define JEWELS_RIGHT BUTTON_RC_FF
|
|
#define JEWELS_SELECT BUTTON_RC_PLAY
|
|
#define JEWELS_CANCEL BUTTON_RC_REC
|
|
#define HK_SELECT "PLAY"
|
|
#define HK_CANCEL "REC"
|
|
|
|
#define JEWELS_RC_CANCEL BUTTON_REC
|
|
|
|
#elif CONFIG_KEYPAD == COWON_D2_PAD
|
|
#define JEWELS_CANCEL BUTTON_POWER
|
|
#define HK_CANCEL "POWER"
|
|
|
|
#elif CONFIG_KEYPAD == IAUDIO67_PAD
|
|
#define JEWELS_UP BUTTON_STOP
|
|
#define JEWELS_DOWN BUTTON_PLAY
|
|
#define JEWELS_LEFT BUTTON_LEFT
|
|
#define JEWELS_RIGHT BUTTON_RIGHT
|
|
#define JEWELS_SELECT BUTTON_MENU
|
|
#define JEWELS_CANCEL BUTTON_POWER
|
|
#define HK_SELECT "MENU"
|
|
#define HK_CANCEL "POWER"
|
|
|
|
#elif CONFIG_KEYPAD == CREATIVEZVM_PAD
|
|
#define JEWELS_UP BUTTON_UP
|
|
#define JEWELS_DOWN BUTTON_DOWN
|
|
#define JEWELS_LEFT BUTTON_LEFT
|
|
#define JEWELS_RIGHT BUTTON_RIGHT
|
|
#define JEWELS_SELECT BUTTON_SELECT
|
|
#define JEWELS_CANCEL BUTTON_BACK
|
|
#define HK_SELECT "MIDDLE"
|
|
#define HK_CANCEL "BACK"
|
|
|
|
#elif CONFIG_KEYPAD == PHILIPS_HDD1630_PAD
|
|
#define JEWELS_UP BUTTON_UP
|
|
#define JEWELS_DOWN BUTTON_DOWN
|
|
#define JEWELS_LEFT BUTTON_LEFT
|
|
#define JEWELS_RIGHT BUTTON_RIGHT
|
|
#define JEWELS_SELECT BUTTON_SELECT
|
|
#define JEWELS_CANCEL BUTTON_POWER
|
|
#define HK_SELECT "SELECT"
|
|
#define HK_CANCEL "POWER"
|
|
|
|
#elif CONFIG_KEYPAD == PHILIPS_HDD6330_PAD
|
|
#define JEWELS_UP BUTTON_UP
|
|
#define JEWELS_DOWN BUTTON_DOWN
|
|
#define JEWELS_LEFT BUTTON_LEFT
|
|
#define JEWELS_RIGHT BUTTON_RIGHT
|
|
#define JEWELS_SELECT BUTTON_PLAY
|
|
#define JEWELS_CANCEL BUTTON_POWER
|
|
#define HK_SELECT "PLAY"
|
|
#define HK_CANCEL "POWER"
|
|
|
|
#elif CONFIG_KEYPAD == PHILIPS_SA9200_PAD
|
|
#define JEWELS_UP BUTTON_UP
|
|
#define JEWELS_DOWN BUTTON_DOWN
|
|
#define JEWELS_LEFT BUTTON_PREV
|
|
#define JEWELS_RIGHT BUTTON_NEXT
|
|
#define JEWELS_SELECT BUTTON_PLAY
|
|
#define JEWELS_CANCEL BUTTON_POWER
|
|
#define HK_SELECT "PLAY"
|
|
#define HK_CANCEL "POWER"
|
|
|
|
#elif CONFIG_KEYPAD == ONDAVX747_PAD || \
|
|
CONFIG_KEYPAD == ONDAVX777_PAD || \
|
|
CONFIG_KEYPAD == MROBE500_PAD
|
|
#define JEWELS_CANCEL BUTTON_POWER
|
|
#define HK_CANCEL "POWER"
|
|
|
|
#elif CONFIG_KEYPAD == SAMSUNG_YH_PAD
|
|
#define JEWELS_UP BUTTON_UP
|
|
#define JEWELS_DOWN BUTTON_DOWN
|
|
#define JEWELS_LEFT BUTTON_LEFT
|
|
#define JEWELS_RIGHT BUTTON_RIGHT
|
|
#define JEWELS_SELECT BUTTON_PLAY
|
|
#define JEWELS_CANCEL BUTTON_REW
|
|
#define HK_SELECT "PLAY"
|
|
#define HK_CANCEL "REWIND"
|
|
|
|
#elif CONFIG_KEYPAD == PBELL_VIBE500_PAD
|
|
#define JEWELS_UP BUTTON_UP
|
|
#define JEWELS_DOWN BUTTON_DOWN
|
|
#define JEWELS_LEFT BUTTON_PREV
|
|
#define JEWELS_RIGHT BUTTON_NEXT
|
|
#define JEWELS_SELECT BUTTON_OK
|
|
#define JEWELS_CANCEL BUTTON_REC
|
|
#define HK_SELECT "OK"
|
|
#define HK_CANCEL "REC"
|
|
|
|
#elif CONFIG_KEYPAD == MPIO_HD200_PAD
|
|
#define JEWELS_LEFT BUTTON_VOL_DOWN
|
|
#define JEWELS_RIGHT BUTTON_VOL_UP
|
|
#define JEWELS_UP BUTTON_REW
|
|
#define JEWELS_DOWN BUTTON_FF
|
|
#define JEWELS_SELECT BUTTON_FUNC
|
|
#define JEWELS_CANCEL BUTTON_REC
|
|
#define HK_SELECT "FUNC"
|
|
#define HK_CANCEL "REC"
|
|
|
|
#elif CONFIG_KEYPAD == MPIO_HD300_PAD
|
|
#define JEWELS_LEFT BUTTON_REW
|
|
#define JEWELS_RIGHT BUTTON_FF
|
|
#define JEWELS_UP BUTTON_UP
|
|
#define JEWELS_DOWN BUTTON_DOWN
|
|
#define JEWELS_SELECT BUTTON_ENTER
|
|
#define JEWELS_CANCEL BUTTON_MENU
|
|
#define HK_SELECT "ENTER"
|
|
#define HK_CANCEL "MENU"
|
|
|
|
#else
|
|
#error No keymap defined!
|
|
#endif
|
|
|
|
#ifdef HAVE_TOUCHSCREEN
|
|
#ifndef JEWELS_UP
|
|
#define JEWELS_UP BUTTON_TOPMIDDLE
|
|
#endif
|
|
#ifndef JEWELS_DOWN
|
|
#define JEWELS_DOWN BUTTON_BOTTOMMIDDLE
|
|
#endif
|
|
#ifndef JEWELS_LEFT
|
|
#define JEWELS_LEFT BUTTON_MIDLEFT
|
|
#endif
|
|
#ifndef JEWELS_RIGHT
|
|
#define JEWELS_RIGHT BUTTON_MIDRIGHT
|
|
#endif
|
|
#ifndef JEWELS_SELECT
|
|
#define JEWELS_SELECT BUTTON_CENTER
|
|
#define HK_SELECT "CENTER"
|
|
#endif
|
|
#ifndef JEWELS_CANCEL
|
|
#define JEWELS_CANCEL BUTTON_TOPLEFT
|
|
#define HK_CANCEL "TOPLEFT"
|
|
#endif
|
|
#endif
|
|
|
|
#define TILE_WIDTH BMPWIDTH_jewels
|
|
#define TILE_HEIGHT (BMPHEIGHT_jewels/23)
|
|
|
|
#if LCD_HEIGHT < LCD_WIDTH
|
|
/* This calculation assumes integer division w/ LCD_HEIGHT/TILE_HEIGHT */
|
|
#define YOFS LCD_HEIGHT-((LCD_HEIGHT/TILE_HEIGHT)*TILE_HEIGHT)
|
|
#else
|
|
#define YOFS 0
|
|
#endif
|
|
|
|
#define NUM_SCORES 5
|
|
|
|
/* swap directions */
|
|
#define SWAP_UP 0
|
|
#define SWAP_RIGHT 1
|
|
#define SWAP_DOWN 2
|
|
#define SWAP_LEFT 3
|
|
|
|
/* play board dimension */
|
|
#define BJ_HEIGHT 9
|
|
#define BJ_WIDTH 8
|
|
|
|
/* next level threshold */
|
|
#define LEVEL_PTS 100
|
|
|
|
/* animation frame rate */
|
|
#define MAX_FPS 20
|
|
|
|
/* text margin */
|
|
#define MARGIN 5
|
|
|
|
/* Game types */
|
|
enum game_type {
|
|
GAME_TYPE_NORMAL,
|
|
GAME_TYPE_PUZZLE
|
|
};
|
|
|
|
/* external bitmaps */
|
|
extern const fb_data jewels[];
|
|
|
|
/* tile background colors */
|
|
#ifdef HAVE_LCD_COLOR
|
|
static const unsigned jewels_bkgd[2] = {
|
|
LCD_RGBPACK(104, 63, 63),
|
|
LCD_RGBPACK(83, 44, 44)
|
|
};
|
|
#endif
|
|
|
|
/* the tile struct
|
|
* type is the jewel number 0-7
|
|
* falling if the jewel is falling
|
|
* delete marks the jewel for deletion
|
|
*/
|
|
struct tile {
|
|
int type;
|
|
bool falling;
|
|
bool delete;
|
|
};
|
|
|
|
/* the game context struct
|
|
* score is the current level score
|
|
* segments is the number of cleared segments in the current run
|
|
* level is the current level
|
|
* tmp_type is the select type in the menu
|
|
* type is the game type (normal or puzzle)
|
|
* playboard is the game playing board (first row is hidden)
|
|
* num_jewels is the number of different jewels to use
|
|
*/
|
|
struct game_context {
|
|
unsigned int score;
|
|
unsigned int segments;
|
|
unsigned int level;
|
|
unsigned int type;
|
|
unsigned int tmp_type;
|
|
struct tile playboard[BJ_HEIGHT][BJ_WIDTH];
|
|
unsigned int num_jewels;
|
|
};
|
|
|
|
#define MAX_NUM_JEWELS 7
|
|
|
|
#define MAX_PUZZLE_TILES 4
|
|
#define NUM_PUZZLE_LEVELS 10
|
|
|
|
struct puzzle_tile {
|
|
int x;
|
|
int y;
|
|
int tile_type;
|
|
};
|
|
|
|
struct puzzle_level {
|
|
unsigned int num_jewels;
|
|
unsigned int num_tiles;
|
|
struct puzzle_tile tiles[MAX_PUZZLE_TILES];
|
|
};
|
|
|
|
#define PUZZLE_TILE_UP 1
|
|
#define PUZZLE_TILE_DOWN 2
|
|
#define PUZZLE_TILE_LEFT 4
|
|
#define PUZZLE_TILE_RIGHT 8
|
|
|
|
struct puzzle_level puzzle_levels[NUM_PUZZLE_LEVELS] = {
|
|
{ 5, 2, { {3, 3, PUZZLE_TILE_RIGHT},
|
|
{4, 2, PUZZLE_TILE_LEFT} } },
|
|
{ 5, 2, { {3, 2, PUZZLE_TILE_DOWN},
|
|
{3, 4, PUZZLE_TILE_UP} } },
|
|
{ 6, 3, { {3, 2, PUZZLE_TILE_DOWN},
|
|
{3, 4, PUZZLE_TILE_UP|PUZZLE_TILE_DOWN},
|
|
{3, 6, PUZZLE_TILE_UP} } },
|
|
{ 6, 3, { {3, 2, PUZZLE_TILE_RIGHT},
|
|
{4, 3, PUZZLE_TILE_LEFT|PUZZLE_TILE_RIGHT},
|
|
{5, 4, PUZZLE_TILE_LEFT} } },
|
|
{ 6, 2, { {3, 4, PUZZLE_TILE_RIGHT},
|
|
{4, 2, PUZZLE_TILE_LEFT} } },
|
|
{ 6, 2, { {3, 2, PUZZLE_TILE_DOWN},
|
|
{4, 4, PUZZLE_TILE_UP} } },
|
|
{ 7, 4, { {3, 2, PUZZLE_TILE_RIGHT|PUZZLE_TILE_DOWN},
|
|
{4, 3, PUZZLE_TILE_LEFT|PUZZLE_TILE_DOWN},
|
|
{3, 4, PUZZLE_TILE_RIGHT|PUZZLE_TILE_UP},
|
|
{4, 4, PUZZLE_TILE_LEFT|PUZZLE_TILE_UP} } },
|
|
{ 6, 3, { {3, 2, PUZZLE_TILE_DOWN},
|
|
{4, 4, PUZZLE_TILE_UP|PUZZLE_TILE_DOWN},
|
|
{3, 6, PUZZLE_TILE_UP} } },
|
|
{ 7, 3, { {2, 2, PUZZLE_TILE_RIGHT},
|
|
{4, 1, PUZZLE_TILE_LEFT|PUZZLE_TILE_RIGHT},
|
|
{5, 4, PUZZLE_TILE_LEFT} } },
|
|
{ 7, 4, { {3, 0, PUZZLE_TILE_RIGHT|PUZZLE_TILE_DOWN},
|
|
{5, 0, PUZZLE_TILE_LEFT|PUZZLE_TILE_DOWN},
|
|
{2, 7, PUZZLE_TILE_RIGHT|PUZZLE_TILE_UP},
|
|
{4, 7, PUZZLE_TILE_LEFT|PUZZLE_TILE_UP} } },
|
|
};
|
|
|
|
#define SAVE_FILE PLUGIN_GAMES_DIR "/jewels.save"
|
|
#define SCORE_FILE PLUGIN_GAMES_DIR "/jewels.score"
|
|
struct highscore highscores[NUM_SCORES];
|
|
|
|
static bool resume_file = false;
|
|
|
|
/*****************************************************************************
|
|
* jewels_setcolors() set the foreground and background colors.
|
|
******************************************************************************/
|
|
static inline void jewels_setcolors(void) {
|
|
#ifdef HAVE_LCD_COLOR
|
|
rb->lcd_set_background(LCD_RGBPACK(49, 26, 26));
|
|
rb->lcd_set_foreground(LCD_RGBPACK(210, 181, 181));
|
|
#endif
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* jewels_loadgame() loads the saved game and returns load success.
|
|
******************************************************************************/
|
|
static bool jewels_loadgame(struct game_context* bj)
|
|
{
|
|
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, &bj->tmp_type, sizeof(bj->tmp_type)) <= 0) break;
|
|
if(rb->read(fd, &bj->type, sizeof(bj->type)) <= 0) break;
|
|
if(rb->read(fd, &bj->score, sizeof(bj->score)) <= 0) break;
|
|
if(rb->read(fd, &bj->level, sizeof(bj->level)) <= 0) break;
|
|
if(rb->read(fd, &bj->segments, sizeof(bj->segments)) <= 0) break;
|
|
if(rb->read(fd, &bj->num_jewels, sizeof(bj->num_jewels)) <= 0) break;
|
|
if(rb->read(fd, bj->playboard, sizeof(bj->playboard)) <= 0) break;
|
|
loaded = true;
|
|
break;
|
|
}
|
|
|
|
rb->close(fd);
|
|
|
|
return loaded;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* jewels_savegame() saves the current game state.
|
|
******************************************************************************/
|
|
static void jewels_savegame(struct game_context* bj)
|
|
{
|
|
int fd;
|
|
/* write out the game state to the save file */
|
|
fd = rb->open(SAVE_FILE, O_WRONLY|O_CREAT, 0666);
|
|
if(fd < 0) return;
|
|
|
|
rb->write(fd, &bj->tmp_type, sizeof(bj->tmp_type));
|
|
rb->write(fd, &bj->type, sizeof(bj->type));
|
|
rb->write(fd, &bj->score, sizeof(bj->score));
|
|
rb->write(fd, &bj->level, sizeof(bj->level));
|
|
rb->write(fd, &bj->segments, sizeof(bj->segments));
|
|
rb->write(fd, &bj->num_jewels, sizeof(bj->num_jewels));
|
|
rb->write(fd, bj->playboard, sizeof(bj->playboard));
|
|
rb->close(fd);
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* jewels_drawboard() redraws the entire game board.
|
|
******************************************************************************/
|
|
static void jewels_drawboard(struct game_context* bj) {
|
|
int i, j;
|
|
int w, h;
|
|
unsigned int tempscore;
|
|
unsigned int size;
|
|
char *title = "Level";
|
|
char str[10];
|
|
|
|
if (bj->type == GAME_TYPE_NORMAL) {
|
|
tempscore = (bj->score>LEVEL_PTS ? LEVEL_PTS : bj->score);
|
|
size = LEVEL_PTS;
|
|
} else {
|
|
tempscore = (bj->level>NUM_PUZZLE_LEVELS ? NUM_PUZZLE_LEVELS : bj->level);
|
|
size = NUM_PUZZLE_LEVELS;
|
|
}
|
|
|
|
/* clear screen */
|
|
rb->lcd_clear_display();
|
|
|
|
/* dispay playing board */
|
|
for(i=0; i<BJ_HEIGHT-1; i++){
|
|
for(j=0; j<BJ_WIDTH; j++){
|
|
#ifdef HAVE_LCD_COLOR
|
|
rb->lcd_set_foreground(jewels_bkgd[(i+j)%2]);
|
|
rb->lcd_fillrect(j*TILE_WIDTH, i*TILE_HEIGHT+YOFS,
|
|
TILE_WIDTH, TILE_HEIGHT);
|
|
rb->lcd_bitmap_transparent_part(jewels,
|
|
0, TILE_HEIGHT*(bj->playboard[i+1][j].type),
|
|
STRIDE( SCREEN_MAIN,
|
|
BMPWIDTH_jewels, BMPHEIGHT_jewels),
|
|
j*TILE_WIDTH, i*TILE_HEIGHT+YOFS,
|
|
TILE_WIDTH, TILE_HEIGHT);
|
|
#else
|
|
rb->lcd_bitmap_part(jewels,
|
|
0, TILE_HEIGHT*(bj->playboard[i+1][j].type),
|
|
STRIDE( SCREEN_MAIN,
|
|
BMPWIDTH_jewels, BMPHEIGHT_jewels),
|
|
j*TILE_WIDTH, i*TILE_HEIGHT+YOFS,
|
|
TILE_WIDTH, TILE_HEIGHT);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
#if LCD_WIDTH > LCD_HEIGHT /* horizontal layout */
|
|
|
|
/* draw separator lines */
|
|
jewels_setcolors();
|
|
rb->lcd_vline(BJ_WIDTH*TILE_WIDTH, 0, LCD_HEIGHT-1);
|
|
|
|
rb->lcd_hline(BJ_WIDTH*TILE_WIDTH, LCD_WIDTH-1, 18);
|
|
rb->lcd_hline(BJ_WIDTH*TILE_WIDTH, LCD_WIDTH-1, LCD_HEIGHT-10);
|
|
|
|
/* draw progress bar */
|
|
#ifdef HAVE_LCD_COLOR
|
|
rb->lcd_set_foreground(LCD_RGBPACK(104, 63, 63));
|
|
#endif
|
|
rb->lcd_fillrect(BJ_WIDTH*TILE_WIDTH+(LCD_WIDTH-BJ_WIDTH*TILE_WIDTH)/4,
|
|
(LCD_HEIGHT-10)-(((LCD_HEIGHT-10)-18)*
|
|
tempscore/size),
|
|
(LCD_WIDTH-BJ_WIDTH*TILE_WIDTH)/2,
|
|
((LCD_HEIGHT-10)-18)*tempscore/size);
|
|
#ifdef HAVE_LCD_COLOR
|
|
rb->lcd_set_foreground(LCD_RGBPACK(83, 44, 44));
|
|
rb->lcd_drawrect(BJ_WIDTH*TILE_WIDTH+(LCD_WIDTH-BJ_WIDTH*TILE_WIDTH)/4+1,
|
|
(LCD_HEIGHT-10)-(((LCD_HEIGHT-10)-18)*
|
|
tempscore/size)+1,
|
|
(LCD_WIDTH-BJ_WIDTH*TILE_WIDTH)/2-2,
|
|
((LCD_HEIGHT-10)-18)*tempscore/size-1);
|
|
jewels_setcolors();
|
|
rb->lcd_drawrect(BJ_WIDTH*TILE_WIDTH+(LCD_WIDTH-BJ_WIDTH*TILE_WIDTH)/4,
|
|
(LCD_HEIGHT-10)-(((LCD_HEIGHT-10)-18)*tempscore/size),
|
|
(LCD_WIDTH-BJ_WIDTH*TILE_WIDTH)/2,
|
|
((LCD_HEIGHT-10)-18)*tempscore/size+1);
|
|
#endif
|
|
|
|
/* print text */
|
|
rb->lcd_getstringsize(title, &w, &h);
|
|
rb->lcd_putsxy(LCD_WIDTH-(LCD_WIDTH-BJ_WIDTH*TILE_WIDTH)/2-w/2, 1, title);
|
|
rb->snprintf(str, 4, "%d", bj->level);
|
|
rb->lcd_getstringsize(str, &w, &h);
|
|
rb->lcd_putsxy(LCD_WIDTH-(LCD_WIDTH-BJ_WIDTH*TILE_WIDTH)/2-w/2, 10, str);
|
|
|
|
if (bj->type == GAME_TYPE_NORMAL) {
|
|
rb->snprintf(str, 6, "%d", (bj->level-1)*LEVEL_PTS+bj->score);
|
|
rb->lcd_getstringsize(str, &w, &h);
|
|
rb->lcd_putsxy(LCD_WIDTH-(LCD_WIDTH-BJ_WIDTH*TILE_WIDTH)/2-w/2,
|
|
LCD_HEIGHT-8, str);
|
|
}
|
|
|
|
#elif LCD_WIDTH < LCD_HEIGHT /* vertical layout */
|
|
|
|
/* draw separator lines */
|
|
jewels_setcolors();
|
|
rb->lcd_hline(0, LCD_WIDTH-1, 8*TILE_HEIGHT+YOFS);
|
|
rb->lcd_hline(0, LCD_WIDTH-1, LCD_HEIGHT-14);
|
|
rb->lcd_vline(LCD_WIDTH/2, LCD_HEIGHT-14, LCD_HEIGHT-1);
|
|
|
|
/* draw progress bar */
|
|
#ifdef HAVE_LCD_COLOR
|
|
rb->lcd_set_foreground(LCD_RGBPACK(104, 63, 63));
|
|
#endif
|
|
rb->lcd_fillrect(0, (8*TILE_HEIGHT+YOFS)
|
|
+(LCD_HEIGHT-14-(8*TILE_HEIGHT+YOFS))/4,
|
|
LCD_WIDTH*tempscore/size,
|
|
(LCD_HEIGHT-14-(8*TILE_HEIGHT+YOFS))/2);
|
|
#ifdef HAVE_LCD_COLOR
|
|
rb->lcd_set_foreground(LCD_RGBPACK(83, 44, 44));
|
|
rb->lcd_drawrect(1, (8*TILE_HEIGHT+YOFS)
|
|
+(LCD_HEIGHT-14-(8*TILE_HEIGHT+YOFS))/4+1,
|
|
LCD_WIDTH*tempscore/size-1,
|
|
(LCD_HEIGHT-14-(8*TILE_HEIGHT+YOFS))/2-2);
|
|
jewels_setcolors();
|
|
rb->lcd_drawrect(0, (8*TILE_HEIGHT+YOFS)
|
|
+(LCD_HEIGHT-14-(8*TILE_HEIGHT+YOFS))/4,
|
|
LCD_WIDTH*tempscore/size+1,
|
|
(LCD_HEIGHT-14-(8*TILE_HEIGHT+YOFS))/2);
|
|
#endif
|
|
|
|
/* print text */
|
|
rb->lcd_putsxyf(1, LCD_HEIGHT-10, "%s %d", title, bj->level);
|
|
|
|
if (bj->type == GAME_TYPE_NORMAL) {
|
|
rb->snprintf(str, 6, "%d", (bj->level-1)*LEVEL_PTS+bj->score);
|
|
rb->lcd_getstringsize(str, &w, &h);
|
|
rb->lcd_putsxy((LCD_WIDTH-2)-w, LCD_HEIGHT-10, str);
|
|
}
|
|
|
|
|
|
#else /* square layout */
|
|
|
|
/* draw separator lines */
|
|
jewels_setcolors();
|
|
rb->lcd_hline(0, LCD_WIDTH-1, 8*TILE_HEIGHT+YOFS);
|
|
rb->lcd_vline(BJ_WIDTH*TILE_WIDTH, 0, 8*TILE_HEIGHT+YOFS);
|
|
rb->lcd_vline(LCD_WIDTH/2, 8*TILE_HEIGHT+YOFS, LCD_HEIGHT-1);
|
|
|
|
/* draw progress bar */
|
|
#ifdef HAVE_LCD_COLOR
|
|
rb->lcd_set_foreground(LCD_RGBPACK(104, 63, 63));
|
|
#endif
|
|
rb->lcd_fillrect(BJ_WIDTH*TILE_WIDTH+(LCD_WIDTH-BJ_WIDTH*TILE_WIDTH)/4,
|
|
(8*TILE_HEIGHT+YOFS)-(8*TILE_HEIGHT+YOFS)*tempscore/size,
|
|
(LCD_WIDTH-BJ_WIDTH*TILE_WIDTH)/2,
|
|
(8*TILE_HEIGHT+YOFS)*tempscore/size);
|
|
#ifdef HAVE_LCD_COLOR
|
|
rb->lcd_set_foreground(LCD_RGBPACK(83, 44, 44));
|
|
rb->lcd_drawrect(BJ_WIDTH*TILE_WIDTH+(LCD_WIDTH-BJ_WIDTH*TILE_WIDTH)/4+1,
|
|
(8*TILE_HEIGHT+YOFS)-(8*TILE_HEIGHT+YOFS)
|
|
*tempscore/size+1,
|
|
(LCD_WIDTH-BJ_WIDTH*TILE_WIDTH)/2-2,
|
|
(8*TILE_HEIGHT+YOFS)*tempscore/size-1);
|
|
jewels_setcolors();
|
|
rb->lcd_drawrect(BJ_WIDTH*TILE_WIDTH+(LCD_WIDTH-BJ_WIDTH*TILE_WIDTH)/4,
|
|
(8*TILE_HEIGHT+YOFS)-(8*TILE_HEIGHT+YOFS)
|
|
*tempscore/size,
|
|
(LCD_WIDTH-BJ_WIDTH*TILE_WIDTH)/2,
|
|
(8*TILE_HEIGHT+YOFS)*tempscore/size+1);
|
|
#endif
|
|
|
|
/* print text */
|
|
rb->lcd_putsxyf(1, LCD_HEIGHT-(LCD_HEIGHT-(8*TILE_HEIGHT+YOFS))/2-3,"%s %d",
|
|
title, bj->level);
|
|
|
|
if (bj->type == GAME_TYPE_NORMAL) {
|
|
rb->snprintf(str, 6, "%d", (bj->level-1)*LEVEL_PTS+bj->score);
|
|
rb->lcd_getstringsize(str, &w, &h);
|
|
rb->lcd_putsxy((LCD_WIDTH-2)-w,
|
|
LCD_HEIGHT-(LCD_HEIGHT-(8*TILE_HEIGHT+YOFS))/2-3, str);
|
|
}
|
|
|
|
#endif /* layout */
|
|
|
|
rb->lcd_update();
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* jewels_putjewels() makes the jewels fall to fill empty spots and adds
|
|
* new random jewels at the empty spots at the top of each row.
|
|
******************************************************************************/
|
|
static void jewels_putjewels(struct game_context* bj){
|
|
int i, j, k;
|
|
bool mark, done;
|
|
long lasttick, currenttick;
|
|
|
|
/* loop to make all the jewels fall */
|
|
while(true) {
|
|
/* mark falling jewels and add new jewels to hidden top row*/
|
|
mark = false;
|
|
done = true;
|
|
for(j=0; j<BJ_WIDTH; j++) {
|
|
if(bj->playboard[1][j].type == 0) {
|
|
bj->playboard[0][j].type = rb->rand()%bj->num_jewels+1;
|
|
}
|
|
for(i=BJ_HEIGHT-2; i>=0; i--) {
|
|
if(!mark && bj->playboard[i+1][j].type == 0) {
|
|
mark = true;
|
|
done = false;
|
|
}
|
|
if(mark) bj->playboard[i][j].falling = true;
|
|
}
|
|
/*if(bj->playboard[1][j].falling) {
|
|
bj->playboard[0][j].type = rb->rand()%bj->num_jewels+1;
|
|
bj->playboard[0][j].falling = true;
|
|
}*/
|
|
mark = false;
|
|
}
|
|
|
|
/* break if there are no falling jewels */
|
|
if(done) break;
|
|
|
|
/* animate falling jewels */
|
|
lasttick = *rb->current_tick;
|
|
|
|
for(k=1; k<=8; k++) {
|
|
for(i=BJ_HEIGHT-2; i>=0; i--) {
|
|
for(j=0; j<BJ_WIDTH; j++) {
|
|
if(bj->playboard[i][j].falling &&
|
|
bj->playboard[i][j].type != 0) {
|
|
/* clear old position */
|
|
#ifdef HAVE_LCD_COLOR
|
|
if(i == 0 && YOFS) {
|
|
rb->lcd_set_foreground(rb->lcd_get_background());
|
|
} else {
|
|
rb->lcd_set_foreground(jewels_bkgd[(i-1+j)%2]);
|
|
}
|
|
rb->lcd_fillrect(j*TILE_WIDTH, (i-1)*TILE_HEIGHT+YOFS,
|
|
TILE_WIDTH, TILE_HEIGHT);
|
|
if(bj->playboard[i+1][j].type == 0) {
|
|
rb->lcd_set_foreground(jewels_bkgd[(i+j)%2]);
|
|
rb->lcd_fillrect(j*TILE_WIDTH, i*TILE_HEIGHT+YOFS,
|
|
TILE_WIDTH, TILE_HEIGHT);
|
|
}
|
|
#else
|
|
rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
|
|
rb->lcd_fillrect(j*TILE_WIDTH, (i-1)*TILE_HEIGHT+YOFS,
|
|
TILE_WIDTH, TILE_HEIGHT);
|
|
if(bj->playboard[i+1][j].type == 0) {
|
|
rb->lcd_fillrect(j*TILE_WIDTH, i*TILE_HEIGHT+YOFS,
|
|
TILE_WIDTH, TILE_HEIGHT);
|
|
}
|
|
rb->lcd_set_drawmode(DRMODE_SOLID);
|
|
#endif
|
|
|
|
/* draw new position */
|
|
#ifdef HAVE_LCD_COLOR
|
|
rb->lcd_bitmap_transparent_part(jewels, 0,
|
|
TILE_HEIGHT*(bj->playboard[i][j].type),
|
|
STRIDE( SCREEN_MAIN,
|
|
BMPWIDTH_jewels,
|
|
BMPHEIGHT_jewels),
|
|
j*TILE_WIDTH,
|
|
(i-1)*TILE_HEIGHT+YOFS+
|
|
((((TILE_HEIGHT<<10)*k)/8)>>10),
|
|
TILE_WIDTH, TILE_HEIGHT);
|
|
#else
|
|
rb->lcd_bitmap_part(jewels, 0,
|
|
TILE_HEIGHT*(bj->playboard[i][j].type),
|
|
STRIDE( SCREEN_MAIN,
|
|
BMPWIDTH_jewels,
|
|
BMPHEIGHT_jewels),
|
|
j*TILE_WIDTH,
|
|
(i-1)*TILE_HEIGHT+YOFS+
|
|
((((TILE_HEIGHT<<10)*k)/8)>>10),
|
|
TILE_WIDTH, TILE_HEIGHT);
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
|
|
rb->lcd_update_rect(0, 0, TILE_WIDTH*8, LCD_HEIGHT);
|
|
jewels_setcolors();
|
|
|
|
/* framerate limiting */
|
|
currenttick = *rb->current_tick;
|
|
if(currenttick-lasttick < HZ/MAX_FPS) {
|
|
rb->sleep((HZ/MAX_FPS)-(currenttick-lasttick));
|
|
} else {
|
|
rb->yield();
|
|
}
|
|
lasttick = currenttick;
|
|
}
|
|
|
|
/* shift jewels down */
|
|
for(j=0; j<BJ_WIDTH; j++) {
|
|
for(i=BJ_HEIGHT-1; i>=1; i--) {
|
|
if(bj->playboard[i-1][j].falling) {
|
|
bj->playboard[i][j].type = bj->playboard[i-1][j].type;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* clear out top row */
|
|
for(j=0; j<BJ_WIDTH; j++) {
|
|
bj->playboard[0][j].type = 0;
|
|
}
|
|
|
|
/* mark everything not falling */
|
|
for(i=0; i<BJ_HEIGHT; i++) {
|
|
for(j=0; j<BJ_WIDTH; j++) {
|
|
bj->playboard[i][j].falling = false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* jewels_clearjewels() finds all the connected rows and columns and
|
|
* calculates and returns the points earned.
|
|
******************************************************************************/
|
|
static unsigned int jewels_clearjewels(struct game_context* bj) {
|
|
int i, j;
|
|
int last, run;
|
|
unsigned int points = 0;
|
|
|
|
/* check for connected rows */
|
|
for(i=1; i<BJ_HEIGHT; i++) {
|
|
last = 0;
|
|
run = 1;
|
|
for(j=0; j<BJ_WIDTH; j++) {
|
|
if(bj->playboard[i][j].type == last &&
|
|
bj->playboard[i][j].type != 0 &&
|
|
bj->playboard[i][j].type <= MAX_NUM_JEWELS) {
|
|
run++;
|
|
|
|
if(run == 3) {
|
|
bj->segments++;
|
|
points += bj->segments;
|
|
bj->playboard[i][j].delete = true;
|
|
bj->playboard[i][j-1].delete = true;
|
|
bj->playboard[i][j-2].delete = true;
|
|
} else if(run > 3) {
|
|
points++;
|
|
bj->playboard[i][j].delete = true;
|
|
}
|
|
} else {
|
|
run = 1;
|
|
last = bj->playboard[i][j].type;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* check for connected columns */
|
|
for(j=0; j<BJ_WIDTH; j++) {
|
|
last = 0;
|
|
run = 1;
|
|
for(i=1; i<BJ_HEIGHT; i++) {
|
|
if(bj->playboard[i][j].type != 0 &&
|
|
bj->playboard[i][j].type == last &&
|
|
bj->playboard[i][j].type <= MAX_NUM_JEWELS) {
|
|
run++;
|
|
|
|
if(run == 3) {
|
|
bj->segments++;
|
|
points += bj->segments;
|
|
bj->playboard[i][j].delete = true;
|
|
bj->playboard[i-1][j].delete = true;
|
|
bj->playboard[i-2][j].delete = true;
|
|
} else if(run > 3) {
|
|
points++;
|
|
bj->playboard[i][j].delete = true;
|
|
}
|
|
} else {
|
|
run = 1;
|
|
last = bj->playboard[i][j].type;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* clear deleted jewels */
|
|
for(i=1; i<BJ_HEIGHT; i++) {
|
|
for(j=0; j<BJ_WIDTH; j++) {
|
|
if(bj->playboard[i][j].delete) {
|
|
bj->playboard[i][j].delete = false;
|
|
bj->playboard[i][j].type = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
return points;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* jewels_runboard() runs the board until it settles in a fixed state and
|
|
* returns points earned.
|
|
******************************************************************************/
|
|
static unsigned int jewels_runboard(struct game_context* bj) {
|
|
unsigned int points = 0;
|
|
unsigned int ret;
|
|
|
|
bj->segments = 0;
|
|
|
|
while((ret = jewels_clearjewels(bj)) > 0) {
|
|
points += ret;
|
|
jewels_drawboard(bj);
|
|
jewels_putjewels(bj);
|
|
}
|
|
|
|
return points;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* jewels_swapjewels() swaps two jewels as long as it results in points and
|
|
* returns points earned.
|
|
******************************************************************************/
|
|
static unsigned int jewels_swapjewels(struct game_context* bj,
|
|
int x, int y, int direc) {
|
|
int k;
|
|
int horzmod, vertmod;
|
|
int movelen = 0;
|
|
bool undo = false;
|
|
unsigned int points = 0;
|
|
long lasttick, currenttick;
|
|
|
|
/* check for invalid parameters */
|
|
if(x < 0 || x >= BJ_WIDTH || y < 0 || y >= BJ_HEIGHT-1 ||
|
|
direc < SWAP_UP || direc > SWAP_LEFT) {
|
|
return 0;
|
|
}
|
|
|
|
/* check for invalid directions */
|
|
if((x == 0 && direc == SWAP_LEFT) ||
|
|
(x == BJ_WIDTH-1 && direc == SWAP_RIGHT) ||
|
|
(y == 0 && direc == SWAP_UP) ||
|
|
(y == BJ_HEIGHT-2 && direc == SWAP_DOWN)) {
|
|
return 0;
|
|
}
|
|
|
|
/* set direction variables */
|
|
horzmod = 0;
|
|
vertmod = 0;
|
|
switch(direc) {
|
|
case SWAP_UP:
|
|
vertmod = -1;
|
|
movelen = TILE_HEIGHT;
|
|
break;
|
|
case SWAP_RIGHT:
|
|
horzmod = 1;
|
|
movelen = TILE_WIDTH;
|
|
break;
|
|
case SWAP_DOWN:
|
|
vertmod = 1;
|
|
movelen = TILE_HEIGHT;
|
|
break;
|
|
case SWAP_LEFT:
|
|
horzmod = -1;
|
|
movelen = TILE_WIDTH;
|
|
break;
|
|
}
|
|
|
|
while(true) {
|
|
lasttick = *rb->current_tick;
|
|
|
|
/* animate swapping jewels */
|
|
for(k=0; k<=8; k++) {
|
|
/* clear old position */
|
|
#ifdef HAVE_LCD_COLOR
|
|
rb->lcd_set_foreground(jewels_bkgd[(x+y)%2]);
|
|
rb->lcd_fillrect(x*TILE_WIDTH,
|
|
y*TILE_HEIGHT+YOFS,
|
|
TILE_WIDTH, TILE_HEIGHT);
|
|
rb->lcd_set_foreground(jewels_bkgd[(x+horzmod+y+vertmod)%2]);
|
|
rb->lcd_fillrect((x+horzmod)*TILE_WIDTH,
|
|
(y+vertmod)*TILE_HEIGHT+YOFS,
|
|
TILE_WIDTH, TILE_HEIGHT);
|
|
#else
|
|
rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
|
|
rb->lcd_fillrect(x*TILE_WIDTH,
|
|
y*TILE_HEIGHT+YOFS,
|
|
TILE_WIDTH, TILE_HEIGHT);
|
|
rb->lcd_fillrect((x+horzmod)*TILE_WIDTH,
|
|
(y+vertmod)*TILE_HEIGHT+YOFS,
|
|
TILE_WIDTH, TILE_HEIGHT);
|
|
rb->lcd_set_drawmode(DRMODE_SOLID);
|
|
#endif
|
|
/* draw new position */
|
|
#ifdef HAVE_LCD_COLOR
|
|
rb->lcd_bitmap_transparent_part(jewels,
|
|
0, TILE_HEIGHT*(bj->playboard
|
|
[y+1+vertmod][x+horzmod].type),
|
|
STRIDE( SCREEN_MAIN,
|
|
BMPWIDTH_jewels, BMPHEIGHT_jewels),
|
|
(x+horzmod)*TILE_WIDTH-horzmod*
|
|
((((movelen<<10)*k)/8)>>10),
|
|
(y+vertmod)*TILE_HEIGHT-vertmod*
|
|
((((movelen<<10)*k)/8)>>10)+YOFS,
|
|
TILE_WIDTH, TILE_HEIGHT);
|
|
rb->lcd_bitmap_transparent_part(jewels,
|
|
0, TILE_HEIGHT*(bj->playboard[y+1][x].type),
|
|
STRIDE( SCREEN_MAIN,
|
|
BMPWIDTH_jewels, BMPHEIGHT_jewels),
|
|
x*TILE_WIDTH+horzmod*
|
|
((((movelen<<10)*k)/8)>>10),
|
|
y*TILE_HEIGHT+vertmod*
|
|
((((movelen<<10)*k)/8)>>10)+YOFS,
|
|
TILE_WIDTH, TILE_HEIGHT);
|
|
#else
|
|
rb->lcd_bitmap_part(jewels,
|
|
0, TILE_HEIGHT*(bj->playboard
|
|
[y+1+vertmod][x+horzmod].type),
|
|
STRIDE( SCREEN_MAIN,
|
|
BMPWIDTH_jewels, BMPHEIGHT_jewels),
|
|
(x+horzmod)*TILE_WIDTH-horzmod*
|
|
((((movelen<<10)*k)/8)>>10),
|
|
(y+vertmod)*TILE_HEIGHT-vertmod*
|
|
((((movelen<<10)*k)/8)>>10)+YOFS,
|
|
TILE_WIDTH, TILE_HEIGHT);
|
|
rb->lcd_set_drawmode(DRMODE_FG);
|
|
rb->lcd_bitmap_part(jewels,
|
|
0, TILE_HEIGHT*(bj->playboard[y+1][x].type),
|
|
STRIDE( SCREEN_MAIN,
|
|
BMPWIDTH_jewels, BMPHEIGHT_jewels),
|
|
x*TILE_WIDTH+horzmod*
|
|
((((movelen<<10)*k)/8)>>10),
|
|
y*TILE_HEIGHT+vertmod*
|
|
((((movelen<<10)*k)/8)>>10)+YOFS,
|
|
TILE_WIDTH, TILE_HEIGHT);
|
|
rb->lcd_set_drawmode(DRMODE_SOLID);
|
|
#endif
|
|
|
|
rb->lcd_update_rect(0, 0, TILE_WIDTH*8, LCD_HEIGHT);
|
|
jewels_setcolors();
|
|
|
|
/* framerate limiting */
|
|
currenttick = *rb->current_tick;
|
|
if(currenttick-lasttick < HZ/MAX_FPS) {
|
|
rb->sleep((HZ/MAX_FPS)-(currenttick-lasttick));
|
|
} else {
|
|
rb->yield();
|
|
}
|
|
lasttick = currenttick;
|
|
}
|
|
|
|
/* swap jewels */
|
|
int temp = bj->playboard[y+1][x].type;
|
|
bj->playboard[y+1][x].type =
|
|
bj->playboard[y+1+vertmod][x+horzmod].type;
|
|
bj->playboard[y+1+vertmod][x+horzmod].type = temp;
|
|
|
|
if(undo) break;
|
|
|
|
points = jewels_runboard(bj);
|
|
if(points == 0) {
|
|
undo = true;
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
|
|
return points;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* jewels_movesavail() uses pattern matching to see if there are any
|
|
* available move left.
|
|
******************************************************************************/
|
|
static bool jewels_movesavail(struct game_context* bj) {
|
|
int i, j;
|
|
bool moves = false;
|
|
int mytype;
|
|
|
|
for(i=1; i<BJ_HEIGHT; i++) {
|
|
for(j=0; j<BJ_WIDTH; j++) {
|
|
mytype = bj->playboard[i][j].type;
|
|
if(mytype == 0 || mytype > MAX_NUM_JEWELS) continue;
|
|
|
|
/* check horizontal patterns */
|
|
if(j <= BJ_WIDTH-3) {
|
|
if(i > 1) {
|
|
if(bj->playboard[i-1][j+1].type == mytype) {
|
|
if(bj->playboard[i-1][j+2].type == mytype)
|
|
{moves = true; break;}
|
|
if(bj->playboard[i][j+2].type == mytype)
|
|
{moves = true; break;}
|
|
}
|
|
if(bj->playboard[i][j+1].type == mytype) {
|
|
if(bj->playboard[i-1][j+2].type == mytype)
|
|
{moves = true; break;}
|
|
}
|
|
}
|
|
|
|
if(j <= BJ_WIDTH-4) {
|
|
if(bj->playboard[i][j+3].type == mytype) {
|
|
if(bj->playboard[i][j+1].type == mytype)
|
|
{moves = true; break;}
|
|
if(bj->playboard[i][j+2].type == mytype)
|
|
{moves = true; break;}
|
|
}
|
|
}
|
|
|
|
if(i < BJ_HEIGHT-1) {
|
|
if(bj->playboard[i][j+1].type == mytype) {
|
|
if(bj->playboard[i+1][j+2].type == mytype)
|
|
{moves = true; break;}
|
|
}
|
|
if(bj->playboard[i+1][j+1].type == mytype) {
|
|
if(bj->playboard[i][j+2].type == mytype)
|
|
{moves = true; break;}
|
|
if(bj->playboard[i+1][j+2].type == mytype)
|
|
{moves = true; break;}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* check vertical patterns */
|
|
if(i <= BJ_HEIGHT-3) {
|
|
if(j > 0) {
|
|
if(bj->playboard[i+1][j-1].type == mytype) {
|
|
if(bj->playboard[i+2][j-1].type == mytype)
|
|
{moves = true; break;}
|
|
if(bj->playboard[i+2][j].type == mytype)
|
|
{moves = true; break;}
|
|
}
|
|
if(bj->playboard[i+1][j].type == mytype) {
|
|
if(bj->playboard[i+2][j-1].type == mytype)
|
|
{moves = true; break;}
|
|
}
|
|
}
|
|
|
|
if(i <= BJ_HEIGHT-4) {
|
|
if(bj->playboard[i+3][j].type == mytype) {
|
|
if(bj->playboard[i+1][j].type == mytype)
|
|
{moves = true; break;}
|
|
if(bj->playboard[i+2][j].type == mytype)
|
|
{moves = true; break;}
|
|
}
|
|
}
|
|
|
|
if(j < BJ_WIDTH-1) {
|
|
if(bj->playboard[i+1][j].type == mytype) {
|
|
if(bj->playboard[i+2][j+1].type == mytype)
|
|
{moves = true; break;}
|
|
}
|
|
if(bj->playboard[i+1][j+1].type == mytype) {
|
|
if(bj->playboard[i+2][j].type == mytype)
|
|
{moves = true; break;}
|
|
if (bj->playboard[i+2][j+1].type == mytype)
|
|
{moves = true; break;}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if(moves) break;
|
|
}
|
|
return moves;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* jewels_puzzle_is_finished() checks if the puzzle is finished.
|
|
******************************************************************************/
|
|
static bool jewels_puzzle_is_finished(struct game_context* bj) {
|
|
unsigned int i, j;
|
|
for(i=0; i<BJ_HEIGHT; i++) {
|
|
for(j=0; j<BJ_WIDTH; j++) {
|
|
int mytype = bj->playboard[i][j].type;
|
|
if(mytype>MAX_NUM_JEWELS) {
|
|
mytype -= MAX_NUM_JEWELS;
|
|
if(mytype&PUZZLE_TILE_UP) {
|
|
if(i==0 || bj->playboard[i-1][j].type<=MAX_NUM_JEWELS ||
|
|
!((bj->playboard[i-1][j].type-MAX_NUM_JEWELS)
|
|
&PUZZLE_TILE_DOWN))
|
|
return false;
|
|
}
|
|
if(mytype&PUZZLE_TILE_DOWN) {
|
|
if(i==BJ_HEIGHT-1 ||
|
|
bj->playboard[i+1][j].type<=MAX_NUM_JEWELS ||
|
|
!((bj->playboard[i+1][j].type-MAX_NUM_JEWELS)
|
|
&PUZZLE_TILE_UP))
|
|
return false;
|
|
}
|
|
if(mytype&PUZZLE_TILE_LEFT) {
|
|
if(j==0 || bj->playboard[i][j-1].type<=MAX_NUM_JEWELS ||
|
|
!((bj->playboard[i][j-1].type-MAX_NUM_JEWELS)
|
|
&PUZZLE_TILE_RIGHT))
|
|
return false;
|
|
}
|
|
if(mytype&PUZZLE_TILE_RIGHT) {
|
|
if(j==BJ_WIDTH-1 ||
|
|
bj->playboard[i][j+1].type<=MAX_NUM_JEWELS ||
|
|
!((bj->playboard[i][j+1].type-MAX_NUM_JEWELS)
|
|
&PUZZLE_TILE_LEFT))
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* jewels_initlevel() initialises a level.
|
|
******************************************************************************/
|
|
static unsigned int jewels_initlevel(struct game_context* bj) {
|
|
unsigned int points = 0;
|
|
|
|
switch(bj->type) {
|
|
case GAME_TYPE_NORMAL:
|
|
bj->num_jewels = MAX_NUM_JEWELS;
|
|
break;
|
|
|
|
case GAME_TYPE_PUZZLE:
|
|
{
|
|
unsigned int i, j;
|
|
struct puzzle_tile *tile;
|
|
|
|
bj->num_jewels = puzzle_levels[bj->level-1].num_jewels;
|
|
|
|
for(i=0; i<BJ_HEIGHT; i++) {
|
|
for(j=0; j<BJ_WIDTH; j++) {
|
|
bj->playboard[i][j].type = (rb->rand()%bj->num_jewels)+1;
|
|
bj->playboard[i][j].falling = false;
|
|
bj->playboard[i][j].delete = false;
|
|
}
|
|
}
|
|
jewels_runboard(bj);
|
|
tile = puzzle_levels[bj->level-1].tiles;
|
|
for(i=0; i<puzzle_levels[bj->level-1].num_tiles; i++, tile++) {
|
|
bj->playboard[tile->y+1][tile->x].type = MAX_NUM_JEWELS
|
|
+tile->tile_type;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
jewels_drawboard(bj);
|
|
|
|
/* run the play board */
|
|
jewels_putjewels(bj);
|
|
points += jewels_runboard(bj);
|
|
return points;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* jewels_init() initializes jewels data structures.
|
|
******************************************************************************/
|
|
static void jewels_init(struct game_context* bj) {
|
|
/* seed the rand generator */
|
|
rb->srand(*rb->current_tick);
|
|
|
|
bj->type = bj->tmp_type;
|
|
bj->level = 1;
|
|
bj->score = 0;
|
|
bj->segments = 0;
|
|
|
|
jewels_setcolors();
|
|
|
|
/* clear playing board */
|
|
rb->memset(bj->playboard, 0, sizeof(bj->playboard));
|
|
do {
|
|
bj->score += jewels_initlevel(bj);
|
|
} while(!jewels_movesavail(bj));
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* jewels_nextlevel() advances the game to the next bj->level and returns
|
|
* points earned.
|
|
******************************************************************************/
|
|
static void jewels_nextlevel(struct game_context* bj) {
|
|
int i, x, y;
|
|
unsigned int points = 0;
|
|
|
|
switch(bj->type) {
|
|
case GAME_TYPE_NORMAL:
|
|
/* roll over score, change and display level */
|
|
while(bj->score >= LEVEL_PTS) {
|
|
bj->score -= LEVEL_PTS;
|
|
bj->level++;
|
|
rb->splashf(HZ*2, "Level %d", bj->level);
|
|
jewels_drawboard(bj);
|
|
}
|
|
|
|
/* randomly clear some jewels */
|
|
for(i=0; i<16; i++) {
|
|
x = rb->rand()%8;
|
|
y = rb->rand()%8;
|
|
|
|
if(bj->playboard[y][x].type != 0) {
|
|
points++;
|
|
bj->playboard[y][x].type = 0;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case GAME_TYPE_PUZZLE:
|
|
bj->level++;
|
|
rb->splashf(HZ*2, "Level %d", bj->level);
|
|
break;
|
|
}
|
|
|
|
points += jewels_initlevel(bj);
|
|
bj->score += points;
|
|
}
|
|
|
|
static bool jewels_help(void)
|
|
{
|
|
static char *help_text[] = {
|
|
"Jewels", "", "Aim", "",
|
|
"Swap", "pairs", "of", "jewels", "to", "form", "connected",
|
|
"segments", "of", "three", "or", "more", "of", "the", "same",
|
|
"type.", "",
|
|
"The", "goal", "of", "the", "game", "is", "to", "score", "as", "many",
|
|
"points", "as", "possible", "before", "running", "out", "of",
|
|
"available", "moves.", "", "",
|
|
"Controls", "",
|
|
"Directions",
|
|
#ifdef JEWELS_SCROLLWHEEL
|
|
"or", "scroll",
|
|
#endif
|
|
"to", "move", "",
|
|
HK_SELECT, "to", "select", "",
|
|
HK_CANCEL, "to", "go", "to", "menu"
|
|
};
|
|
static struct style_text formation[]={
|
|
{ 0, TEXT_CENTER|TEXT_UNDERLINE },
|
|
{ 2, C_RED },
|
|
{ 42, C_RED },
|
|
LAST_STYLE_ITEM
|
|
};
|
|
|
|
rb->lcd_setfont(FONT_UI);
|
|
if (display_text(ARRAYLEN(help_text), help_text, formation, NULL, true))
|
|
return true;
|
|
rb->lcd_setfont(FONT_SYSFIXED);
|
|
|
|
return false;
|
|
}
|
|
|
|
static bool _ingame;
|
|
static int jewels_menu_cb(int action, const struct menu_item_ex *this_item)
|
|
{
|
|
int i = ((intptr_t)this_item);
|
|
if(action == ACTION_REQUEST_MENUITEM
|
|
&& !_ingame && (i==0 || i==6))
|
|
return ACTION_EXIT_MENUITEM;
|
|
return action;
|
|
}
|
|
/*****************************************************************************
|
|
* jewels_game_menu() shows the game menu.
|
|
******************************************************************************/
|
|
static int jewels_game_menu(struct game_context* bj, bool ingame)
|
|
{
|
|
rb->button_clear_queue();
|
|
int choice = 0;
|
|
|
|
_ingame = ingame;
|
|
|
|
static struct opt_items mode[] = {
|
|
{ "Normal", -1 },
|
|
{ "Puzzle", -1 },
|
|
};
|
|
|
|
MENUITEM_STRINGLIST (main_menu, "Jewels Menu", jewels_menu_cb,
|
|
"Resume Game",
|
|
"Start New Game",
|
|
"Mode",
|
|
"Help",
|
|
"High Scores",
|
|
"Playback Control",
|
|
"Quit without Saving",
|
|
"Quit");
|
|
|
|
while (1) {
|
|
switch (rb->do_menu(&main_menu, &choice, NULL, false)) {
|
|
case 0:
|
|
jewels_setcolors();
|
|
if(resume_file)
|
|
rb->remove(SAVE_FILE);
|
|
return 0;
|
|
case 1:
|
|
jewels_init(bj);
|
|
return 0;
|
|
case 2:
|
|
rb->set_option("Mode", &bj->tmp_type, INT, mode, 2, NULL);
|
|
break;
|
|
case 3:
|
|
if(jewels_help())
|
|
return 1;
|
|
break;
|
|
case 4:
|
|
highscore_show(-1, highscores, NUM_SCORES, true);
|
|
break;
|
|
case 5:
|
|
playback_control(NULL);
|
|
break;
|
|
case 6:
|
|
return 1;
|
|
case 7:
|
|
if (ingame) {
|
|
rb->splash(HZ*1, "Saving game ...");
|
|
jewels_savegame(bj);
|
|
}
|
|
return 1;
|
|
case MENU_ATTACHED_USB:
|
|
return 1;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
static int jewels_main(struct game_context* bj) {
|
|
int button;
|
|
int position;
|
|
bool selected = false;
|
|
bool no_movesavail;
|
|
int x=0, y=0;
|
|
|
|
bool loaded = jewels_loadgame(bj);
|
|
resume_file = loaded;
|
|
if (jewels_game_menu(bj, loaded)!=0)
|
|
return 0;
|
|
|
|
resume_file = false;
|
|
while(true) {
|
|
no_movesavail = false;
|
|
|
|
/* refresh the board */
|
|
jewels_drawboard(bj);
|
|
|
|
/* display the cursor */
|
|
if(selected) {
|
|
rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
|
|
rb->lcd_fillrect(x*TILE_WIDTH, y*TILE_HEIGHT+YOFS,
|
|
TILE_WIDTH, TILE_HEIGHT);
|
|
rb->lcd_set_drawmode(DRMODE_SOLID);
|
|
} else {
|
|
rb->lcd_drawrect(x*TILE_WIDTH, y*TILE_HEIGHT+YOFS,
|
|
TILE_WIDTH, TILE_HEIGHT);
|
|
}
|
|
rb->lcd_update_rect(x*TILE_WIDTH, y*TILE_HEIGHT+YOFS,
|
|
TILE_WIDTH, TILE_HEIGHT);
|
|
|
|
/* handle game button presses */
|
|
rb->yield();
|
|
button = rb->button_get(true);
|
|
switch(button){
|
|
case JEWELS_LEFT: /* move cursor left */
|
|
case (JEWELS_LEFT|BUTTON_REPEAT):
|
|
if(selected) {
|
|
bj->score += jewels_swapjewels(bj, x, y, SWAP_LEFT);
|
|
selected = false;
|
|
if (!jewels_movesavail(bj)) no_movesavail = true;
|
|
} else {
|
|
x = (x+BJ_WIDTH-1)%BJ_WIDTH;
|
|
}
|
|
break;
|
|
|
|
case JEWELS_RIGHT: /* move cursor right */
|
|
case (JEWELS_RIGHT|BUTTON_REPEAT):
|
|
if(selected) {
|
|
bj->score += jewels_swapjewels(bj, x, y, SWAP_RIGHT);
|
|
selected = false;
|
|
if (!jewels_movesavail(bj)) no_movesavail = true;
|
|
} else {
|
|
x = (x+1)%BJ_WIDTH;
|
|
}
|
|
break;
|
|
|
|
case JEWELS_DOWN: /* move cursor down */
|
|
case (JEWELS_DOWN|BUTTON_REPEAT):
|
|
if(selected) {
|
|
bj->score += jewels_swapjewels(bj, x, y, SWAP_DOWN);
|
|
selected = false;
|
|
if (!jewels_movesavail(bj)) no_movesavail = true;
|
|
} else {
|
|
y = (y+1)%(BJ_HEIGHT-1);
|
|
}
|
|
break;
|
|
|
|
case JEWELS_UP: /* move cursor up */
|
|
case (JEWELS_UP|BUTTON_REPEAT):
|
|
if(selected) {
|
|
bj->score += jewels_swapjewels(bj, x, y, SWAP_UP);
|
|
selected = false;
|
|
if (!jewels_movesavail(bj)) no_movesavail = true;
|
|
} else {
|
|
y = (y+(BJ_HEIGHT-1)-1)%(BJ_HEIGHT-1);
|
|
}
|
|
break;
|
|
|
|
#ifdef JEWELS_SCROLLWHEEL
|
|
case JEWELS_PREV: /* scroll backwards */
|
|
case (JEWELS_PREV|BUTTON_REPEAT):
|
|
if(!selected) {
|
|
if(x == 0) {
|
|
y = (y+(BJ_HEIGHT-1)-1)%(BJ_HEIGHT-1);
|
|
}
|
|
x = (x+BJ_WIDTH-1)%BJ_WIDTH;
|
|
}
|
|
break;
|
|
|
|
case JEWELS_NEXT: /* scroll forwards */
|
|
case (JEWELS_NEXT|BUTTON_REPEAT):
|
|
if(!selected) {
|
|
if(x == BJ_WIDTH-1) {
|
|
y = (y+1)%(BJ_HEIGHT-1);
|
|
}
|
|
x = (x+1)%BJ_WIDTH;
|
|
}
|
|
break;
|
|
#endif
|
|
|
|
case JEWELS_SELECT: /* toggle selected */
|
|
selected = !selected;
|
|
break;
|
|
|
|
#ifdef JEWELS_RC_CANCEL
|
|
case JEWELS_RC_CANCEL:
|
|
#endif
|
|
case JEWELS_CANCEL: /* end game */
|
|
if (jewels_game_menu(bj, true)!=0)
|
|
return 0;
|
|
break;
|
|
|
|
default:
|
|
if (rb->default_event_handler (button) == SYS_USB_CONNECTED)
|
|
return PLUGIN_USB_CONNECTED;
|
|
break;
|
|
}
|
|
|
|
switch(bj->type) {
|
|
case GAME_TYPE_NORMAL:
|
|
if(bj->score >= LEVEL_PTS)
|
|
jewels_nextlevel(bj);
|
|
break;
|
|
case GAME_TYPE_PUZZLE:
|
|
if (jewels_puzzle_is_finished(bj)) {
|
|
if (bj->level < NUM_PUZZLE_LEVELS) {
|
|
jewels_nextlevel(bj);
|
|
} else {
|
|
rb->splash(2*HZ, "Congratulations!");
|
|
rb->splash(2*HZ, "You have finished the game!");
|
|
if (jewels_game_menu(bj, false)!=0) {
|
|
return 0;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (no_movesavail) {
|
|
switch(bj->type) {
|
|
case GAME_TYPE_NORMAL:
|
|
rb->splash(HZ*2, "Game Over!");
|
|
rb->lcd_clear_display();
|
|
bj->score += (bj->level-1)*LEVEL_PTS;
|
|
position=highscore_update(bj->score, bj->level, "",
|
|
highscores, NUM_SCORES);
|
|
if (position != -1)
|
|
{
|
|
if (position == 0)
|
|
rb->splash(HZ*2, "New High Score");
|
|
highscore_show(position, highscores, NUM_SCORES, true);
|
|
}
|
|
break;
|
|
case GAME_TYPE_PUZZLE:
|
|
rb->splash(2*HZ, "Game Over");
|
|
break;
|
|
}
|
|
if (jewels_game_menu(bj, false)!=0) {
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* this is the plugin entry point */
|
|
enum plugin_status plugin_start(const void* parameter)
|
|
{
|
|
(void)parameter;
|
|
|
|
/* load high scores */
|
|
highscore_load(SCORE_FILE, highscores, NUM_SCORES);
|
|
|
|
rb->lcd_setfont(FONT_SYSFIXED);
|
|
#if LCD_DEPTH > 1
|
|
rb->lcd_set_backdrop(NULL);
|
|
#endif
|
|
|
|
struct game_context bj;
|
|
bj.tmp_type = GAME_TYPE_NORMAL;
|
|
jewels_main(&bj);
|
|
highscore_save(SCORE_FILE, highscores, NUM_SCORES);
|
|
rb->lcd_setfont(FONT_UI);
|
|
|
|
return PLUGIN_OK;
|
|
}
|