summaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
authorAntoine Cellerier <dionoea@videolan.org>2006-08-02 22:17:21 +0000
committerAntoine Cellerier <dionoea@videolan.org>2006-08-02 22:17:21 +0000
commit5e2a9a19cf97129580b5567527824ce89078d3fd (patch)
treeddef6df574bb6d3d4878eca97a4930d6fb6c03b1 /apps
parentc00c94e1a4f2099aadc2569c1300125396ad5203 (diff)
downloadrockbox-5e2a9a19cf97129580b5567527824ce89078d3fd.tar.gz
rockbox-5e2a9a19cf97129580b5567527824ce89078d3fd.zip
Cleanup solitaire code a bit. A side effect is that it should now be possible to play on small LCD screens like the recorder's (which had become impossible since revision 1.20).
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@10422 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps')
-rw-r--r--apps/plugins/solitaire.c1615
1 files changed, 815 insertions, 800 deletions
diff --git a/apps/plugins/solitaire.c b/apps/plugins/solitaire.c
index a9a0d5c762..e85872ee2a 100644
--- a/apps/plugins/solitaire.c
+++ b/apps/plugins/solitaire.c
@@ -7,7 +7,7 @@
7 * \/ \/ \/ \/ \/ 7 * \/ \/ \/ \/ \/
8 * $Id$ 8 * $Id$
9 * 9 *
10 * Copyright (C) 2004-2006 dionoea (Antoine Cellerier) 10 * Copyright (C) 2004-2006 Antoine Cellerier <dionoea @t videolan d.t org>
11 * 11 *
12 * All files in this archive are subject to the GNU General Public License. 12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement. 13 * See the file COPYING in the source tree root for full license agreement.
@@ -36,253 +36,246 @@ use F3 to put card on top of the remains' stack on one of the 4 final stacks
36#include "button.h" 36#include "button.h"
37#include "lcd.h" 37#include "lcd.h"
38 38
39
40#ifdef HAVE_LCD_BITMAP 39#ifdef HAVE_LCD_BITMAP
41 40
42PLUGIN_HEADER 41PLUGIN_HEADER
43 42
44/* here is a global api struct pointer. while not strictly necessary,
45 it's nice not to have to pass the api pointer in all function calls
46 in the plugin */
47static struct plugin_api* rb; 43static struct plugin_api* rb;
48
49#define min(a,b) (a<b?a:b) 44#define min(a,b) (a<b?a:b)
50 45
46/**
47 * Key definitions
48 */
51 49
52/* variable button definitions */
53#if CONFIG_KEYPAD == RECORDER_PAD
54#define SOL_QUIT BUTTON_OFF
55#define SOL_UP BUTTON_UP
56#define SOL_DOWN BUTTON_DOWN
57#define SOL_LEFT BUTTON_LEFT
58#define SOL_RIGHT BUTTON_RIGHT
59#define SOL_MOVE BUTTON_ON
60#define SOL_DRAW BUTTON_F2
61#define SOL_REM2CUR BUTTON_PLAY
62#define SOL_CUR2STACK BUTTON_F1
63#define SOL_REM2STACK BUTTON_F3
64#define SOL_MENU_RUN BUTTON_RIGHT
65#define SOL_MENU_RUN2 BUTTON_PLAY
66#define SOL_MENU_INFO BUTTON_F1
67#define SOL_MENU_INFO2 BUTTON_F2
68#define SOL_MENU_INFO3 BUTTON_F3
69
70#elif CONFIG_KEYPAD == ONDIO_PAD
71#define SOL_QUIT BUTTON_OFF
72#define SOL_UP_PRE BUTTON_UP
73#define SOL_UP (BUTTON_UP | BUTTON_REL)
74#define SOL_DOWN_PRE BUTTON_DOWN
75#define SOL_DOWN (BUTTON_DOWN | BUTTON_REL)
76#define SOL_LEFT_PRE BUTTON_LEFT
77#define SOL_LEFT (BUTTON_LEFT | BUTTON_REL)
78#define SOL_RIGHT_PRE BUTTON_RIGHT
79#define SOL_RIGHT (BUTTON_RIGHT | BUTTON_REL)
80#define SOL_MOVE_PRE BUTTON_MENU
81#define SOL_MOVE (BUTTON_MENU | BUTTON_REL)
82#define SOL_DRAW_PRE BUTTON_MENU
83#define SOL_DRAW (BUTTON_MENU | BUTTON_REPEAT)
84#define SOL_REM2CUR_PRE BUTTON_LEFT
85#define SOL_REM2CUR (BUTTON_LEFT | BUTTON_REPEAT)
86#define SOL_CUR2STACK_PRE BUTTON_RIGHT
87#define SOL_CUR2STACK (BUTTON_RIGHT | BUTTON_REPEAT)
88#define SOL_REM2STACK_PRE BUTTON_UP
89#define SOL_REM2STACK (BUTTON_UP | BUTTON_REPEAT)
90#define SOL_MENU_RUN BUTTON_RIGHT
91#define SOL_MENU_INFO BUTTON_MENU
92
93#elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
94 (CONFIG_KEYPAD == IRIVER_H300_PAD)
95#define SOL_QUIT BUTTON_OFF
96#define SOL_UP BUTTON_UP
97#define SOL_DOWN BUTTON_DOWN
98#define SOL_LEFT BUTTON_LEFT
99#define SOL_RIGHT BUTTON_RIGHT
100#define SOL_MOVE_PRE BUTTON_SELECT
101#define SOL_MOVE (BUTTON_SELECT | BUTTON_REL)
102#define SOL_DRAW BUTTON_MODE
103#define SOL_REM2CUR (BUTTON_LEFT | BUTTON_ON)
104#define SOL_CUR2STACK (BUTTON_SELECT | BUTTON_REPEAT)
105#define SOL_REM2STACK (BUTTON_RIGHT | BUTTON_ON)
106#define SOL_MENU_RUN BUTTON_SELECT
107#define SOL_MENU_RUN2 BUTTON_RIGHT
108#define SOL_MENU_INFO BUTTON_MODE
109#define SOL_OPT BUTTON_ON
110#define SOL_REM BUTTON_REC
111
112#define SOL_RC_QUIT BUTTON_RC_STOP
113
114#elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
115 (CONFIG_KEYPAD == IPOD_3G_PAD)
116#define SOL_QUIT (BUTTON_SELECT | BUTTON_MENU)
117#define SOL_UP BUTTON_MENU
118#define SOL_DOWN BUTTON_PLAY
119#define SOL_LEFT BUTTON_LEFT
120#define SOL_RIGHT BUTTON_RIGHT
121#define SOL_MOVE BUTTON_SELECT
122#define SOL_DRAW (BUTTON_SELECT | BUTTON_PLAY)
123#define SOL_REM2CUR (BUTTON_SELECT | BUTTON_LEFT)
124#define SOL_CUR2STACK (BUTTON_SELECT | BUTTON_RIGHT)
125#define SOL_REM2STACK (BUTTON_LEFT | BUTTON_RIGHT)
126#define SOL_MENU_RUN BUTTON_SELECT
127#define SOL_MENU_INFO (BUTTON_PLAY | BUTTON_MENU)
128
129#elif (CONFIG_KEYPAD == IAUDIO_X5_PAD)
130#define SOL_QUIT BUTTON_POWER
131#define SOL_UP BUTTON_UP
132#define SOL_DOWN BUTTON_DOWN
133#define SOL_LEFT BUTTON_LEFT
134#define SOL_RIGHT BUTTON_RIGHT
135#define SOL_MOVE BUTTON_SELECT
136#define SOL_DRAW BUTTON_PLAY
137#define SOL_REM2CUR (BUTTON_REC | BUTTON_LEFT)
138#define SOL_CUR2STACK (BUTTON_REC | BUTTON_UP)
139#define SOL_REM2STACK (BUTTON_REC | BUTTON_DOWN)
140#define SOL_MENU_RUN BUTTON_SELECT
141#define SOL_MENU_INFO BUTTON_PLAY
142
143#elif (CONFIG_KEYPAD == GIGABEAT_PAD)
144#define SOL_QUIT BUTTON_A
145#define SOL_UP BUTTON_UP
146#define SOL_DOWN BUTTON_DOWN
147#define SOL_LEFT BUTTON_LEFT
148#define SOL_RIGHT BUTTON_RIGHT
149#define SOL_MOVE_PRE BUTTON_SELECT
150#define SOL_MOVE (BUTTON_SELECT | BUTTON_REL)
151#define SOL_DRAW BUTTON_MENU
152#define SOL_REM2CUR (BUTTON_LEFT | BUTTON_POWER)
153#define SOL_CUR2STACK (BUTTON_SELECT | BUTTON_REPEAT)
154#define SOL_REM2STACK (BUTTON_RIGHT | BUTTON_POWER)
155#define SOL_MENU_RUN BUTTON_SELECT
156#define SOL_MENU_RUN2 BUTTON_RIGHT
157#define SOL_MENU_INFO BUTTON_MENU
158#endif
159
160/* common help definitions */
161#define HELP_SOL_UP "UP: Move the cursor up in the column."
162#define HELP_SOL_DOWN "DOWN: Move the cursor down in the column."
163#define HELP_SOL_LEFT "LEFT: Move the cursor to the previous column."
164#define HELP_SOL_RIGHT "RIGHT: Move the cursor to the next column."
165
166/* variable help definitions */
167#if CONFIG_KEYPAD == RECORDER_PAD 50#if CONFIG_KEYPAD == RECORDER_PAD
168#define HELP_SOL_MOVE "ON: Select cards, Move cards, reveal hidden cards ..." 51# define SOL_QUIT BUTTON_OFF
169#define HELP_SOL_DRAW "F2: Un-select a card if it was selected. Else, draw 3 new cards out of the remains' stack." 52# define SOL_UP BUTTON_UP
170#define HELP_SOL_REM2CUR "PLAY: Put the card on top of the remains' stack on top of the cursor." 53# define SOL_DOWN BUTTON_DOWN
171#define HELP_SOL_CUR2STACK "F1: Put the card under the cursor on one of the 4 final stacks." 54# define SOL_LEFT BUTTON_LEFT
172#define HELP_SOL_REM2STACK "F3: Put the card on top of the remains' stack on one of the 4 final stacks." 55# define SOL_RIGHT BUTTON_RIGHT
56# define SOL_MOVE BUTTON_ON
57# define SOL_DRAW BUTTON_F2
58# define SOL_REM2CUR BUTTON_PLAY
59# define SOL_CUR2STACK BUTTON_F1
60# define SOL_REM2STACK BUTTON_F3
61# define SOL_MENU_RUN BUTTON_RIGHT
62# define SOL_MENU_RUN2 BUTTON_PLAY
63# define HK_MOVE "ON"
64# define HK_DRAW "F2"
65# define HK_REM2CUR "PLAY"
66# define HK_CUR2STACK "F1"
67# define HK_REM2STACK "F3"
173 68
174#elif CONFIG_KEYPAD == ONDIO_PAD 69#elif CONFIG_KEYPAD == ONDIO_PAD
175#define HELP_SOL_MOVE "MODE: Select cards, Move cards, reveal hidden cards ..." 70# define SOL_QUIT BUTTON_OFF
176#define HELP_SOL_DRAW "MODE..: Un-select a card if it was selected. Else, draw 3 new cards out of the remains' stack." 71# define SOL_UP_PRE BUTTON_UP
177#define HELP_SOL_REM2CUR "LEFT..: Put the card on top of the remains' stack on top of the cursor." 72# define SOL_UP (BUTTON_UP | BUTTON_REL)
178#define HELP_SOL_CUR2STACK "RIGHT..: Put the card under the cursor on one of the 4 final stacks." 73# define SOL_DOWN_PRE BUTTON_DOWN
179#define HELP_SOL_REM2STACK "UP..: Put the card on top of the remains' stack on one of the 4 final stacks." 74# define SOL_DOWN (BUTTON_DOWN | BUTTON_REL)
75# define SOL_LEFT_PRE BUTTON_LEFT
76# define SOL_LEFT (BUTTON_LEFT | BUTTON_REL)
77# define SOL_RIGHT_PRE BUTTON_RIGHT
78# define SOL_RIGHT (BUTTON_RIGHT | BUTTON_REL)
79# define SOL_MOVE_PRE BUTTON_MENU
80# define SOL_MOVE (BUTTON_MENU | BUTTON_REL)
81# define SOL_DRAW_PRE BUTTON_MENU
82# define SOL_DRAW (BUTTON_MENU | BUTTON_REPEAT)
83# define SOL_REM2CUR_PRE BUTTON_LEFT
84# define SOL_REM2CUR (BUTTON_LEFT | BUTTON_REPEAT)
85# define SOL_CUR2STACK_PRE BUTTON_RIGHT
86# define SOL_CUR2STACK (BUTTON_RIGHT | BUTTON_REPEAT)
87# define SOL_REM2STACK_PRE BUTTON_UP
88# define SOL_REM2STACK (BUTTON_UP | BUTTON_REPEAT)
89# define SOL_MENU_RUN BUTTON_RIGHT
90# define HK_MOVE "MODE"
91# define HK_DRAW "MODE.."
92# define HK_REM2CUR "LEFT.."
93# define HK_CUR2STACK "RIGHT.."
94# define HK_REM2STACK "UP.."
180 95
181#elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \ 96#elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
182 (CONFIG_KEYPAD == IRIVER_H300_PAD) 97 (CONFIG_KEYPAD == IRIVER_H300_PAD)
183#define HELP_SOL_MOVE "SELECT: Select cards, Move cards, reveal hidden cards ..." 98# define SOL_QUIT BUTTON_OFF
184#define HELP_SOL_DRAW "REC: Un-select a card if it was selected. Else, draw 3 new cards out of the remains' stack." 99# define SOL_UP BUTTON_UP
185#define HELP_SOL_REM2CUR "PLAY+LEFT: Put the card on top of the remains' stack on top of the cursor." 100# define SOL_DOWN BUTTON_DOWN
186#define HELP_SOL_CUR2STACK "SELECT..: Put the card under the cursor on one of the 4 final stacks." 101# define SOL_LEFT BUTTON_LEFT
187#define HELP_SOL_REM2STACK "PLAY+RIGHT: Put the card on top of the remains' stack on one of the 4 final stacks." 102# define SOL_RIGHT BUTTON_RIGHT
103# define SOL_MOVE_PRE BUTTON_SELECT
104# define SOL_MOVE (BUTTON_SELECT | BUTTON_REL)
105# define SOL_DRAW BUTTON_MODE
106# define SOL_REM2CUR (BUTTON_LEFT | BUTTON_ON)
107# define SOL_CUR2STACK (BUTTON_SELECT | BUTTON_REPEAT)
108# define SOL_REM2STACK (BUTTON_RIGHT | BUTTON_ON)
109# define SOL_MENU_RUN BUTTON_SELECT
110# define SOL_MENU_RUN2 BUTTON_RIGHT
111# define SOL_OPT BUTTON_ON
112# define SOL_REM BUTTON_REC
113# define SOL_RC_QUIT BUTTON_RC_STOP
114# define HK_MOVE "SELECT"
115# define HK_DRAW "REC"
116# define HK_REM2CUR "PLAY+LEFT"
117# define HK_CUR2STACK "SELECT"
118# define HK_REM2STACK "PLAY+RIGHT"
188 119
189#elif (CONFIG_KEYPAD == IPOD_4G_PAD) ||(CONFIG_KEYPAD == IPOD_3G_PAD) 120#elif (CONFIG_KEYPAD == IPOD_4G_PAD) ||(CONFIG_KEYPAD == IPOD_3G_PAD)
190#define HELP_SOL_MOVE "SELECT: Select cards, Move cards, reveal hidden cards ..." 121# define SOL_QUIT (BUTTON_SELECT | BUTTON_MENU)
191#define HELP_SOL_DRAW "SELECT+PLAY: Un-select a card if it was selected. Else, draw 3 new cards out of the remains' stack." 122# define SOL_UP BUTTON_MENU
192#define HELP_SOL_REM2CUR "SELECT+LEFT: Put the card on top of the remains' stack on top of the cursor." 123# define SOL_DOWN BUTTON_PLAY
193#define HELP_SOL_CUR2STACK "SELECT+RIGHT..: Put the card under the cursor on one of the 4 final stacks." 124# define SOL_LEFT BUTTON_LEFT
194#define HELP_SOL_REM2STACK "LEFT+RIGHT: Put the card on top of the remains' stack on one of the 4 final stacks." 125# define SOL_RIGHT BUTTON_RIGHT
126# define SOL_MOVE BUTTON_SELECT
127# define SOL_DRAW (BUTTON_SELECT | BUTTON_PLAY)
128# define SOL_REM2CUR (BUTTON_SELECT | BUTTON_LEFT)
129# define SOL_CUR2STACK (BUTTON_SELECT | BUTTON_RIGHT)
130# define SOL_REM2STACK (BUTTON_LEFT | BUTTON_RIGHT)
131# define SOL_MENU_RUN BUTTON_SELECT
132# define HK_MOVE "SELECT"
133# define HK_DRAW "SELECT+PLAY"
134# define HK_REM2CUR "SELECT+LEFT"
135# define HK_CUR2STACK "SELECT+RIGHT.."
136# define HK_REM2STACK "LEFT+RIGHT"
195 137
196#elif (CONFIG_KEYPAD == IAUDIO_X5_PAD) 138#elif (CONFIG_KEYPAD == IAUDIO_X5_PAD)
197#define HELP_SOL_MOVE "MENU: Select cards, Move cards, reveal hidden cards ..." 139# define SOL_QUIT BUTTON_POWER
198#define HELP_SOL_DRAW "PLAY: Un-select a card if it was selected. Else, draw 3 new cards out of the remains' stack." 140# define SOL_UP BUTTON_UP
199#define HELP_SOL_REM2CUR "REC+LEFT: Put the card on top of the remains' stack on top of the cursor." 141# define SOL_DOWN BUTTON_DOWN
200#define HELP_SOL_CUR2STACK "REC+UP..: Put the card under the cursor on one of the 4 final stacks." 142# define SOL_LEFT BUTTON_LEFT
201#define HELP_SOL_REM2STACK "REC+DOWN: Put the card on top of the remains' stack on one of the 4 final stacks." 143# define SOL_RIGHT BUTTON_RIGHT
144# define SOL_MOVE BUTTON_SELECT
145# define SOL_DRAW BUTTON_PLAY
146# define SOL_REM2CUR (BUTTON_REC | BUTTON_LEFT)
147# define SOL_CUR2STACK (BUTTON_REC | BUTTON_UP)
148# define SOL_REM2STACK (BUTTON_REC | BUTTON_DOWN)
149# define SOL_MENU_RUN BUTTON_SELECT
150# define HK_MOVE "MENU"
151# define HK_DRAW "PLAY"
152# define HK_REM2CUR "REC+LEFT"
153# define HK_CUR2STACK "REC+UP.."
154# define HK_REM2STACK "REC+DOWN"
202 155
203#elif (CONFIG_KEYPAD == GIGABEAT_PAD) 156#elif (CONFIG_KEYPAD == GIGABEAT_PAD)
204#define HELP_SOL_MOVE "SELECT: Select cards, Move cards, reveal hidden cards ..." 157# define SOL_QUIT BUTTON_A
205#define HELP_SOL_DRAW "MENU: Un-select a card if it was selected. Else, draw 3 new cards out of the remains' stack." 158# define SOL_UP BUTTON_UP
206#define HELP_SOL_REM2CUR "POWER+LEFT: Put the card on top of the remains' stack on top of the cursor." 159# define SOL_DOWN BUTTON_DOWN
207#define HELP_SOL_CUR2STACK "SELECT..: Put the card under the cursor on one of the 4 final stacks." 160# define SOL_LEFT BUTTON_LEFT
208#define HELP_SOL_REM2STACK "POWER+RIGHT: Put the card on top of the remains' stack on one of the 4 final stacks." 161# define SOL_RIGHT BUTTON_RIGHT
162# define SOL_MOVE_PRE BUTTON_SELECT
163# define SOL_MOVE (BUTTON_SELECT | BUTTON_REL)
164# define SOL_DRAW BUTTON_MENU
165# define SOL_REM2CUR (BUTTON_LEFT | BUTTON_POWER)
166# define SOL_CUR2STACK (BUTTON_SELECT | BUTTON_REPEAT)
167# define SOL_REM2STACK (BUTTON_RIGHT | BUTTON_POWER)
168# define SOL_MENU_RUN BUTTON_SELECT
169# define SOL_MENU_RUN2 BUTTON_RIGHT
170# define HK_MOVE "SELECT"
171# define HK_DRAW "MENU"
172# define HK_REM2CUR "POWER+LEFT"
173# define HK_CUR2STACK "SELECT.."
174# define HK_REM2STACK "POWER+RIGHT"
209 175
210#endif
211
212#if LCD_DEPTH>1
213static const unsigned colors[4] = {
214#ifdef HAVE_LCD_COLOR
215 LCD_BLACK, LCD_RGBPACK(255, 0, 0), LCD_BLACK, LCD_RGBPACK(255, 0, 0)
216#else 176#else
217 LCD_BLACK, LCD_BRIGHTNESS(127), LCD_BLACK, LCD_BRIGHTNESS(127) 177# error "Unknown keypad"
218#endif
219};
220#endif 178#endif
221 179
222#define BMPHEIGHT_c 10 180/**
223#define BMPWIDTH_c 8 181 * Help strings
182 */
183
184#define HELP_SOL_UP "UP: Move the cursor up in the column."
185#define HELP_SOL_DOWN "DOWN: Move the cursor down in the column."
186#define HELP_SOL_LEFT "LEFT: Move the cursor to the previous column."
187#define HELP_SOL_RIGHT "RIGHT: Move the cursor to the next column."
188#define HELP_SOL_MOVE HK_MOVE \
189 ": Select cards, Move cards, reveal hidden cards ..."
190#define HELP_SOL_DRAW HK_DRAW \
191 ": Un-select a card if it was selected. " \
192 "Else, draw 3 new cards out of the remains' stack."
193#define HELP_SOL_REM2CUR HK_REM2CUR \
194 ": Put the card on top of the remains' stack on top of the cursor."
195#define HELP_SOL_CUR2STACK HK_CUR2STACK \
196 ": Put the card under the cursor on one of the 4 final stacks."
197#define HELP_SOL_REM2STACK HK_REM2STACK \
198 ": Put the card on top of the remains' stack on one of the 4 final stacks."
199
200/**
201 * Misc constants, graphics and other defines
202 */
224 203
225#ifdef HAVE_LCD_COLOR 204/* size of a card on the screen */
226#if (LCD_WIDTH >= 220) && (LCD_HEIGHT >= 176) 205#if (LCD_WIDTH >= 220) && (LCD_HEIGHT >= 176)
227#define BMPHEIGHT_CARDBACK 33 206# define CARD_WIDTH 27
228#define BMPWIDTH_CARDBACK 26 207# define CARD_HEIGHT 34
208#elif LCD_HEIGHT > 64
209# define CARD_WIDTH 19
210# define CARD_HEIGHT 24
229#else 211#else
230#define BMPHEIGHT_CARDBACK 24 212# define CARD_WIDTH 14
231#define BMPWIDTH_CARDBACK 18 213# define CARD_HEIGHT 10
232#endif 214#endif
233 215
234extern const fb_data solitaire_cardback[]; 216/* where the cards start */
217#define CARD_START ( CARD_HEIGHT + 4 )
218
219#if LCD_HEIGHT > 64
220# define NUMBER_HEIGHT 10
221# define NUMBER_WIDTH 8
222# define NUMBER_STRIDE 8
223# define SUIT_HEIGHT 10
224# define SUIT_WIDTH 8
225# define SUIT_STRIDE 8
226#else
227# define NUMBER_HEIGHT 6
228# define NUMBER_WIDTH 6
229# define NUMBER_STRIDE 6
230# define SUIT_HEIGHT 6
231# define SUIT_WIDTH 6
232# define SUIT_STRIDE 6
235#endif 233#endif
236 234
237static const unsigned char suitsi[4][30] = { 235#define SUITI_HEIGHT 16
238 {0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x07, 0x0f, 0x1f, 0x1f, 0x0f, 0x7f, 0x7f, 0x7f, 0x0f, 0x1f, 0x1f, 0x0f, 0x07, 0x00}, 236#define SUITI_WIDTH 15
239 {0x00, 0xf0, 0xf8, 0xfc, 0xfe, 0xfc, 0xf8, 0xf0, 0xf8, 0xfc, 0xfe, 0xfc, 0xf8, 0xf0, 0x00, 0x00, 0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x7f, 0x1f, 0x0f, 0x07, 0x03, 0x01, 0x00, 0x00}, 237#define SUITI_STRIDE 16
240 {0x00, 0xc0, 0xe0, 0xe0, 0xfc, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfc, 0xe0, 0xe0, 0xc0, 0x00, 0x00, 0x03, 0x07, 0x07, 0x0f, 0x0f, 0x7f, 0x7f, 0x7f, 0x0f, 0x0f, 0x07, 0x07, 0x03, 0x00}, 238
241 {0x00, 0x00, 0x00, 0x00, 0x80, 0xe0, 0xf8, 0xfe, 0xfe, 0xf8, 0xe0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x07, 0x1f, 0x7f, 0x7f, 0x1f, 0x07, 0x01, 0x00, 0x00, 0x00}, 239
242}; 240#define draw_number( num, x, y ) \
243static const unsigned char suits[4][16] = { 241 rb->lcd_bitmap_part( numbers, 0, num * NUMBER_HEIGHT, NUMBER_STRIDE, \
244/* Spades */ 242 x, y, NUMBER_WIDTH, NUMBER_HEIGHT );
245 {0x00, 0x78, 0x3c, 0xfe, 0xfe, 0x3c, 0x78, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00},/* ........ */ 243extern const fb_data solitaire_numbers[];
246/* Hearts */ 244#define numbers solitaire_numbers
247 {0x00, 0x3c, 0x7e, 0xfc, 0xf8, 0xfc, 0x7e, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00},/* ........ */ 245
248/* Clubs */ 246#define draw_suit( num, x, y ) \
249 {0x00, 0x70, 0x34, 0xfe, 0xfe, 0x34, 0x70, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00},/* ........ */ 247 rb->lcd_bitmap_part( suits, 0, num * SUIT_HEIGHT, SUIT_STRIDE, \
250/* Diamonds */ 248 x, y, SUIT_WIDTH, SUIT_HEIGHT );
251 {0x00, 0x70, 0xfc, 0xfe, 0xfe, 0xfc, 0x70, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00} /* ........ */ 249extern const fb_data solitaire_suits[];
252}; 250#define suits solitaire_suits
253 251
254static unsigned char numbers[13][16] = { 252#if ( CARD_HEIGHT < SUITI_HEIGHT + 1 ) || ( CARD_WIDTH < SUITI_WIDTH + 1 )
255/* Ace */ 253# undef SUITI_HEIGHT
256 {0x00, 0xf0, 0xfc, 0x7e, 0x36, 0x7e, 0xfc, 0xf0, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01}, 254# undef SUITI_WIDTH
257/* 2 */ 255# define SUITI_HEIGHT SUIT_HEIGHT
258 {0x00, 0x8c, 0xce, 0xe6, 0xf6, 0xbe, 0x9c, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00}, /* ........ */ 256# define SUITI_WIDTH SUIT_WIDTH
259/* 3 */ 257# define draw_suiti( num, x, y ) draw_suit( num, x, y )
260 {0x00, 0xcc, 0x86, 0xb6, 0xb6, 0xfe, 0xdc, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00}, /* ........ */ 258#else
261/* 4 */ 259# define draw_suiti( num, x, y ) \
262 {0x00, 0x3e, 0x3e, 0x30, 0xfe, 0xfe, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00}, /* ........ */ 260 rb->lcd_bitmap_part( suitsi, 0, num * SUITI_HEIGHT, SUITI_STRIDE, \
263/* 5 */ 261 x, y, SUITI_WIDTH, SUITI_HEIGHT );
264 {0x00, 0xbe, 0xbe, 0xb6, 0xb6, 0xf6, 0xe6, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00}, /* ........ */ 262 extern const fb_data solitaire_suitsi[];
265/* 6 */ 263# define suitsi solitaire_suitsi
266 {0x00, 0xfc, 0xfe, 0xb6, 0xb6, 0xf6, 0xe4, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00}, /* ........ */ 264#endif
267/* 7 */
268 {0x00, 0x86, 0xc6, 0x66, 0x36, 0x1e, 0x0e, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00}, /* ........ */
269/* 8 */
270 {0x00, 0xdc, 0xfe, 0xb6, 0xb6, 0xfe, 0xdc, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00}, /* ........ */
271/* 9 */
272 {0x00, 0x9c, 0xbe, 0xb6, 0xb6, 0xfe, 0xfc, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00}, /* ........ */
273/* 10 */
274 {0x00, 0x18, 0x0c, 0xfe, 0x00, 0xfc, 0x86, 0xfc, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00}, /* ........ */
275/* Jack */
276 {0x00, 0xe6, 0xc6, 0x86, 0xfe, 0xfe, 0x06, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00}, /* ........ */
277/* Queen */
278 {0x00, 0x7c, 0xfe, 0xc6, 0xe6, 0xfe, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00}, /* ........ */
279/* King */
280 {0x00, 0xfe, 0xfe, 0x38, 0x7c, 0xee, 0xc6, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00} /* ........ */
281};
282
283 265
284#define FILENAME "sol.cfg" 266#ifdef HAVE_LCD_COLOR
267# if (LCD_WIDTH >= 220) && (LCD_HEIGHT >= 176)
268# define CARDBACK_HEIGHT 33
269# define CARDBACK_WIDTH 26
270# else
271# define CARDBACK_HEIGHT 24
272# define CARDBACK_WIDTH 18
273# endif
274
275 extern const fb_data solitaire_cardback[];
276#endif
285 277
278#define CONFIG_FILENAME "sol.cfg"
286 279
287#define NOT_A_CARD 255 280#define NOT_A_CARD 255
288 281
@@ -292,76 +285,155 @@ static unsigned char numbers[13][16] = {
292/* number of suits */ 285/* number of suits */
293#define SUITS 4 286#define SUITS 4
294 287
288#define NUM_CARDS ( CARDS_PER_SUIT * SUITS )
289
295/* number of columns */ 290/* number of columns */
296#define COL_NUM 7 291#define COL_NUM 7
297 292
298/* pseudo column numbers to be used for cursor coordinates */ 293/* pseudo column numbers to be used for cursor coordinates */
299/* columns COL_NUM t COL_NUM + SUITS - 1 correspond to the final stacks */ 294/* columns COL_NUM to COL_NUM + SUITS - 1 correspond to the final stacks */
300#define STACKS_COL COL_NUM 295#define STACKS_COL COL_NUM
301/* column COL_NUM + SUITS corresponds to the remains' stack */ 296/* column COL_NUM + SUITS corresponds to the remains' stack */
302#define REM_COL (STACKS_COL + SUITS) 297#define REM_COL (STACKS_COL + SUITS)
303 298
304#define NOT_A_COL 255 299#define NOT_A_COL 255
305 300
301/* background color */
302#define BACKGROUND_COLOR LCD_RGBPACK(0,157,0)
306 303
307/* size of a card on the screen */ 304#if LCD_DEPTH > 1 && !defined( LCD_WHITE )
308#if (LCD_WIDTH >= 220) && (LCD_HEIGHT >= 176) 305# define LCD_WHITE LCD_DEFAULT_BG
309#define CARD_WIDTH 26
310#define CARD_HEIGHT 34
311#else
312#define CARD_WIDTH 18
313#define CARD_HEIGHT 24
314#endif
315
316/* where the cards start */
317#define CARD_START CARD_HEIGHT +4
318
319#if (LCD_WIDTH >= 220) && (LCD_HEIGHT >= 176)
320#define KNOWN_CARD 23
321#define NOT_KNOWN_CARD 30
322#else
323#define KNOWN_CARD 13
324#define NOT_KNOWN_CARD 20
325#endif 306#endif
326 307
327/* background color */ 308typedef struct
328#define background_color LCD_RGBPACK(0,157,0) 309{
329
330typedef struct card {
331 unsigned char suit : 2; 310 unsigned char suit : 2;
332 unsigned char num : 4; 311 unsigned char num : 4;
333 unsigned char known : 1; 312 unsigned char known : 1;
334 unsigned char used : 1;/* this is what is used when dealing cards */ 313 unsigned char used : 1;/* this is what is used when dealing cards */
335 unsigned char next; 314 unsigned char next;
336} card; 315} card_t;
337 316
338unsigned char next_random_card(card *deck){
339 unsigned char i,r;
340 317
341 r = rb->rand()%(SUITS * CARDS_PER_SUIT)+1; 318/**
342 i = 0; 319 * LCD card drawing routines
320 */
321
322static void draw_cursor( int x, int y )
323{
324 rb->lcd_set_drawmode( DRMODE_COMPLEMENT );
325 rb->lcd_fillrect( x+1, y+1, CARD_WIDTH-1, CARD_HEIGHT-1 );
326 rb->lcd_set_drawmode( DRMODE_SOLID );
327}
343 328
344 while(r>0){ 329/* Draw a card's border, select it if it's selected and draw the cursor
345 i = (i + 1)%(SUITS * CARDS_PER_SUIT); 330 * is the cursor is currently over the card */
346 if(!deck[i].used) r--; 331static void draw_card_ext( int x, int y, bool selected, bool cursor )
332{
333#if LCD_DEPTH > 1
334 rb->lcd_set_foreground( LCD_BLACK );
335#endif
336 /* draw a rectangle omiting the corner pixels, which is why we don't
337 * use drawrect */
338 rb->lcd_drawline( x+1, y, x+CARD_WIDTH-1, y );
339 rb->lcd_drawline( x+1, y+CARD_HEIGHT, x+CARD_WIDTH-1, y+CARD_HEIGHT );
340 rb->lcd_drawline( x, y+1, x, y+CARD_HEIGHT-1 );
341 rb->lcd_drawline( x+CARD_WIDTH, y+1, x+CARD_WIDTH, y+CARD_HEIGHT-1 );
342
343 if( selected )
344 {
345 rb->lcd_drawrect( x+1, y+1, CARD_WIDTH-1, CARD_HEIGHT-1 );
347 } 346 }
347 if( cursor )
348 {
349 draw_cursor( x, y );
350 }
351}
348 352
349 deck[i].used = 1; 353/* Draw a card's inner graphics */
354static void draw_card( card_t card, int x, int y,
355 bool selected, bool cursor, bool leftstyle )
356{
357#ifndef HAVE_LCD_COLOR
358 /* On Black&White or Greyscale LCDs we don't have a card back.
359 * We thus need to clear the card area even if the card isn't
360 * known. */
361#if LCD_DEPTH > 1
362 rb->lcd_set_foreground( LCD_WHITE );
363#else
364 rb->lcd_set_drawmode( DRMODE_SOLID|DRMODE_INVERSEVID );
365#endif
366 rb->lcd_fillrect( x+1, y+1, CARD_WIDTH-1, CARD_HEIGHT-1 );
367#if LCD_DEPTH == 1
368 rb->lcd_set_drawmode( DRMODE_SOLID );
369#endif
370#endif
371 if( card.known )
372 {
373#ifdef HAVE_LCD_COLOR
374 /* On Color LCDs we have a card back so we only need to clear
375 * the card area when it's known*/
376 rb->lcd_set_foreground( LCD_WHITE );
377 rb->lcd_fillrect( x+1, y+1, CARD_WIDTH-1, CARD_HEIGHT-1 );
378#endif
379 draw_number( card.num, x+1, y+1 );
380 if( leftstyle )
381 {
382 draw_suit( card.suit, x+1, y+2+NUMBER_HEIGHT );
383 }
384 else
385 {
386 draw_suit( card.suit, x+2+NUMBER_WIDTH, y+1 );
387 }
388 }
389#ifdef HAVE_LCD_COLOR
390 else
391 {
392 rb->lcd_bitmap( solitaire_cardback, x+1, y+1,
393 CARDBACK_WIDTH, CARDBACK_HEIGHT );
394 }
395#endif
350 396
351 return i; 397 draw_card_ext( x, y, selected, cursor );
398}
399
400/* Draw an empty stack */
401static void draw_empty_stack( int s, int x, int y, bool cursor )
402{
403#if LCD_DEPTH > 1
404 rb->lcd_set_foreground( LCD_WHITE );
405#else
406 rb->lcd_set_drawmode( DRMODE_SOLID|DRMODE_INVERSEVID );
407#endif
408 rb->lcd_fillrect( x+1, y+1, CARD_WIDTH-1, CARD_HEIGHT-1 );
409#if LCD_DEPTH == 1
410 rb->lcd_set_drawmode( DRMODE_SOLID );
411#endif
412 draw_suiti( s, x+(CARD_WIDTH-SUITI_WIDTH)/2,
413 y+(CARD_HEIGHT-SUITI_HEIGHT)/2 );
414
415 draw_card_ext( x, y, false, cursor );
352} 416}
353 417
354#define HELP_QUIT 0 418/**
355#define HELP_USB 1 419 * Help
420 *
421 * TODO: the help menu should just list the key definitions. Asking the
422 * user to try all possible keys/key combos is just counter
423 * productive.
424 */
425
426enum help { HELP_QUIT, HELP_USB };
356 427
357/* help for the not so intuitive interface */ 428/* help for the not so intuitive interface */
358int solitaire_help(void){ 429enum help solitaire_help( void )
430{
359 431
360 int button; 432 int button;
361 int lastbutton = BUTTON_NONE; 433 int lastbutton = BUTTON_NONE;
362 434
363 while(1){ 435 while( true )
364 436 {
365 rb->lcd_clear_display(); 437 rb->lcd_clear_display();
366 438
367#if CONFIG_KEYPAD == RECORDER_PAD 439#if CONFIG_KEYPAD == RECORDER_PAD
@@ -388,82 +460,85 @@ int solitaire_help(void){
388 rb->lcd_putsxy(20, 48, "All actions can be"); 460 rb->lcd_putsxy(20, 48, "All actions can be");
389 rb->lcd_putsxy(20, 56, "done using the"); 461 rb->lcd_putsxy(20, 56, "done using the");
390 rb->lcd_putsxy(20, 64, "joystick and RECORD."); 462 rb->lcd_putsxy(20, 64, "joystick and RECORD.");
463#else
464//# warning "Add help strings for other keypads"
391#endif 465#endif
392 466
393 rb->lcd_update(); 467 rb->lcd_update();
394 468
395 button = rb->button_get(true); 469 button = rb->button_get( true );
396 switch(button){ 470 switch( button )
471 {
397 case SOL_UP: 472 case SOL_UP:
398#ifdef SOL_UP_PRE 473#ifdef SOL_UP_PRE
399 if(lastbutton != SOL_UP_PRE) 474 if( lastbutton != SOL_UP_PRE )
400 break; 475 break;
401#endif 476#endif
402 rb->splash(HZ*2, true, HELP_SOL_UP); 477 rb->splash( HZ*2, true, HELP_SOL_UP );
403 break; 478 break;
404 479
405 case SOL_DOWN: 480 case SOL_DOWN:
406#ifdef SOL_DOWN_PRE 481#ifdef SOL_DOWN_PRE
407 if(lastbutton != SOL_DOWN_PRE) 482 if( lastbutton != SOL_DOWN_PRE )
408 break; 483 break;
409#endif 484#endif
410 rb->splash(HZ*2, true, HELP_SOL_DOWN); 485 rb->splash( HZ*2, true, HELP_SOL_DOWN );
411 break; 486 break;
412 487
413 case SOL_LEFT: 488 case SOL_LEFT:
414#ifdef SOL_LEFT_PRE 489#ifdef SOL_LEFT_PRE
415 if(lastbutton != SOL_LEFT_PRE) 490 if( lastbutton != SOL_LEFT_PRE )
416 break; 491 break;
417#endif 492#endif
418 rb->splash(HZ*2, true, HELP_SOL_LEFT); 493 rb->splash( HZ*2, true, HELP_SOL_LEFT );
419 break; 494 break;
420 495
421 case SOL_RIGHT: 496 case SOL_RIGHT:
422#ifdef SOL_RIGHT_PRE 497#ifdef SOL_RIGHT_PRE
423 if(lastbutton != SOL_RIGHT_PRE) 498 if( lastbutton != SOL_RIGHT_PRE )
424 break; 499 break;
425#endif 500#endif
426 rb->splash(HZ*2, true, HELP_SOL_RIGHT); 501 rb->splash( HZ*2, true, HELP_SOL_RIGHT );
427 break; 502 break;
428 503
429 case SOL_MOVE: 504 case SOL_MOVE:
430#ifdef SOL_MOVE_PRE 505#ifdef SOL_MOVE_PRE
431 if(lastbutton != SOL_MOVE_PRE) 506 if( lastbutton != SOL_MOVE_PRE )
432 break; 507 break;
433#endif 508#endif
434 rb->splash(HZ*2, true, HELP_SOL_MOVE); 509 rb->splash( HZ*2, true, HELP_SOL_MOVE );
435 break; 510 break;
436 511
437 case SOL_DRAW: 512 case SOL_DRAW:
438#ifdef SOL_DRAW_PRE 513#ifdef SOL_DRAW_PRE
439 if(lastbutton != SOL_DRAW_PRE) 514 if( lastbutton != SOL_DRAW_PRE )
440 break; 515 break;
441#endif 516#endif
442 rb->splash(HZ*2, true, HELP_SOL_DRAW); 517 rb->splash( HZ*2, true, HELP_SOL_DRAW );
443 break; 518 break;
444 519
445 case SOL_CUR2STACK: 520 case SOL_CUR2STACK:
446#ifdef SOL_CUR2STACK_PRE 521#ifdef SOL_CUR2STACK_PRE
447 if(lastbutton != SOL_CUR2STACK_PRE) 522 if( lastbutton != SOL_CUR2STACK_PRE )
448 break; 523 break;
449#endif 524#endif
450 rb->splash(HZ*2, true, HELP_SOL_CUR2STACK); 525 rb->splash( HZ*2, true, HELP_SOL_CUR2STACK );
451 break; 526 break;
452 527
453 case SOL_REM2STACK: 528 case SOL_REM2STACK:
454#ifdef SOL_REM2STACK_PRE 529#ifdef SOL_REM2STACK_PRE
455 if(lastbutton != SOL_REM2STACK_PRE) 530 if( lastbutton != SOL_REM2STACK_PRE )
456 break; 531 break;
457#endif 532#endif
458 rb->splash(HZ*2, true, HELP_SOL_REM2STACK); 533 rb->splash( HZ*2, true, HELP_SOL_REM2STACK );
459 break; 534 break;
460 535
461 case SOL_REM2CUR: 536 case SOL_REM2CUR:
462#ifdef SOL_REM2CUR_PRE 537#ifdef SOL_REM2CUR_PRE
463 if(lastbutton != SOL_REM2CUR_PRE) 538 if( lastbutton != SOL_REM2CUR_PRE )
464 break; 539 break;
465#endif 540#endif
466 rb->splash(HZ*2, true, HELP_SOL_REM2CUR); 541 rb->splash( HZ*2, true, HELP_SOL_REM2CUR );
467 break; 542 break;
468#ifdef SOL_RC_QUIT 543#ifdef SOL_RC_QUIT
469 case SOL_RC_QUIT: 544 case SOL_RC_QUIT:
@@ -472,48 +547,40 @@ int solitaire_help(void){
472 return HELP_QUIT; 547 return HELP_QUIT;
473 548
474 default: 549 default:
475 if(rb->default_event_handler(button) == SYS_USB_CONNECTED) 550 if( rb->default_event_handler( button ) == SYS_USB_CONNECTED )
476 return HELP_USB; 551 return HELP_USB;
477 break; 552 break;
478 } 553 }
479 if(button != BUTTON_NONE) 554 if( button != BUTTON_NONE )
480 lastbutton = button; 555 lastbutton = button;
481 } 556 }
482} 557}
558
559/**
560 * Custom menu / options
561 *
562 * TODO: use rockbox api menus instead
563 */
564
483#define CFGFILE_VERSION 0 565#define CFGFILE_VERSION 0
484int draw_type; 566int draw_type;
485 567
486
487unsigned char change_draw(unsigned char draw){
488 if (draw == 0)
489 return 1;
490 else
491 return 0;
492}
493static struct configdata config[] = { 568static struct configdata config[] = {
494 { TYPE_INT, 0, 1, &draw_type, "draw_type", NULL, NULL } 569 { TYPE_INT, 0, 1, &draw_type, "draw_type", NULL, NULL }
495}; 570};
496 571
497/* menu return codes */ 572/* menu return codes */
498#define MENU_RESUME 0 573enum { MENU_RESUME, MENU_RESTART, MENU_OPT,
499#define MENU_RESTART 1 574 MENU_HELP, MENU_QUIT, MENU_USB };
500#define MENU_HELP 3 575#define MENU_LENGTH MENU_USB
501#define MENU_QUIT 4
502#define MENU_USB 5
503#define MENU_OPT 2
504
505/* menu item number */
506#define MENU_LENGTH 5
507 576
508/* different menu behaviors */ 577/* different menu behaviors */
578enum { MENU_BEFOREGAME, MENU_BEFOREGAMEOP, MENU_DURINGGAME };
509 579
510#define MENU_BEFOREGAME 0 580/**
511#define MENU_BEFOREGAMEOP 1 581 * The menu
512#define MENU_DURINGGAME 2 582 * text displayed changes depending on the context */
513unsigned char when; 583int solitaire_menu( unsigned char context )
514/* the menu */
515/* text displayed changes depending on the 'when' parameter */
516int solitaire_menu(unsigned char when_n)
517{ 584{
518 static char menu[3][MENU_LENGTH][17] = 585 static char menu[3][MENU_LENGTH][17] =
519 { { "Start Game", 586 { { "Start Game",
@@ -535,34 +602,42 @@ int solitaire_menu(unsigned char when_n)
535 602
536 603
537 int i; 604 int i;
538 int cursor=0; 605 int cursor = 0;
539 int button; 606 int button;
607
540 int fh; 608 int fh;
541 when=when_n; 609 rb->lcd_getstringsize( menu[0][0], NULL, &fh );
542 rb->lcd_getstringsize("A", NULL, &fh);
543 fh++; 610 fh++;
544 611
545 if(when != MENU_BEFOREGAMEOP && when!=MENU_BEFOREGAME && when!=MENU_DURINGGAME) 612 if( context != MENU_BEFOREGAMEOP
546 when = MENU_DURINGGAME; 613 && context != MENU_BEFOREGAME
614 && context != MENU_DURINGGAME )
615 {
616 context = MENU_DURINGGAME;
617 }
547 618
548 while(1){ 619 while( true )
620 {
549 621
550 rb->lcd_clear_display(); 622 rb->lcd_clear_display();
551 rb->lcd_putsxy(20, 1, "Solitaire"); 623 rb->lcd_putsxy( 20, 1, "Solitaire" );
552 624
553 for(i = 0; i<MENU_LENGTH; i++){ 625 for( i = 0; i<MENU_LENGTH; i++ )
554 rb->lcd_putsxy(1, 17+fh*i, menu[when][i]); 626 {
555 if(cursor == i) { 627 rb->lcd_putsxy( 1, 17+fh*i, menu[context][i] );
556 rb->lcd_set_drawmode(DRMODE_COMPLEMENT); 628 if( cursor == i )
557 rb->lcd_fillrect(0,17+fh*i, LCD_WIDTH, fh); 629 {
558 rb->lcd_set_drawmode(DRMODE_SOLID); 630 rb->lcd_set_drawmode( DRMODE_COMPLEMENT );
631 rb->lcd_fillrect( 0, 17+fh*i, LCD_WIDTH, fh );
632 rb->lcd_set_drawmode( DRMODE_SOLID );
559 } 633 }
560 } 634 }
561 635
562 rb->lcd_update(); 636 rb->lcd_update();
563 637
564 button = rb->button_get(true); 638 button = rb->button_get( true );
565 switch(button){ 639 switch( button )
640 {
566 case SOL_UP: 641 case SOL_UP:
567 cursor = (cursor + MENU_LENGTH - 1)%MENU_LENGTH; 642 cursor = (cursor + MENU_LENGTH - 1)%MENU_LENGTH;
568 break; 643 break;
@@ -578,7 +653,8 @@ int solitaire_menu(unsigned char when_n)
578#ifdef SOL_MENU_RUN2 653#ifdef SOL_MENU_RUN2
579 case SOL_MENU_RUN2: 654 case SOL_MENU_RUN2:
580#endif 655#endif
581 switch(cursor){ 656 switch( cursor )
657 {
582 case MENU_RESUME: 658 case MENU_RESUME:
583 case MENU_RESTART: 659 case MENU_RESTART:
584 case MENU_OPT: 660 case MENU_OPT:
@@ -586,20 +662,12 @@ int solitaire_menu(unsigned char when_n)
586 return cursor; 662 return cursor;
587 663
588 case MENU_HELP: 664 case MENU_HELP:
589 if(solitaire_help() == HELP_USB) 665 if( solitaire_help() == HELP_USB )
590 return MENU_USB; 666 return MENU_USB;
591 break; 667 break;
592 } 668 }
593 break; 669 break;
594 670
595 case SOL_MENU_INFO:
596#if defined(SOL_MENU_INFO2) && defined(SOL_MENU_INFO3)
597 case SOL_MENU_INFO2:
598 case SOL_MENU_INFO3:
599#endif
600 rb->splash(HZ, true, "Solitaire for Rockbox by dionoea");
601 break;
602
603#ifdef SOL_OPT 671#ifdef SOL_OPT
604 case SOL_OPT: 672 case SOL_OPT:
605 return MENU_OPT; 673 return MENU_OPT;
@@ -612,13 +680,17 @@ int solitaire_menu(unsigned char when_n)
612 return MENU_QUIT; 680 return MENU_QUIT;
613 681
614 default: 682 default:
615 if(rb->default_event_handler(button) == SYS_USB_CONNECTED) 683 if( rb->default_event_handler( button ) == SYS_USB_CONNECTED )
616 return MENU_USB; 684 return MENU_USB;
617 break; 685 break;
618 } 686 }
619 } 687 }
620} 688}
621 689
690/**
691 * Global variables
692 */
693
622/* player's cursor */ 694/* player's cursor */
623unsigned char cur_card; 695unsigned char cur_card;
624/* player's cursor column num */ 696/* player's cursor column num */
@@ -628,7 +700,7 @@ unsigned char cur_col;
628unsigned char sel_card; 700unsigned char sel_card;
629 701
630/* the deck */ 702/* the deck */
631card deck[SUITS * CARDS_PER_SUIT]; 703card_t deck[ NUM_CARDS ];
632 704
633/* the remaining cards */ 705/* the remaining cards */
634unsigned char rem; 706unsigned char rem;
@@ -638,51 +710,84 @@ unsigned char coun_rem;
638/* the 7 game columns */ 710/* the 7 game columns */
639unsigned char cols[COL_NUM]; 711unsigned char cols[COL_NUM];
640 712
641int CARDS_PER_DRAW; 713int cards_per_draw;
642/* the 4 final stacks */ 714/* the 4 final stacks */
643unsigned char stacks[SUITS]; 715unsigned char stacks[SUITS];
644 716
717/**
718 * Card handling routines
719 */
720
721unsigned char next_random_card( card_t *deck )
722{
723 unsigned char i,r;
724
725 r = rb->rand()%(NUM_CARDS)+1;
726 i = 0;
727
728 while( r>0 )
729 {
730 i = (i + 1)%(NUM_CARDS);
731 if( !deck[i].used ) r--;
732 }
733
734 deck[i].used = 1;
735
736 return i;
737}
738
739
645/* initialize the game */ 740/* initialize the game */
646void solitaire_init(void){ 741void solitaire_init( void )
742{
647 743
648 unsigned char c; 744 unsigned char c;
649 int i,j; 745 int i, j;
650#if LCD_DEPTH>1 746
651 rb->lcd_set_foreground(LCD_BLACK); 747 /* number of cards that are drawn on the remains' stack (by pressing F2) */
652#ifdef HAVE_LCD_COLOR 748 if( draw_type == 0 )
653 rb->lcd_set_background(background_color); 749 {
654#endif 750 cards_per_draw = 3;
655#endif
656/* number of cards that are drawn on the remains' stack (by pressing F2) */
657 if(draw_type == 0) {
658 CARDS_PER_DRAW =3;
659 } else {
660 CARDS_PER_DRAW=1;
661 } 751 }
752 else
753 {
754 cards_per_draw = 1;
755 }
756
662 /* init deck */ 757 /* init deck */
663 for(i=0;i<SUITS;i++){ 758 for( i=0; i<SUITS; i++ )
664 for(j=0;j<CARDS_PER_SUIT;j++){ 759 {
665 deck[i*CARDS_PER_SUIT+j].suit = i; 760 for( j=0; j<CARDS_PER_SUIT; j++ )
666 deck[i*CARDS_PER_SUIT+j].num = j; 761 {
667 deck[i*CARDS_PER_SUIT+j].known = 1; 762#define card deck[i*CARDS_PER_SUIT+j]
668 deck[i*CARDS_PER_SUIT+j].used = 0; 763 card.suit = i;
669 deck[i*CARDS_PER_SUIT+j].next = NOT_A_CARD; 764 card.num = j;
765 card.known = 1;
766 card.used = 0;
767 card.next = NOT_A_CARD;
768#undef card
670 } 769 }
671 } 770 }
672 771
673 /* deal the cards ... */ 772 /* deal the cards ... */
674 /* ... in the columns */ 773 /* ... in the columns */
675 for(i=0; i<COL_NUM; i++){ 774 for( i=0; i<COL_NUM; i++ )
775 {
676 c = NOT_A_CARD; 776 c = NOT_A_CARD;
677 for(j=0; j<=i; j++){ 777 for( j=0; j<=i; j++ )
678 if(c == NOT_A_CARD){ 778 {
679 cols[i] = next_random_card(deck); 779 if( c == NOT_A_CARD )
780 {
781 cols[i] = next_random_card( deck );
680 c = cols[i]; 782 c = cols[i];
681 } else { 783 }
682 deck[c].next = next_random_card(deck); 784 else
785 {
786 deck[c].next = next_random_card( deck );
683 c = deck[c].next; 787 c = deck[c].next;
684 } 788 }
685 if(j<i) deck[c].known = 0; 789 if( j < i )
790 deck[c].known = 0;
686 } 791 }
687 } 792 }
688 793
@@ -690,15 +795,17 @@ void solitaire_init(void){
690 rem = next_random_card(deck); 795 rem = next_random_card(deck);
691 c = rem; 796 c = rem;
692 797
693 for(i=1; i<SUITS * CARDS_PER_SUIT - COL_NUM * (COL_NUM + 1)/2; i++){ 798 for( i=1; i < NUM_CARDS - COL_NUM * (COL_NUM + 1)/2; i++ )
694 deck[c].next = next_random_card(deck); 799 {
800 deck[c].next = next_random_card( deck );
695 c = deck[c].next; 801 c = deck[c].next;
696 } 802 }
697 803
698 /* we now finished dealing the cards. The game can start ! (at last) */ 804 /* we now finished dealing the cards. The game can start ! (at last) */
699 805
700 /* init the stack */ 806 /* init the stack */
701 for(i = 0; i<SUITS; i++){ 807 for( i = 0; i<SUITS; i++ )
808 {
702 stacks[i] = NOT_A_CARD; 809 stacks[i] = NOT_A_CARD;
703 } 810 }
704 811
@@ -716,24 +823,29 @@ void solitaire_init(void){
716} 823}
717 824
718/* find the column number in which 'card' can be found */ 825/* find the column number in which 'card' can be found */
719unsigned char find_card_col(unsigned char card){ 826unsigned char find_card_col( unsigned char card )
827{
720 int i; 828 int i;
721 unsigned char c; 829 unsigned char c;
722 830
723 if(card == NOT_A_CARD) return NOT_A_COL; 831 if( card == NOT_A_CARD ) return NOT_A_COL;
724 832
725 for(i=0; i<COL_NUM; i++){ 833 for( i=0; i<COL_NUM; i++ )
834 {
726 c = cols[i]; 835 c = cols[i];
727 while(c!=NOT_A_CARD){ 836 while( c != NOT_A_CARD )
728 if(c == card) return i; 837 {
838 if( c == card ) return i;
729 c = deck[c].next; 839 c = deck[c].next;
730 } 840 }
731 } 841 }
732 842
733 for(i=0; i<SUITS; i++){ 843 for( i=0; i<SUITS; i++ )
844 {
734 c = stacks[i]; 845 c = stacks[i];
735 while(c!=NOT_A_CARD){ 846 while( c != NOT_A_CARD )
736 if(c == card) return STACKS_COL + i; 847 {
848 if( c == card ) return STACKS_COL + i;
737 c = deck[c].next; 849 c = deck[c].next;
738 } 850 }
739 } 851 }
@@ -743,41 +855,49 @@ unsigned char find_card_col(unsigned char card){
743 855
744/* find the card preceding 'card' */ 856/* find the card preceding 'card' */
745/* if it doesn't exist, return NOT_A_CARD */ 857/* if it doesn't exist, return NOT_A_CARD */
746unsigned char find_prev_card(unsigned char card){ 858unsigned char find_prev_card( unsigned char card ){
747 int i; 859 int i;
748 860
749 for(i=0; i<SUITS*CARDS_PER_SUIT; i++){ 861 for( i=0; i < NUM_CARDS; i++ )
750 if(deck[i].next == card) return i; 862 {
863 if( deck[i].next == card ) return i;
751 } 864 }
752 865
753 return NOT_A_CARD; 866 return NOT_A_CARD;
754} 867}
755 868
756/* find the last card of a given column */ 869/* find the last card of a given column */
757unsigned char find_last_card(unsigned char col){ 870unsigned char find_last_card( unsigned char col )
871{
758 unsigned char c; 872 unsigned char c;
759 873
760 if(col < COL_NUM){ 874 if( col < COL_NUM )
875 {
761 c = cols[col]; 876 c = cols[col];
762 } else if(col < REM_COL){ 877 }
878 else if( col < REM_COL )
879 {
763 c = stacks[col - STACKS_COL]; 880 c = stacks[col - STACKS_COL];
764 } else { 881 }
882 else
883 {
765 c = rem; 884 c = rem;
766 } 885 }
767 886
768 if(c == NOT_A_CARD) 887 if(c == NOT_A_CARD)
769 return c; 888 return c;
770 else { 889 else
771 while(deck[c].next != NOT_A_CARD){ 890 {
891 while(deck[c].next != NOT_A_CARD)
772 c = deck[c].next; 892 c = deck[c].next;
773 }
774 return c; 893 return c;
775 } 894 }
776} 895}
777 896
778#define MOVE_OK 0 897enum move { MOVE_OK, MOVE_NOT_OK };
779#define MOVE_NOT_OK 1 898
780unsigned char move_card(unsigned char dest_col, unsigned char src_card){ 899enum move move_card( unsigned char dest_col, unsigned char src_card )
900{
781 /* the column on which to take src_card */ 901 /* the column on which to take src_card */
782 unsigned char src_col; 902 unsigned char src_col;
783 903
@@ -788,82 +908,95 @@ unsigned char move_card(unsigned char dest_col, unsigned char src_card){
788 unsigned char src_card_prev; 908 unsigned char src_card_prev;
789 909
790 /* you can't move no card (at least, it doesn't have any consequence) */ 910 /* you can't move no card (at least, it doesn't have any consequence) */
791 if(src_card == NOT_A_CARD) return MOVE_NOT_OK; 911 if( src_card == NOT_A_CARD ) return MOVE_NOT_OK;
792 /* you can't put a card back on the remains' stack */ 912 /* you can't put a card back on the remains' stack */
793 if(dest_col == REM_COL) return MOVE_NOT_OK; 913 if( dest_col == REM_COL ) return MOVE_NOT_OK;
794 914
795 src_col = find_card_col(src_card); 915 src_col = find_card_col( src_card );
796 dest_card = find_last_card(dest_col); 916 dest_card = find_last_card( dest_col );
797 src_card_prev = find_prev_card(src_card); 917 src_card_prev = find_prev_card( src_card );
798 918
799 /* you can't move more than one card at a time from the final stack */ 919 /* you can't move more than one card at a time from the final stack */
800 /* to the rest of the game */ 920 /* to the rest of the game */
801 if(src_col >= COL_NUM && src_col < REM_COL 921 if( src_col >= COL_NUM && src_col < REM_COL
802 && deck[src_card].next != NOT_A_CARD){ 922 && deck[src_card].next != NOT_A_CARD )
923 {
803 return MOVE_NOT_OK; 924 return MOVE_NOT_OK;
804 } 925 }
805 926
806 /* if we (that means dest) are on one of the 7 columns ... */ 927 /* if we (that means dest) are on one of the 7 columns ... */
807 if(dest_col < COL_NUM){ 928 if( dest_col < COL_NUM )
929 {
808 /* ... check is we are on an empty color and that the src is a king */ 930 /* ... check is we are on an empty color and that the src is a king */
809 if(dest_card == NOT_A_CARD 931 if( dest_card == NOT_A_CARD
810 && deck[src_card].num == CARDS_PER_SUIT - 1){ 932 && deck[src_card].num == CARDS_PER_SUIT - 1 )
933 {
811 /* this is a winning combination */ 934 /* this is a winning combination */
812 cols[dest_col] = src_card; 935 cols[dest_col] = src_card;
813 } 936 }
814 /* ... or check if the cards follow one another and have same suit */ 937 /* ... or check if the cards follow one another and have same suit */
815 else if((deck[dest_card].suit + deck[src_card].suit)%2==1 938 else if(( deck[dest_card].suit + deck[src_card].suit)%2==1
816 && deck[dest_card].num == deck[src_card].num + 1){ 939 && deck[dest_card].num == deck[src_card].num + 1 )
940 {
817 /* this is a winning combination */ 941 /* this is a winning combination */
818 deck[dest_card].next = src_card; 942 deck[dest_card].next = src_card;
819 } 943 }
820 /* ... or, humpf, well that's not good news */ 944 /* ... or, humpf, well that's not good news */
821 else { 945 else
946 {
822 /* this is not a winning combination */ 947 /* this is not a winning combination */
823 return MOVE_NOT_OK; 948 return MOVE_NOT_OK;
824 } 949 }
825 } 950 }
826 /* if we are on one of the 4 final stacks ... */ 951 /* if we are on one of the 4 final stacks ... */
827 else if(dest_col < REM_COL){ 952 else if( dest_col < REM_COL )
953 {
828 /* ... check if we are on an empty stack, that the src is an 954 /* ... check if we are on an empty stack, that the src is an
829 * ace and that this is the good final stack */ 955 * ace and that this is the good final stack */
830 if(dest_card == NOT_A_CARD 956 if( dest_card == NOT_A_CARD
831 && deck[src_card].num == 0 957 && deck[src_card].num == 0
832 && deck[src_card].suit == dest_col - STACKS_COL){ 958 && deck[src_card].suit == dest_col - STACKS_COL )
959 {
833 /* this is a winning combination */ 960 /* this is a winning combination */
834 stacks[dest_col - STACKS_COL] = src_card; 961 stacks[dest_col - STACKS_COL] = src_card;
835 } 962 }
836 /* ... or check if the cards follow one another, have the same 963 /* ... or check if the cards follow one another, have the same
837 * suit and {that src has no .next element or is from the remains' 964 * suit and {that src has no .next element or is from the remains'
838 * stack} */ 965 * stack} */
839 else if(deck[dest_card].suit == deck[src_card].suit 966 else if( deck[dest_card].suit == deck[src_card].suit
840 && deck[dest_card].num + 1 == deck[src_card].num 967 && deck[dest_card].num + 1 == deck[src_card].num
841 && (deck[src_card].next == NOT_A_CARD || src_col == REM_COL) ){ 968 && (deck[src_card].next == NOT_A_CARD || src_col == REM_COL) )
969 {
842 /* this is a winning combination */ 970 /* this is a winning combination */
843 deck[dest_card].next = src_card; 971 deck[dest_card].next = src_card;
844 } 972 }
845 /* ... or, well that's not good news */ 973 /* ... or, well that's not good news */
846 else { 974 else
975 {
847 /* this is not a winnong combination */ 976 /* this is not a winnong combination */
848 return MOVE_NOT_OK; 977 return MOVE_NOT_OK;
849 } 978 }
850 } 979 }
851 /* if we are on the remains' stack */ 980 /* if we are on the remains' stack */
852 else { 981 else
982 {
853 /* you can't move a card back to the remains' stack */ 983 /* you can't move a card back to the remains' stack */
854 return MOVE_NOT_OK; 984 return MOVE_NOT_OK;
855 } 985 }
856 986
857 /* if the src card is from the remains' stack, we don't want to take 987 /* if the src card is from the remains' stack, we don't want to take
858 * the following cards */ 988 * the following cards */
859 if(src_col == REM_COL){ 989 if( src_col == REM_COL )
990 {
860 /* if src card is the first card from the stack */ 991 /* if src card is the first card from the stack */
861 if(src_card_prev == NOT_A_CARD){ 992 if( src_card_prev == NOT_A_CARD )
993 {
862 rem = deck[src_card].next; 994 rem = deck[src_card].next;
863 coun_rem = coun_rem-1; 995 coun_rem = coun_rem-1;
864 } 996 }
865 /* if src card is not the first card from the stack */ 997 /* if src card is not the first card from the stack */
866 else { 998 else
999 {
867 deck[src_card_prev].next = deck[src_card].next; 1000 deck[src_card_prev].next = deck[src_card].next;
868 } 1001 }
869 deck[src_card].next = NOT_A_CARD; 1002 deck[src_card].next = NOT_A_CARD;
@@ -871,14 +1004,21 @@ unsigned char move_card(unsigned char dest_col, unsigned char src_card){
871 coun_rem = coun_rem-1; 1004 coun_rem = coun_rem-1;
872 } 1005 }
873 /* if the src card is from somewhere else, just take everything */ 1006 /* if the src card is from somewhere else, just take everything */
874 else { 1007 else
875 if(src_card_prev == NOT_A_CARD){ 1008 {
876 if(src_col < COL_NUM){ 1009 if( src_card_prev == NOT_A_CARD )
1010 {
1011 if( src_col < COL_NUM )
1012 {
877 cols[src_col] = NOT_A_CARD; 1013 cols[src_col] = NOT_A_CARD;
878 } else { 1014 }
1015 else
1016 {
879 stacks[src_col - STACKS_COL] = NOT_A_CARD; 1017 stacks[src_col - STACKS_COL] = NOT_A_CARD;
880 } 1018 }
881 } else { 1019 }
1020 else
1021 {
882 deck[src_card_prev].next = NOT_A_CARD; 1022 deck[src_card_prev].next = NOT_A_CARD;
883 } 1023 }
884 } 1024 }
@@ -887,11 +1027,11 @@ unsigned char move_card(unsigned char dest_col, unsigned char src_card){
887 return MOVE_OK; 1027 return MOVE_OK;
888} 1028}
889 1029
1030/**
1031 * The main game loop
1032 */
890 1033
891 1034enum { SOLITAIRE_WIN, SOLITAIRE_QUIT, SOLITAIRE_USB };
892#define SOLITAIRE_WIN 0
893#define SOLITAIRE_QUIT 1
894#define SOLITAIRE_USB 2
895 1035
896#if ( LCD_WIDTH > ( CARD_WIDTH * 8 ) ) 1036#if ( LCD_WIDTH > ( CARD_WIDTH * 8 ) )
897# define BIG_SCREEN 1 1037# define BIG_SCREEN 1
@@ -900,416 +1040,254 @@ unsigned char move_card(unsigned char dest_col, unsigned char src_card){
900#endif 1040#endif
901#define LCD_WIDTH2 (LCD_WIDTH - BIG_SCREEN) 1041#define LCD_WIDTH2 (LCD_WIDTH - BIG_SCREEN)
902 1042
903/* the game */ 1043int solitaire( void )
904int solitaire(void){ 1044{
905 1045
906 int i,j,x; 1046 int i,j;
907 int button, lastbutton = 0; 1047 int button, lastbutton = 0;
908 unsigned char c,h,prevcard; 1048 unsigned char c,h,prevcard;
909 int biggest_col_length; 1049 int biggest_col_length;
910 1050
911 configfile_init(rb); 1051 configfile_init(rb);
912 configfile_load(FILENAME, config, 1, 0); 1052 configfile_load(CONFIG_FILENAME, config, 1, 0);
913 1053
914 rb->srand( *rb->current_tick ); 1054 rb->srand( *rb->current_tick );
915 switch(solitaire_menu(draw_type==0?MENU_BEFOREGAME:MENU_BEFOREGAMEOP)) { 1055 switch( solitaire_menu( draw_type == 0 ? MENU_BEFOREGAME
916 case MENU_QUIT: 1056 : MENU_BEFOREGAMEOP ) )
1057 {
1058 case MENU_QUIT:
917 return SOLITAIRE_QUIT; 1059 return SOLITAIRE_QUIT;
918 1060
919 case MENU_USB: 1061 case MENU_USB:
920 return SOLITAIRE_USB; 1062 return SOLITAIRE_USB;
921 case MENU_OPT: 1063
922 draw_type=change_draw(draw_type); 1064 case MENU_OPT:
923 configfile_save(FILENAME, config, 1, 0); 1065 draw_type = (draw_type+1)%2;
924 when=draw_type==0?MENU_BEFOREGAME:MENU_BEFOREGAMEOP; 1066 configfile_save(CONFIG_FILENAME, config, 1, 0);
925 return 0; 1067 return 0;
926 } 1068 }
1069 solitaire_init();
1070
1071 while( true )
1072 {
1073
927#if LCD_DEPTH>1 1074#if LCD_DEPTH>1
928 rb->lcd_set_foreground(LCD_BLACK); 1075 rb->lcd_set_foreground(LCD_BLACK);
929#ifdef HAVE_LCD_COLOR 1076#ifdef HAVE_LCD_COLOR
930 rb->lcd_set_background(background_color); 1077 rb->lcd_set_background(BACKGROUND_COLOR);
931#else
932 rb->lcd_set_background(LCD_DEFAULT_BG);
933#endif 1078#endif
934#endif 1079#endif
935 solitaire_init();
936
937 while(true){
938
939 rb->lcd_clear_display(); 1080 rb->lcd_clear_display();
940 1081
1082#if LCD_DEPTH > 1
1083 rb->lcd_set_foreground(LCD_BLACK);
1084 rb->lcd_set_background(LCD_WHITE);
1085#endif
1086
941 /* get the biggest column length so that display can be "optimized" */ 1087 /* get the biggest column length so that display can be "optimized" */
942 biggest_col_length = 0; 1088 biggest_col_length = 0;
943 1089
944 for(i=0;i<COL_NUM;i++){ 1090 for(i=0;i<COL_NUM;i++)
1091 {
945 j = 0; 1092 j = 0;
946 c = cols[i]; 1093 c = cols[i];
947 while(c != NOT_A_CARD){ 1094 while( c != NOT_A_CARD )
1095 {
948 j++; 1096 j++;
949 c = deck[c].next; 1097 c = deck[c].next;
950 } 1098 }
951 if(j>biggest_col_length) biggest_col_length = j; 1099 if( j > biggest_col_length ) biggest_col_length = j;
952 } 1100 }
953 1101
954 /* check if there are cards remaining in the game. */ 1102 /* check if there are cards remaining in the game. */
955 /* if there aren't any, that means you won :) */ 1103 /* if there aren't any, that means you won :) */
956 if(biggest_col_length == 0 && rem == NOT_A_CARD){ 1104 if( biggest_col_length == 0 && rem == NOT_A_CARD )
957 rb->splash(HZ*2, true, "You Won :)"); 1105 {
1106 rb->splash( HZ*2, true, "You Won :)" );
958 return SOLITAIRE_WIN; 1107 return SOLITAIRE_WIN;
959 } 1108 }
960 1109
961 /* draw the columns */ 1110 /* draw the columns */
962 for(i=0;i<COL_NUM;i++){ 1111 for( i = 0; i < COL_NUM; i++ )
1112 {
963 c = cols[i]; 1113 c = cols[i];
964 j = CARD_START; 1114 j = CARD_START;
965 while(true){ 1115 while( true )
966 if(c==NOT_A_CARD) { 1116 {
1117 if( c == NOT_A_CARD )
1118 {
967 /* draw the cursor on empty columns */ 1119 /* draw the cursor on empty columns */
968 if(cur_col == i){ 1120 if( cur_col == i )
969 rb->lcd_set_drawmode(DRMODE_COMPLEMENT); 1121 {
970 rb->lcd_fillrect(1+i*(LCD_WIDTH-2)/COL_NUM+1, j+1, CARD_WIDTH-1, CARD_HEIGHT-1); 1122 draw_cursor( 1+i*(LCD_WIDTH - 2)/COL_NUM, j+1 );
971 } 1123 }
972 break; 1124 break;
973 } 1125 }
974 /* clear the card's spot */
975 1126
976 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); 1127 draw_card( deck[c], 1+i*(LCD_WIDTH - 2)/COL_NUM, j+1,
977 rb->lcd_fillrect(1+i*(LCD_WIDTH - 2)/COL_NUM, j+1, CARD_WIDTH, CARD_HEIGHT-1); 1128 c == sel_card, c == cur_card, false );
978 rb->lcd_set_drawmode(DRMODE_SOLID); 1129
979 /* known card */ 1130 h = c;
980 if(deck[c].known == 1){ 1131 c = deck[c].next;
981#if LCD_DEPTH>1 1132 if( c == NOT_A_CARD ) break;
982 #ifdef HAVE_LCD_COLOR 1133
983 rb->lcd_set_foreground(LCD_WHITE); 1134 /* This is where we change the spacing between cards so that
984 rb->lcd_set_background(LCD_WHITE); 1135 * they don't overflow out of the LCD */
985 #else 1136 if( h == cur_card )
986 rb->lcd_set_foreground(LCD_DEFAULT_BG); 1137 j += SUIT_HEIGHT+2;
987 rb->lcd_set_background(LCD_DEFAULT_BG); 1138 else
988 #endif 1139 j += min( SUIT_HEIGHT+2,
989#endif 1140 (LCD_HEIGHT - CARD_START - CARD_HEIGHT)/biggest_col_length );
990 rb->lcd_fillrect(1+i*(LCD_WIDTH - 2)/COL_NUM+1, j+1, CARD_WIDTH-1, CARD_HEIGHT-1);
991#if LCD_DEPTH>1
992 rb->lcd_set_foreground(colors[deck[c].suit]);
993#endif
994 rb->lcd_mono_bitmap(numbers[deck[c].num], 1+i*(LCD_WIDTH - 2)/COL_NUM+1, j+1, BMPWIDTH_c, BMPHEIGHT_c);
995 rb->lcd_mono_bitmap(suits[deck[c].suit], 1+i*(LCD_WIDTH - 2)/COL_NUM+ BMPWIDTH_c +2, j+1, BMPWIDTH_c, BMPHEIGHT_c);
996#if LCD_DEPTH>1
997 rb->lcd_set_foreground(LCD_BLACK);
998#ifdef HAVE_LCD_COLOR
999 rb->lcd_set_background(background_color);
1000#endif
1001#endif
1002 } else {
1003#ifdef HAVE_LCD_COLOR
1004 rb->lcd_bitmap(solitaire_cardback,
1005 1+i*(LCD_WIDTH - 2)/COL_NUM+1, j+1,
1006 BMPWIDTH_CARDBACK, BMPHEIGHT_CARDBACK);
1007#endif
1008 }
1009 /* draw top line of the card */
1010 rb->lcd_drawline(1+i*(LCD_WIDTH - 2)/COL_NUM+1,j,1+i*(LCD_WIDTH - 2)/COL_NUM+CARD_WIDTH-1,j);
1011 /* selected card */
1012 if(c == sel_card && sel_card != NOT_A_CARD){
1013 rb->lcd_drawrect(1+i*(LCD_WIDTH - 2)/COL_NUM+1, j+1, CARD_WIDTH-1, CARD_HEIGHT-1);
1014 }
1015 /* cursor (or not) */
1016 if(c == cur_card){
1017 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
1018 rb->lcd_fillrect(1+i*(LCD_WIDTH - 2)/COL_NUM+1, j+1, CARD_WIDTH-1, CARD_HEIGHT-1);
1019 rb->lcd_set_drawmode(DRMODE_SOLID);
1020 /* go to the next card */
1021 c = deck[c].next;
1022 if(c == NOT_A_CARD) break;
1023 else {
1024 if(deck[c].known == 0) {
1025 j += CARD_HEIGHT - NOT_KNOWN_CARD;
1026 } else {
1027 j += CARD_HEIGHT - KNOWN_CARD;
1028 }
1029 }
1030 } else {
1031 /* go to the next card */
1032 h = c;
1033 c = deck[c].next;
1034 if(c == NOT_A_CARD) break;
1035 if(c!=NOT_A_CARD) {
1036 if(deck[h].known == 0) {
1037 /*changeeee*/ j += CARD_HEIGHT - NOT_KNOWN_CARD;
1038 } else {
1039 j += min(CARD_HEIGHT - KNOWN_CARD, (LCD_HEIGHT - CARD_START - CARD_HEIGHT)/biggest_col_length);
1040 }
1041 }
1042 }
1043 }
1044 if(cols[i]!=NOT_A_CARD){
1045 /* draw line to the left of the column */
1046 rb->lcd_drawline(1+i*(LCD_WIDTH - 2)/COL_NUM,CARD_START,1+i*(LCD_WIDTH - 2)/COL_NUM,j+CARD_HEIGHT-1);
1047 /* draw line to the right of the column */
1048 rb->lcd_drawline(1+i*(LCD_WIDTH - 2)/COL_NUM+CARD_WIDTH,CARD_START,1+i*(LCD_WIDTH - 2)/COL_NUM+CARD_WIDTH,j+CARD_HEIGHT-1);
1049 /* draw bottom of the last card */
1050 rb->lcd_drawline(1+i*(LCD_WIDTH - 2)/COL_NUM+1,j+CARD_HEIGHT,1+i*(LCD_WIDTH - 2)/COL_NUM+CARD_WIDTH-1,j+CARD_HEIGHT);
1051 } 1141 }
1052 } 1142 }
1053#if LCD_DEPTH>1
1054 rb->lcd_set_foreground(LCD_BLACK);
1055#ifdef HAVE_LCD_COLOR
1056 rb->lcd_set_background(background_color);
1057#endif
1058#endif
1059 rb->lcd_set_drawmode(DRMODE_SOLID);
1060 /* draw the stacks */
1061 for(i=0; i<SUITS; i++){
1062 c = stacks[i];
1063 if(c!=NOT_A_CARD){
1064 while(deck[c].next != NOT_A_CARD){
1065 c = deck[c].next;
1066 }
1067 }
1068 1143
1069 if(c != NOT_A_CARD) { 1144 /* draw the stacks */
1070#if LCD_DEPTH>1 1145 for( i=0; i<SUITS; i++ )
1071 #ifdef HAVE_LCD_COLOR 1146 {
1072 rb->lcd_set_foreground(LCD_WHITE); 1147 c = find_last_card( STACKS_COL + i );
1073 rb->lcd_set_background(LCD_WHITE); 1148
1074 #else 1149 if( c != NOT_A_CARD )
1075 rb->lcd_set_foreground(LCD_DEFAULT_BG); 1150 {
1076 rb->lcd_set_background(LCD_DEFAULT_BG); 1151 draw_card( deck[c],
1077 #endif 1152 LCD_WIDTH2 - (CARD_WIDTH*4+8)+CARD_WIDTH*i+i*2+1, 2,
1078#endif 1153 c == sel_card, cur_col == STACKS_COL + i, false );
1079 rb->lcd_fillrect(LCD_WIDTH2 - (CARD_WIDTH*4+8)+CARD_WIDTH*i+i*2+1, 2, CARD_WIDTH-1, CARD_HEIGHT-1);
1080#if LCD_DEPTH>1
1081 rb->lcd_set_foreground(colors[i]);
1082#endif
1083 rb->lcd_mono_bitmap(numbers[deck[c].num], LCD_WIDTH2 - (CARD_WIDTH*4+8)+CARD_WIDTH*i+i*2+1, 2, BMPWIDTH_c, BMPHEIGHT_c);
1084 rb->lcd_mono_bitmap(suits[deck[c].suit], LCD_WIDTH2 - (CARD_WIDTH*4+8)+CARD_WIDTH*i+i*2+10, 2, BMPWIDTH_c, BMPHEIGHT_c);
1085 } else {
1086#if LCD_DEPTH>1
1087 #ifdef HAVE_LCD_COLOR
1088 rb->lcd_set_foreground(LCD_WHITE);
1089 rb->lcd_set_background(LCD_WHITE);
1090 #else
1091 rb->lcd_set_foreground(LCD_DEFAULT_BG);
1092 rb->lcd_set_background(LCD_DEFAULT_BG);
1093 #endif
1094#endif
1095 rb->lcd_fillrect(LCD_WIDTH2 - (CARD_WIDTH*4+8)+CARD_WIDTH*i+i*2+1, 2, CARD_WIDTH-1, CARD_HEIGHT-1);
1096#if LCD_DEPTH>1
1097 rb->lcd_set_foreground(colors[i]);
1098#endif
1099#ifdef HAVE_LCD_COLOR
1100 rb->lcd_mono_bitmap(suitsi[i], LCD_WIDTH2 - (CARD_WIDTH*4+8)+CARD_WIDTH*i+i*2+(CARD_WIDTH/2-7), CARD_HEIGHT/2-7, 15, 16);
1101#endif
1102 }
1103#if LCD_DEPTH>1
1104 rb->lcd_set_foreground(LCD_BLACK);
1105#ifdef HAVE_LCD_COLOR
1106 rb->lcd_set_background(background_color);
1107#endif
1108#endif
1109 /* draw a selected card */
1110 if(c != NOT_A_CARD) {
1111 if(sel_card == c){
1112 rb->lcd_drawrect(LCD_WIDTH2 -(CARD_WIDTH*4+8)+CARD_WIDTH*i+i*2+1, 2, CARD_WIDTH-1, CARD_HEIGHT-1);
1113 }
1114 } 1154 }
1115 rb->lcd_drawline(LCD_WIDTH2 - (CARD_WIDTH*4+8)+CARD_WIDTH*i+i*2+1, 1,LCD_WIDTH2 - (CARD_WIDTH*4+8)+CARD_WIDTH*i+i*2+CARD_WIDTH,1); 1155 else
1116 rb->lcd_drawline(LCD_WIDTH2 - (CARD_WIDTH*4+8)+CARD_WIDTH*i+i*2 ,2,LCD_WIDTH2 - (CARD_WIDTH*4+8)+CARD_WIDTH*i+i*2,CARD_HEIGHT); 1156 {
1117 rb->lcd_drawline(LCD_WIDTH2 - (CARD_WIDTH*4+8)+CARD_WIDTH*i+i*2+1,CARD_HEIGHT+1,LCD_WIDTH2 - (CARD_WIDTH*4+8)+CARD_WIDTH*i+i*2+CARD_WIDTH - 1,CARD_HEIGHT+1); 1157 draw_empty_stack( i,
1118#if BIG_SCREEN 1158 LCD_WIDTH2 - (CARD_WIDTH*4+8)+CARD_WIDTH*i+i*2+1, 2,
1119 rb->lcd_drawline(LCD_WIDTH2 - (CARD_WIDTH*4+8)+CARD_WIDTH*i+i*2+CARD_WIDTH,2,LCD_WIDTH2 - (CARD_WIDTH*4+8)+CARD_WIDTH*i+i*2+CARD_WIDTH,CARD_HEIGHT); 1159 cur_col == STACKS_COL + i );
1120#endif
1121 /* draw the cursor on one of the stacks */
1122 if(cur_col == STACKS_COL + i){
1123 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
1124 rb->lcd_fillrect(LCD_WIDTH2 - (CARD_WIDTH*4+8)+CARD_WIDTH*i+i*2+1, 2, CARD_WIDTH-1, CARD_HEIGHT-1);
1125 rb->lcd_set_drawmode(DRMODE_SOLID);
1126 } 1160 }
1127 } 1161 }
1128 1162
1129 /* draw the remains */ 1163 /* draw the remains */
1130 1164 if( rem != NOT_A_CARD )
1131 1165 {
1132 if(rem != NOT_A_CARD) { 1166 coun_rem = coun_rem>2 ? coun_rem=2 : coun_rem;
1133 coun_rem = coun_rem>2?coun_rem=2:coun_rem; 1167 if( cur_rem != NOT_A_CARD
1134 if(cur_rem != NOT_A_CARD && find_prev_card(cur_rem) != NOT_A_CARD && CARDS_PER_DRAW != 1) { 1168 && find_prev_card(cur_rem) != NOT_A_CARD
1135 j = (coun_rem)*(BMPWIDTH_c+2); 1169 && cards_per_draw != 1 )
1136 for(i=0;i<=coun_rem;i++) { 1170 {
1137 if (i>0 && i<3){ 1171 j = 0;
1138#if LCD_DEPTH>1 1172 prevcard = cur_rem;
1139 #ifdef HAVE_LCD_COLOR 1173 for( i = 0; i < coun_rem; i++ )
1140 rb->lcd_set_foreground(LCD_WHITE); 1174 prevcard = find_prev_card(prevcard);
1141 rb->lcd_set_background(LCD_WHITE); 1175 for( i = 0; i <= coun_rem; i++ )
1142 #else 1176 {
1143 rb->lcd_set_foreground(LCD_DEFAULT_BG); 1177 draw_card( deck[prevcard], CARD_WIDTH+4+j+1, 2,
1144 rb->lcd_set_background(LCD_DEFAULT_BG); 1178 sel_card == prevcard, cur_card == prevcard,
1145 #endif 1179 i < coun_rem );
1146#endif 1180 prevcard = deck[prevcard].next;
1147 rb->lcd_fillrect(CARD_WIDTH+4+j+1, 2, BMPWIDTH_c+1, CARD_HEIGHT-1); 1181 j += NUMBER_WIDTH+2;
1148 #if LCD_DEPTH>1
1149 rb->lcd_set_foreground(LCD_BLACK);
1150 #endif
1151 rb->lcd_drawline(CARD_WIDTH+4+j+1,1,CARD_WIDTH+4+j+BMPWIDTH_c+2,1); /* top line */
1152 rb->lcd_drawline(CARD_WIDTH+4+j+1,CARD_HEIGHT+1,CARD_WIDTH+4+j+BMPWIDTH_c+2,CARD_HEIGHT+1); /* bottom line */
1153 rb->lcd_drawline(CARD_WIDTH+4+j,2,CARD_WIDTH+4+j,CARD_HEIGHT); /* right line */
1154
1155
1156 prevcard = cur_rem;
1157 for(x=0;i>x;x++)
1158 prevcard = find_prev_card(prevcard);
1159 #if LCD_DEPTH>1
1160 rb->lcd_set_foreground(colors[deck[prevcard].suit]);
1161 #ifdef HAVE_LCD_COLOR
1162 rb->lcd_set_background(LCD_WHITE);
1163 #endif
1164 #endif
1165 rb->lcd_mono_bitmap(numbers[deck[prevcard].num], CARD_WIDTH+4+j+1, 3, BMPWIDTH_c, BMPHEIGHT_c);
1166 rb->lcd_mono_bitmap(suits[deck[prevcard].suit], CARD_WIDTH+4+j+1, 4+BMPHEIGHT_c, BMPWIDTH_c, BMPHEIGHT_c);
1167
1168
1169 }
1170 j -= BMPWIDTH_c+2;
1171 }
1172 }
1173#if LCD_DEPTH>1
1174 rb->lcd_set_foreground(LCD_BLACK);
1175#endif
1176 if(CARDS_PER_DRAW==1 || cur_rem==NOT_A_CARD)
1177 j=0;
1178 else
1179 j=(coun_rem)*(BMPWIDTH_c+2);
1180 if(cur_rem != NOT_A_CARD){
1181 rb->lcd_drawline(CARD_WIDTH+4+j+1,1,CARD_WIDTH+4+j+CARD_WIDTH-1,1); /* top line */
1182 rb->lcd_drawline(CARD_WIDTH+4+j,2,CARD_WIDTH+4+j,CARD_HEIGHT); /* left line */
1183 rb->lcd_drawline(CARD_WIDTH+4+j+1,CARD_HEIGHT+1,CARD_WIDTH+4+j+CARD_WIDTH - 1,CARD_HEIGHT+1); /* bottom line */
1184 rb->lcd_drawline(CARD_WIDTH+4+j+CARD_WIDTH,2,CARD_WIDTH+4+j+CARD_WIDTH,CARD_HEIGHT); /* right line */
1185 }
1186
1187 rb->lcd_drawline(2,1,CARD_WIDTH+1,1); /* top line */
1188 rb->lcd_drawline(1,2,1,CARD_HEIGHT); /* left line */
1189 rb->lcd_drawline(2,CARD_HEIGHT+1,CARD_WIDTH + 1,CARD_HEIGHT+1); /* bottom line */
1190 rb->lcd_drawline(CARD_WIDTH+2,2,CARD_WIDTH+2,CARD_HEIGHT); /* right line */
1191
1192 if(cur_rem != NOT_A_CARD){
1193#if LCD_DEPTH>1
1194 #ifdef HAVE_LCD_COLOR
1195 rb->lcd_set_foreground(LCD_WHITE);
1196 rb->lcd_set_background(LCD_WHITE);
1197 #else
1198 rb->lcd_set_foreground(LCD_DEFAULT_BG);
1199 rb->lcd_set_background(LCD_DEFAULT_BG);
1200 #endif
1201#endif
1202 rb->lcd_fillrect(CARD_WIDTH+4+j+1, 2, CARD_WIDTH-1, CARD_HEIGHT-1);
1203 #if LCD_DEPTH>1
1204 rb->lcd_set_foreground(colors[deck[cur_rem].suit]);
1205 #endif
1206 rb->lcd_mono_bitmap(numbers[deck[cur_rem].num], CARD_WIDTH+4+j+1, 3, BMPWIDTH_c, BMPHEIGHT_c);
1207 rb->lcd_mono_bitmap(suits[deck[cur_rem].suit], CARD_WIDTH+4+j+10, 3, BMPWIDTH_c, BMPHEIGHT_c);
1208 /* draw a selected card */
1209 #if LCD_DEPTH>1
1210 rb->lcd_set_foreground(LCD_BLACK);
1211 #ifdef HAVE_LCD_COLOR
1212 rb->lcd_set_background(background_color);
1213 #endif
1214 #endif
1215 if(sel_card == cur_rem){
1216 rb->lcd_drawrect(CARD_WIDTH+4+j+1, 2,CARD_WIDTH-1, CARD_HEIGHT-1);
1217 }
1218 }
1219 if(rem != NOT_A_CARD){
1220#ifdef HAVE_LCD_COLOR
1221 rb->lcd_bitmap(solitaire_cardback, 2, 2,
1222 BMPWIDTH_CARDBACK, BMPHEIGHT_CARDBACK);
1223#endif
1224 } 1182 }
1225 } 1183 }
1184 else if( cur_rem == NOT_A_CARD && cur_col == REM_COL )
1185 {
1186 draw_cursor( CARD_WIDTH+4+1, 2 );
1187 }
1226 1188
1227 1189 if( ( prevcard == NOT_A_CARD && rem != NOT_A_CARD )
1228 /* draw the cursor */ 1190 || deck[prevcard].next != NOT_A_CARD )
1229 if(cur_col == REM_COL && rem != NOT_A_CARD){ 1191 {
1230 rb->lcd_set_drawmode(DRMODE_COMPLEMENT); 1192 /* gruik ! (we want to display a card back) */
1231 rb->lcd_fillrect(CARD_WIDTH+4+j+1, 2,CARD_WIDTH-1, CARD_HEIGHT-1); 1193 deck[rem].known = false;
1232 rb->lcd_set_drawmode(DRMODE_SOLID); 1194 draw_card( deck[rem], 2, 2, false, false, false );
1233 } else if(cur_col == REM_COL && rem == NOT_A_CARD) { 1195 deck[rem].known = true;
1234 rb->lcd_set_drawmode(DRMODE_COMPLEMENT); 1196 }
1235 rb->lcd_fillrect(CARD_WIDTH+4+1, 2,CARD_WIDTH-1, CARD_HEIGHT-1);
1236 rb->lcd_set_drawmode(DRMODE_SOLID);
1237 } 1197 }
1238 1198
1239
1240 rb->lcd_update(); 1199 rb->lcd_update();
1241 1200
1242 /* what to do when a key is pressed ... */ 1201 /* what to do when a key is pressed ... */
1243 button = rb->button_get(true); 1202 button = rb->button_get( true );
1244 switch(button){ 1203 switch( button )
1245 1204 {
1246 /* move cursor to the last card of the previous column */ 1205 /* move cursor to the last card of the previous column
1247 /* or to the previous final stack */ 1206 * or to the previous final stack
1248 /* or to the remains stack */ 1207 * or to the remains stack */
1249 case SOL_RIGHT: 1208 case SOL_RIGHT:
1250#ifdef SOL_RIGHT_PRE 1209#ifdef SOL_RIGHT_PRE
1251 if(lastbutton != SOL_RIGHT_PRE) 1210 if( lastbutton != SOL_RIGHT_PRE )
1252 break; 1211 break;
1253#endif 1212#endif
1254 if(cur_col >= COL_NUM){ 1213 if( cur_col >= COL_NUM )
1214 {
1255 cur_col = 0; 1215 cur_col = 0;
1256 } else if(cur_col == COL_NUM - 1){ 1216 }
1217 else if( cur_col == COL_NUM - 1 )
1218 {
1257 cur_col = REM_COL; 1219 cur_col = REM_COL;
1258 } else { 1220 }
1221 else
1222 {
1259 cur_col = (cur_col+1)%(REM_COL+1); 1223 cur_col = (cur_col+1)%(REM_COL+1);
1260 } 1224 }
1261 if(cur_col == REM_COL){ 1225 if(cur_col == REM_COL)
1226 {
1262 cur_card = cur_rem; 1227 cur_card = cur_rem;
1263 break; 1228 break;
1264 } 1229 }
1265 cur_card = find_last_card(cur_col); 1230 cur_card = find_last_card( cur_col );
1266 break; 1231 break;
1267 1232
1268 /* move cursor to the last card of the next column */ 1233 /* move cursor to the last card of the next column
1269 /* or to the next final stack */ 1234 * or to the next final stack
1270 /* or to the remains stack */ 1235 * or to the remains stack */
1271 case SOL_LEFT: 1236 case SOL_LEFT:
1272#ifdef SOL_LEFT_PRE 1237#ifdef SOL_LEFT_PRE
1273 if(lastbutton != SOL_LEFT_PRE) 1238 if( lastbutton != SOL_LEFT_PRE )
1274 break; 1239 break;
1275#endif 1240#endif
1276 if(cur_col == 0){ 1241 if( cur_col == 0 )
1242 {
1277 cur_col = REM_COL; 1243 cur_col = REM_COL;
1278 } else if(cur_col >= COL_NUM) { 1244 }
1245 else if( cur_col >= COL_NUM )
1246 {
1279 cur_col = COL_NUM - 1; 1247 cur_col = COL_NUM - 1;
1280 } else { 1248 }
1249 else
1250 {
1281 cur_col = (cur_col + REM_COL)%(REM_COL+1); 1251 cur_col = (cur_col + REM_COL)%(REM_COL+1);
1282 } 1252 }
1283 if(cur_col == REM_COL){ 1253 if( cur_col == REM_COL )
1254 {
1284 cur_card = cur_rem; 1255 cur_card = cur_rem;
1285 break; 1256 break;
1286 } 1257 }
1287 cur_card = find_last_card(cur_col); 1258 cur_card = find_last_card( cur_col );
1288 break; 1259 break;
1289 1260
1290 /* move cursor to card that's bellow */ 1261 /* move cursor to card that's bellow */
1291 case SOL_DOWN: 1262 case SOL_DOWN:
1292#ifdef SOL_DOWN_PRE 1263#ifdef SOL_DOWN_PRE
1293 if(lastbutton != SOL_DOWN_PRE) 1264 if( lastbutton != SOL_DOWN_PRE )
1294 break; 1265 break;
1295#endif 1266#endif
1296 if(cur_col >= COL_NUM) { 1267 if( cur_col >= COL_NUM )
1268 {
1297 cur_col = (cur_col - COL_NUM + 1)%(SUITS + 1) + COL_NUM; 1269 cur_col = (cur_col - COL_NUM + 1)%(SUITS + 1) + COL_NUM;
1298 if(cur_col == REM_COL){ 1270 if( cur_col == REM_COL )
1271 {
1299 cur_card = cur_rem; 1272 cur_card = cur_rem;
1300 } 1273 }
1301 else { 1274 else
1302 cur_card = find_last_card(cur_col); 1275 {
1276 cur_card = find_last_card( cur_col );
1303 } 1277 }
1304 break; 1278 break;
1305 } 1279 }
1306 if(cur_card == NOT_A_CARD) break; 1280 if( cur_card == NOT_A_CARD ) break;
1307 if(deck[cur_card].next != NOT_A_CARD){ 1281 if( deck[cur_card].next != NOT_A_CARD )
1282 {
1308 cur_card = deck[cur_card].next; 1283 cur_card = deck[cur_card].next;
1309 } else { 1284 }
1285 else
1286 {
1310 cur_card = cols[cur_col]; 1287 cur_card = cols[cur_col];
1311 while(deck[cur_card].known == 0 1288 while( deck[ cur_card].known == 0
1312 && deck[cur_card].next != NOT_A_CARD){ 1289 && deck[cur_card].next != NOT_A_CARD )
1290 {
1313 cur_card = deck[cur_card].next; 1291 cur_card = deck[cur_card].next;
1314 } 1292 }
1315 } 1293 }
@@ -1318,36 +1296,42 @@ int solitaire(void){
1318 /* move cursor to card that's above */ 1296 /* move cursor to card that's above */
1319 case SOL_UP: 1297 case SOL_UP:
1320#ifdef SOL_UP_PRE 1298#ifdef SOL_UP_PRE
1321 if(lastbutton != SOL_UP_PRE) 1299 if( lastbutton != SOL_UP_PRE )
1322 break; 1300 break;
1323#endif 1301#endif
1324 if(cur_col >= COL_NUM) { 1302 if( cur_col >= COL_NUM )
1303 {
1325 cur_col = (cur_col - COL_NUM + SUITS)%(SUITS + 1) + COL_NUM; 1304 cur_col = (cur_col - COL_NUM + SUITS)%(SUITS + 1) + COL_NUM;
1326 if(cur_col == REM_COL){ 1305 if( cur_col == REM_COL )
1306 {
1327 cur_card = cur_rem; 1307 cur_card = cur_rem;
1328 } else { 1308 }
1329 cur_card = find_last_card(cur_col); 1309 else
1310 {
1311 cur_card = find_last_card( cur_col );
1330 } 1312 }
1331 break; 1313 break;
1332 } 1314 }
1333 if(cur_card == NOT_A_CARD) break; 1315 if( cur_card == NOT_A_CARD ) break;
1334 do{ 1316 do {
1335 cur_card = find_prev_card(cur_card); 1317 cur_card = find_prev_card( cur_card );
1336 if(cur_card == NOT_A_CARD){ 1318 if( cur_card == NOT_A_CARD )
1337 cur_card = find_last_card(cur_col); 1319 {
1320 cur_card = find_last_card( cur_col );
1338 } 1321 }
1339 } while (deck[cur_card].next != NOT_A_CARD 1322 } while( deck[cur_card].next != NOT_A_CARD
1340 && deck[cur_card].known == 0); 1323 && deck[cur_card].known == 0 );
1341 break; 1324 break;
1342 1325
1343 /* Try to put card under cursor on one of the stacks */ 1326 /* Try to put card under cursor on one of the stacks */
1344 case SOL_CUR2STACK: 1327 case SOL_CUR2STACK:
1345#ifdef SOL_CUR2STACK_PRE 1328#ifdef SOL_CUR2STACK_PRE
1346 if(lastbutton != SOL_CUR2STACK_PRE) 1329 if( lastbutton != SOL_CUR2STACK_PRE )
1347 break; 1330 break;
1348#endif 1331#endif
1349 if(cur_card != NOT_A_CARD){ 1332 if( cur_card != NOT_A_CARD )
1350 move_card(deck[cur_card].suit + STACKS_COL, cur_card); 1333 {
1334 move_card( deck[cur_card].suit + STACKS_COL, cur_card );
1351 sel_card = NOT_A_CARD; 1335 sel_card = NOT_A_CARD;
1352 } 1336 }
1353 break; 1337 break;
@@ -1355,116 +1339,141 @@ int solitaire(void){
1355 /* Move cards arround, Uncover cards, ... */ 1339 /* Move cards arround, Uncover cards, ... */
1356 case SOL_MOVE: 1340 case SOL_MOVE:
1357#ifdef SOL_MOVE_PRE 1341#ifdef SOL_MOVE_PRE
1358 if(lastbutton != SOL_MOVE_PRE) 1342 if( lastbutton != SOL_MOVE_PRE )
1359 break; 1343 break;
1360#endif 1344#endif
1361 1345
1362 if(sel_card == NOT_A_CARD) { 1346 if( sel_card == NOT_A_CARD )
1363 if(cur_card != NOT_A_CARD) { 1347 {
1364 /* reveal a hidden card */ 1348 if( cur_card != NOT_A_CARD )
1365 if(deck[cur_card].next == NOT_A_CARD && deck[cur_card].known==0){ 1349 {
1350 if( deck[cur_card].next == NOT_A_CARD
1351 && deck[cur_card].known == 0 )
1352 {
1353 /* reveal a hidden card */
1366 deck[cur_card].known = 1; 1354 deck[cur_card].known = 1;
1367 } else if(cur_col == REM_COL && cur_rem == NOT_A_CARD) { 1355 }
1356 else if( cur_col == REM_COL && cur_rem == NOT_A_CARD )
1357 {
1368 break; 1358 break;
1369 /* select a card */ 1359 }
1370 } else { 1360 else
1361 {
1362 /* select a card */
1371 sel_card = cur_card; 1363 sel_card = cur_card;
1372 } 1364 }
1373 } 1365 }
1374 /* unselect card or try putting card on one of the 4 stacks */ 1366 }
1375 } else if(sel_card == cur_card) { 1367 else if( sel_card == cur_card )
1376 move_card(deck[sel_card].suit + COL_NUM, sel_card); 1368 {
1369 /* unselect card or try putting card on
1370 * one of the 4 stacks */
1371 move_card( deck[sel_card].suit + COL_NUM, sel_card );
1377 sel_card = NOT_A_CARD; 1372 sel_card = NOT_A_CARD;
1378 if( cur_col == REM_COL ) 1373 if( cur_col == REM_COL )
1379 { 1374 {
1380 cur_card = cur_rem; 1375 cur_card = cur_rem;
1381 } 1376 }
1382 /* try moving cards */ 1377 }
1383 } else { 1378 else
1384 if(move_card(cur_col, sel_card) == MOVE_OK){ 1379 {
1380 /* try moving cards */
1381 if( move_card( cur_col, sel_card ) == MOVE_OK )
1382 {
1385 sel_card = NOT_A_CARD; 1383 sel_card = NOT_A_CARD;
1386 } 1384 }
1387 } 1385 }
1388 break; 1386 break;
1389 1387
1390 /* If the card on the top of the remains can be put where */ 1388 /* If the card on the top of the remains can be put where
1391 /* the cursor is, go ahead */ 1389 * the cursor is, go ahead */
1392 case SOL_REM2CUR: 1390 case SOL_REM2CUR:
1393#ifdef SOL_REM2CUR_PRE 1391#ifdef SOL_REM2CUR_PRE
1394 if(lastbutton != SOL_REM2CUR_PRE) 1392 if( lastbutton != SOL_REM2CUR_PRE )
1395 break; 1393 break;
1396#endif 1394#endif
1397 coun_rem = coun_rem-1; 1395 coun_rem = coun_rem-1;
1398 move_card(cur_col, cur_rem); 1396 move_card( cur_col, cur_rem );
1399 sel_card = NOT_A_CARD; 1397 sel_card = NOT_A_CARD;
1400 break; 1398 break;
1401 1399
1402 /* If the card on top of the remains can be put on one */ 1400 /* If the card on top of the remains can be put on one
1403 /* of the stacks, do so */ 1401 * of the stacks, do so */
1404 case SOL_REM2STACK: 1402 case SOL_REM2STACK:
1405#ifdef SOL_REM2STACK_PRE 1403#ifdef SOL_REM2STACK_PRE
1406 if(lastbutton != SOL_REM2STACK_PRE) 1404 if( lastbutton != SOL_REM2STACK_PRE )
1407 break; 1405 break;
1408#endif 1406#endif
1409 if(cur_rem != NOT_A_CARD){ 1407 if( cur_rem != NOT_A_CARD )
1410 move_card(deck[cur_rem].suit + COL_NUM, cur_rem); 1408 {
1409 move_card( deck[cur_rem].suit + COL_NUM, cur_rem );
1411 sel_card = NOT_A_CARD; 1410 sel_card = NOT_A_CARD;
1412 coun_rem = coun_rem-1; 1411 coun_rem = coun_rem-1;
1413 } 1412 }
1414 break; 1413 break;
1415 1414
1416
1417#ifdef SOL_REM 1415#ifdef SOL_REM
1418 case SOL_REM: 1416 case SOL_REM:
1419 if(sel_card != NOT_A_CARD){ 1417 if( sel_card != NOT_A_CARD )
1418 {
1420 /* unselect selected card */ 1419 /* unselect selected card */
1421 sel_card = NOT_A_CARD; 1420 sel_card = NOT_A_CARD;
1422 break; 1421 break;
1423 } 1422 }
1424 if(rem != NOT_A_CARD && cur_rem != NOT_A_CARD) { 1423 if( rem != NOT_A_CARD && cur_rem != NOT_A_CARD )
1425 sel_card=cur_rem; 1424 {
1426 break; 1425 sel_card=cur_rem;
1426 break;
1427 } 1427 }
1428 break; 1428 break;
1429#endif 1429#endif
1430 1430
1431 /* unselect selected card or ... */ 1431 /* unselect selected card or ...
1432 /* draw new cards from the remains of the deck */ 1432 * draw new cards from the remains of the deck */
1433 case SOL_DRAW: 1433 case SOL_DRAW:
1434#ifdef SOL_DRAW_PRE 1434#ifdef SOL_DRAW_PRE
1435 if(lastbutton != SOL_DRAW_PRE) 1435 if( lastbutton != SOL_DRAW_PRE )
1436 break; 1436 break;
1437#endif 1437#endif
1438 if(sel_card != NOT_A_CARD){ 1438 if( sel_card != NOT_A_CARD )
1439 {
1439 /* unselect selected card */ 1440 /* unselect selected card */
1440 sel_card = NOT_A_CARD; 1441 sel_card = NOT_A_CARD;
1441 break; 1442 break;
1442 } 1443 }
1443 if(rem != NOT_A_CARD) { 1444 if( rem != NOT_A_CARD )
1445 {
1444 int cur_rem_old = cur_rem; 1446 int cur_rem_old = cur_rem;
1445 coun_rem = 0; 1447 coun_rem = 0;
1446 /* draw new cards form the remains of the deck */ 1448 /* draw new cards form the remains of the deck */
1447 if(cur_rem == NOT_A_CARD){ /*if the cursor card is null*/ 1449 if( cur_rem == NOT_A_CARD )
1450 {
1451 /*if the cursor card is null*/
1448 cur_rem = rem; 1452 cur_rem = rem;
1449 i = CARDS_PER_DRAW - 1; 1453 i = cards_per_draw - 1;
1450 } else { 1454 }
1451 i = CARDS_PER_DRAW; 1455 else
1456 {
1457 i = cards_per_draw;
1452 } 1458 }
1453 1459
1454 while(i>0 && deck[cur_rem].next != NOT_A_CARD){ 1460 while( i > 0 && deck[cur_rem].next != NOT_A_CARD )
1461 {
1455 cur_rem = deck[cur_rem].next; 1462 cur_rem = deck[cur_rem].next;
1456 i--; 1463 i--;
1457 coun_rem = coun_rem +1; 1464 coun_rem = coun_rem +1;
1458 } 1465 }
1459 /* test if any cards are really left on */ 1466 /* test if any cards are really left on
1460 /* the remains' stack */ 1467 * the remains' stack */
1461 if(i == CARDS_PER_DRAW){ 1468 if( i == cards_per_draw )
1469 {
1462 cur_rem = NOT_A_CARD; 1470 cur_rem = NOT_A_CARD;
1463 coun_rem = 0; 1471 coun_rem = 0;
1464 } 1472 }
1465 /* if cursor was on remains' stack when new cards were 1473 /* if cursor was on remains' stack when new cards were
1466 * drawn, put cursor on top of remains' stack */ 1474 * drawn, put cursor on top of remains' stack */
1467 if(cur_col == REM_COL && cur_card == cur_rem_old) { 1475 if( cur_col == REM_COL && cur_card == cur_rem_old )
1476 {
1468 cur_card = cur_rem; 1477 cur_card = cur_rem;
1469 sel_card = NOT_A_CARD; 1478 sel_card = NOT_A_CARD;
1470 } 1479 }
@@ -1476,10 +1485,11 @@ int solitaire(void){
1476 case SOL_RC_QUIT: 1485 case SOL_RC_QUIT:
1477#endif 1486#endif
1478 case SOL_QUIT: 1487 case SOL_QUIT:
1479#if LCD_DEPTH>1 1488#if LCD_DEPTH > 1
1480 rb->lcd_set_background(LCD_DEFAULT_BG); 1489 rb->lcd_set_background( LCD_DEFAULT_BG );
1481#endif 1490#endif
1482 switch(solitaire_menu(MENU_DURINGGAME)){ 1491 switch( solitaire_menu( MENU_DURINGGAME ) )
1492 {
1483 case MENU_QUIT: 1493 case MENU_QUIT:
1484 return SOLITAIRE_QUIT; 1494 return SOLITAIRE_QUIT;
1485 1495
@@ -1490,44 +1500,49 @@ int solitaire(void){
1490 solitaire_init(); 1500 solitaire_init();
1491 break; 1501 break;
1492 } 1502 }
1503 break;
1504
1493 default: 1505 default:
1494 if(rb->default_event_handler(button) == SYS_USB_CONNECTED) 1506 if( rb->default_event_handler( button ) == SYS_USB_CONNECTED )
1495 return SOLITAIRE_USB; 1507 return SOLITAIRE_USB;
1496 break; 1508 break;
1497 } 1509 }
1498 1510
1499 if(button != BUTTON_NONE) 1511 if( button != BUTTON_NONE )
1500 lastbutton = button; 1512 lastbutton = button;
1501 1513
1502 /* fix incoherences concerning cur_col and cur_card */ 1514 /* fix incoherences concerning cur_col and cur_card */
1503 c = find_card_col(cur_card); 1515 c = find_card_col( cur_card );
1504 if(c != NOT_A_COL && c != cur_col) 1516 if( c != NOT_A_COL && c != cur_col )
1505 cur_card = find_last_card(cur_col); 1517 cur_card = find_last_card( cur_col );
1506 1518
1507 if(cur_card == NOT_A_CARD && find_last_card(cur_col) != NOT_A_CARD) 1519 if( cur_card == NOT_A_CARD
1508 cur_card = find_last_card(cur_col); 1520 && find_last_card( cur_col ) != NOT_A_CARD )
1521 cur_card = find_last_card( cur_col );
1509 } 1522 }
1510} 1523}
1511 1524
1512enum plugin_status plugin_start(struct plugin_api* api, void* parameter) 1525/**
1526 * Plugin entry point
1527 */
1528
1529enum plugin_status plugin_start( struct plugin_api* api, void* parameter )
1513{ 1530{
1514 int result; 1531 int result;
1515 1532
1516 /* plugin init */ 1533 /* plugin init */
1517 (void)parameter; 1534 (void)parameter;
1518 rb = api; 1535 rb = api;
1519 /* end of plugin init */
1520 /* Welcome to Solitaire ! */
1521 1536
1522 rb->splash(HZ, true, "Welcome to Solitaire !"); 1537 rb->splash( HZ, true, "Welcome to Solitaire!" );
1523 1538
1524 /* play the game :) */ 1539 /* play the game :)
1525 /* Keep playing if a game was won (that means display the menu after */ 1540 * Keep playing if a game was won (that means display the menu after
1526 /* winning instead of quiting) */ 1541 * winning instead of quiting) */
1527 while((result = solitaire()) == SOLITAIRE_WIN); 1542 while( ( result = solitaire() ) == SOLITAIRE_WIN );
1528 1543
1529 /* Exit the plugin */ 1544 /* Exit the plugin */
1530 return (result == SOLITAIRE_USB) ? PLUGIN_USB_CONNECTED : PLUGIN_OK; 1545 return ( result == SOLITAIRE_USB ) ? PLUGIN_USB_CONNECTED : PLUGIN_OK;
1531} 1546}
1532 1547
1533#endif 1548#endif