summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Ross <midgey@rockbox.org>2007-01-16 21:05:15 +0000
committerTom Ross <midgey@rockbox.org>2007-01-16 21:05:15 +0000
commit913fea27fcecd907e9432f6c87970cd08b8aea28 (patch)
tree143c3401d2b7b655e68e1edd0c7758f37d50d00d
parent285aa1b0a633616bfb3b289535a60786390e4d59 (diff)
downloadrockbox-913fea27fcecd907e9432f6c87970cd08b8aea28.tar.gz
rockbox-913fea27fcecd907e9432f6c87970cd08b8aea28.zip
t! Initial version of a Blackjack plugin for bitmap-screen targets. Also includes the changes to the manual. Cross your fingers...
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@12030 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/plugins/SOURCES1
-rw-r--r--apps/plugins/blackjack.c1442
-rw-r--r--manual/plugins/blackjack.tex81
-rw-r--r--manual/plugins/images/ss-blackjack-112x64x1.pngbin0 -> 476 bytes
-rw-r--r--manual/plugins/images/ss-blackjack-128x128x16.pngbin0 -> 2047 bytes
-rw-r--r--manual/plugins/images/ss-blackjack-138x110x2.pngbin0 -> 816 bytes
-rw-r--r--manual/plugins/images/ss-blackjack-160x128x16.pngbin0 -> 2376 bytes
-rw-r--r--manual/plugins/images/ss-blackjack-160x128x2.pngbin0 -> 871 bytes
-rw-r--r--manual/plugins/images/ss-blackjack-176x132x16.pngbin0 -> 2433 bytes
-rw-r--r--manual/plugins/images/ss-blackjack-176x220x16.pngbin0 -> 2722 bytes
-rw-r--r--manual/plugins/images/ss-blackjack-220x176x16.pngbin0 -> 4134 bytes
-rw-r--r--manual/plugins/images/ss-blackjack-240x320x16.pngbin0 -> 4574 bytes
-rw-r--r--manual/plugins/images/ss-blackjack-320x240x16.pngbin0 -> 8600 bytes
-rw-r--r--manual/plugins/main.tex2
14 files changed, 1526 insertions, 0 deletions
diff --git a/apps/plugins/SOURCES b/apps/plugins/SOURCES
index f00ac71bed..72fdf7454e 100644
--- a/apps/plugins/SOURCES
+++ b/apps/plugins/SOURCES
@@ -43,6 +43,7 @@ jpeg.c
43mandelbrot.c 43mandelbrot.c
44plasma.c 44plasma.c
45 45
46blackjack.c
46bounce.c 47bounce.c
47#ifndef SANSA_E200 48#ifndef SANSA_E200
48bubbles.c 49bubbles.c
diff --git a/apps/plugins/blackjack.c b/apps/plugins/blackjack.c
new file mode 100644
index 0000000000..775fc8c834
--- /dev/null
+++ b/apps/plugins/blackjack.c
@@ -0,0 +1,1442 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id: blackjack.c,v 1.6 2006/11/21 20:528:13 midgey34 Exp $
9 *
10 * Copyright (C) 2006 Tom Ross (midgey34@gmail.com)
11 *
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.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19
20#include "plugin.h"
21#include "solitaire_deck.h"
22#include "solitaire_cardback.h"
23
24PLUGIN_HEADER
25
26/* save files */
27#define SCORE_FILE PLUGIN_DIR "/blackjack.score"
28#define SAVE_FILE PLUGIN_DIR "/blackjack.save"
29
30#define NUM_SCORES LCD_HEIGHT/8-2
31
32/* final game return status */
33#define BJ_END 3
34#define BJ_USB 2
35#define BJ_QUIT 1
36#define BJ_LOSE 0
37
38#if CONFIG_KEYPAD == RECORDER_PAD
39#define BJACK_START BUTTON_ON
40#define BJACK_QUIT BUTTON_OFF
41#define BJACK_MAX (BUTTON_ON|BUTTON_UP)
42#define BJACK_MIN (BUTTON_ON|BUTTON_DOWN)
43#define BJACK_HIT BUTTON_F1
44#define BJACK_STAY BUTTON_F2
45#define BJACK_DOUBLEDOWN BUTTON_F3
46#define BJACK_SCORES BUTTON_RIGHT
47#define BJACK_RESUME BUTTON_PLAY
48#define BJACK_UP BUTTON_UP
49#define BJACK_DOWN BUTTON_DOWN
50#define BJACK_RIGHT BUTTON_RIGHT
51#define BJACK_LEFT BUTTON_LEFT
52
53#elif CONFIG_KEYPAD == ONDIO_PAD
54#define BJACK_START BUTTON_MENU
55#define BJACK_QUIT BUTTON_OFF
56#define BJACK_MAX (BUTTON_MENU|BUTTON_UP)
57#define BJACK_MIN (BUTTON_MENU|BUTTON_DOWN)
58#define BJACK_HIT BUTTON_LEFT
59#define BJACK_STAY BUTTON_RIGHT
60#define BJACK_DOUBLEDOWN BUTTON_UP
61#define BJACK_SCORES BUTTON_UP
62#define BJACK_RESUME BUTTON_DOWN
63#define BJACK_UP BUTTON_UP
64#define BJACK_DOWN BUTTON_DOWN
65#define BJACK_RIGHT BUTTON_RIGHT
66#define BJACK_LEFT BUTTON_LEFT
67
68#elif CONFIG_KEYPAD == IRIVER_H10_PAD
69#define BJACK_START BUTTON_PLAY
70#define BJACK_QUIT BUTTON_POWER
71#define BJACK_MAX (BUTTON_PLAY|BUTTON_SCROLL_UP)
72#define BJACK_MIN (BUTTON_PLAY|BUTTON_SCROLL_DOWN)
73#define BJACK_HIT BUTTON_PLAY
74#define BJACK_STAY BUTTON_FF
75#define BJACK_DOUBLEDOWN BUTTON_REW
76#define BJACK_SCORES BUTTON_LEFT
77#define BJACK_RESUME BUTTON_RIGHT
78#define BJACK_UP BUTTON_SCROLL_UP
79#define BJACK_DOWN BUTTON_SCROLL_DOWN
80#define BJACK_RIGHT BUTTON_RIGHT
81#define BJACK_LEFT BUTTON_LEFT
82
83#elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
84 (CONFIG_KEYPAD == IRIVER_H300_PAD)
85#define BJACK_START BUTTON_ON
86#define BJACK_QUIT BUTTON_OFF
87#define BJACK_MAX (BUTTON_ON|BUTTON_UP)
88#define BJACK_MIN (BUTTON_ON|BUTTON_DOWN)
89#define BJACK_HIT BUTTON_ON
90#define BJACK_STAY BUTTON_REC
91#define BJACK_DOUBLEDOWN BUTTON_SELECT
92#define BJACK_SCORES BUTTON_SELECT
93#define BJACK_RESUME BUTTON_MODE
94#define BJACK_UP BUTTON_UP
95#define BJACK_DOWN BUTTON_DOWN
96#define BJACK_RIGHT BUTTON_RIGHT
97#define BJACK_LEFT BUTTON_LEFT
98
99#elif (CONFIG_KEYPAD == IPOD_3G_PAD) || \
100 (CONFIG_KEYPAD == IPOD_4G_PAD)
101#define BJACK_START BUTTON_SELECT
102#define BJACK_QUIT BUTTON_MENU
103#define BJACK_MAX (BUTTON_SELECT|BUTTON_SCROLL_FWD)
104#define BJACK_MIN (BUTTON_SELECT|BUTTON_SCROLL_BACK)
105#define BJACK_HIT BUTTON_SELECT
106#define BJACK_STAY BUTTON_RIGHT
107#define BJACK_DOUBLEDOWN BUTTON_LEFT
108#define BJACK_SCORES BUTTON_RIGHT
109#define BJACK_RESUME BUTTON_PLAY
110#define BJACK_UP BUTTON_SCROLL_FWD
111#define BJACK_DOWN BUTTON_SCROLL_BACK
112#define BJACK_RIGHT BUTTON_RIGHT
113#define BJACK_LEFT BUTTON_LEFT
114
115#elif CONFIG_KEYPAD == IAUDIO_X5_PAD
116#define BJACK_START BUTTON_PLAY
117#define BJACK_QUIT BUTTON_POWER
118#define BJACK_MAX (BUTTON_PLAY|BUTTON_UP)
119#define BJACK_MIN (BUTTON_PLAY|BUTTON_DOWN)
120#define BJACK_HIT BUTTON_SELECT
121#define BJACK_STAY BUTTON_REC
122#define BJACK_DOUBLEDOWN BUTTON_PLAY
123#define BJACK_SCORES BUTTON_RIGHT
124#define BJACK_RESUME BUTTON_DOWN
125#define BJACK_UP BUTTON_UP
126#define BJACK_DOWN BUTTON_DOWN
127#define BJACK_RIGHT BUTTON_RIGHT
128#define BJACK_LEFT BUTTON_LEFT
129
130#elif CONFIG_KEYPAD == IRIVER_IFP7XX_PAD
131#define BJACK_START BUTTON_MODE
132#define BJACK_QUIT BUTTON_PLAY
133#define BJACK_MAX (BUTTON_EQ|BUTTON_UP)
134#define BJACK_MIN (BUTTON_EQ|BUTTON_DOWN)
135#define BJACK_HIT BUTTON_EQ
136#define BJACK_STAY BUTTON_MODE
137#define BJACK_DOUBLEDOWN BUTTON_SELECT
138#define BJACK_SCORES BUTTON_SELECT
139#define BJACK_RESUME (BUTTON_EQ|BUTTON_MODE)
140#define BJACK_UP BUTTON_UP
141#define BJACK_DOWN BUTTON_DOWN
142#define BJACK_RIGHT BUTTON_RIGHT
143#define BJACK_LEFT BUTTON_LEFT
144
145#elif CONFIG_KEYPAD == GIGABEAT_PAD
146#define BJACK_START BUTTON_POWER
147#define BJACK_QUIT BUTTON_A
148#define BJACK_MAX BUTTON_VOL_UP
149#define BJACK_MIN BUTTON_VOL_DOWN
150#define BJACK_HIT BUTTON_VOL_UP
151#define BJACK_STAY BUTTON_VOL_DOWN
152#define BJACK_DOUBLEDOWN BUTTON_SELECT
153#define BJACK_SCORES BUTTON_RIGHT
154#define BJACK_RESUME BUTTON_MENU
155#define BJACK_UP BUTTON_UP
156#define BJACK_DOWN BUTTON_DOWN
157#define BJACK_RIGHT BUTTON_RIGHT
158#define BJACK_LEFT BUTTON_LEFT
159
160#elif CONFIG_KEYPAD == SANSA_E200_PAD
161#define BJACK_START BUTTON_SELECT
162#define BJACK_QUIT BUTTON_POWER
163#define BJACK_MAX (BUTTON_REC|BUTTON_UP)
164#define BJACK_MIN (BUTTON_REC|BUTTON_DOWN)
165#define BJACK_HIT BUTTON_SELECT
166#define BJACK_STAY BUTTON_RIGHT
167#define BJACK_DOUBLEDOWN BUTTON_LEFT
168#define BJACK_SCORES BUTTON_UP
169#define BJACK_RESUME BUTTON_REC
170#define BJACK_UP BUTTON_SCROLL_UP
171#define BJACK_DOWN BUTTON_SCROLL_DOWN
172#define BJACK_RIGHT BUTTON_RIGHT
173#define BJACK_LEFT BUTTON_LEFT
174
175#elif CONFIG_KEYPAD == ELIO_TPJ1022_PAD
176#define BJACK_START BUTTON_MAIN
177#define BJACK_QUIT BUTTON_POWER
178#define BJACK_MAX (BUTTON_REC|BUTTON_UP)
179#define BJACK_MIN (BUTTON_REC|BUTTON_DOWN)
180#define BJACK_HIT BUTTON_MAIN
181#define BJACK_STAY BUTTON_MENU
182#define BJACK_DOUBLEDOWN BUTTON_DOWN
183#define BJACK_SCORES BUTTON_UP
184#define BJACK_RESUME BUTTON_FF
185#define BJACK_UP BUTTON_UP
186#define BJACK_DOWN BUTTON_DOWN
187#define BJACK_RIGHT BUTTON_RIGHT
188#define BJACK_LEFT BUTTON_LEFT
189
190#else
191 #error BLACKJACK: Unsupported keypad
192#endif
193
194#ifdef HAVE_LCD_COLOR
195#define BG_COLOR LCD_RGBPACK(0,157,0)
196#define FG_COLOR LCD_WHITE
197#elif LCD_DEPTH > 1
198#define BG_COLOR LCD_WHITE
199#define FG_COLOR LCD_BLACK
200#endif
201
202#define CARD_WIDTH BMPWIDTH_solitaire_cardback
203#define CARD_HEIGHT BMPHEIGHT_solitaire_cardback
204
205/* This is the max amount of cards onscreen before condensing */
206#define MAX_CARDS LCD_WIDTH/(CARD_WIDTH+4)
207
208extern const fb_data solitaire_deck[];
209extern const fb_data solitaire_cardback[];
210
211#define NEXT_CARD bj->player_cards[done][bj->num_player_cards[done]]
212
213/* global rockbox api */
214static struct plugin_api* rb;
215
216/* dealer and player card positions */
217unsigned int dealer_x, dealer_y, player_x, player_y;
218
219typedef struct card {
220 unsigned int value; /* Card's value in Blackjack */
221 unsigned int num; /* Value on card face 0-12 (0=Ace, 1=2, 11=Q) */
222 unsigned int suit; /* 0:Spades, 1:Hearts, 2: Clubs; 3: Diamonds */
223 bool is_soft_ace;
224} card;
225
226typedef struct game_context {
227 struct card player_cards[2][22]; /* 22 Cards means the deal was all aces */
228 struct card dealer_cards[22]; /* That is the worst-case scenario */
229 unsigned int player_total;
230 unsigned int dealer_total;
231 signed int player_money;
232 unsigned int num_player_cards[2];
233 unsigned int num_dealer_cards;
234 unsigned int current_bet;
235 unsigned int split_status; /* 0 = split hasn't been asked, *
236 * 1 = split did not occur *
237 * 2 = split occurred *
238 * 3 = split occurred and 1st hand done */
239 bool is_blackjack;
240 bool end_hand;
241 bool asked_insurance;
242 signed short highscores[NUM_SCORES];
243 bool resume;
244 bool dirty;
245} game_context;
246
247/*****************************************************************************
248* blackjack_init() initializes blackjack data structures.
249******************************************************************************/
250static void blackjack_init(struct game_context* bj) {
251 /* seed the rand generator */
252 rb->srand(*rb->current_tick);
253
254 /* reset card positions */
255 dealer_x = 4;
256 dealer_y = LCD_HEIGHT/4 - CARD_HEIGHT/2;
257 player_x = 4;
258 player_y = LCD_HEIGHT - LCD_HEIGHT/4 - CARD_HEIGHT/2;
259
260 /* check for resumed game */
261 if(bj->resume) return;
262
263 /* reset scoring */
264 bj->player_total = 0;
265 bj->dealer_total = 0;
266 bj->num_player_cards[0] = 2;
267 bj->num_player_cards[1] = 0;
268 bj->num_dealer_cards = 2;
269 bj->end_hand = false;
270 bj->split_status = 0;
271 bj->is_blackjack = false;
272 bj->asked_insurance = false;
273}
274
275/*****************************************************************************
276* blackjack_drawtable() draws the table and some text.
277******************************************************************************/
278static void blackjack_drawtable(struct game_context* bj) {
279 unsigned int w, h, y_loc;
280 char str[10];
281
282#if LCD_HEIGHT <= 64
283 rb->lcd_getstringsize("Bet", &w, &h);
284 rb->lcd_putsxy(LCD_WIDTH - w, 2*h + 1, "Bet");
285 rb->snprintf(str, 9, "$%d", bj->current_bet);
286 rb->lcd_getstringsize(str, &w, &h);
287 rb->lcd_putsxy(LCD_WIDTH - w, 3*h + 1, str);
288 y_loc = LCD_HEIGHT/2;
289#else
290 rb->lcd_getstringsize("Bet", &w, &h);
291 rb->lcd_putsxy(LCD_WIDTH - w, 5*h / 2, "Bet");
292 rb->snprintf(str, 9, "$%d", bj->current_bet);
293 rb->lcd_getstringsize(str, &w, &h);
294 rb->lcd_putsxy(LCD_WIDTH - w, 7*h / 2, str);
295 rb->lcd_hline(0, LCD_WIDTH, LCD_HEIGHT/2);
296 y_loc = LCD_HEIGHT/2 + h;
297#endif
298
299 rb->lcd_putsxy(0,0, "Dealer");
300 rb->lcd_getstringsize("Player", &w, &h);
301 rb->lcd_putsxy(0, y_loc, "Player");
302 rb->lcd_getstringsize("Total", &w, &h);
303 rb->lcd_putsxy(LCD_WIDTH - w, y_loc, "Total");
304 rb->lcd_getstringsize("Money", &w, &h);
305 rb->lcd_putsxy(LCD_WIDTH - w, 0, "Money");
306 rb->snprintf(str, 9, "$%d", bj->player_money - bj->current_bet);
307 rb->lcd_getstringsize(str, &w, &h);
308 rb->lcd_putsxy(LCD_WIDTH - w, h + 1, str);
309 rb->snprintf(str, 3, "%d", bj->player_total);
310 rb->lcd_getstringsize(str, &w, &h);
311 rb->lcd_putsxy(LCD_WIDTH - w, y_loc + h, str);
312}
313
314/*****************************************************************************
315* find_value() is passed a card and returns its blackjack value.
316******************************************************************************/
317static unsigned int find_value(unsigned int number) {
318 unsigned int thisValue;
319 if (number == 0)
320 thisValue = 11; /* Aces get a value of 11 at first */
321 else if (number < 10)
322 thisValue = number + 1;
323 else
324 thisValue = 10; /* Anything 10 or higher gets a value of 10 */
325
326 return thisValue;
327}
328
329/*****************************************************************************
330* draw_card() draws a card to the screen.
331******************************************************************************/
332static void draw_card(struct card temp_card, bool shown, unsigned int x,
333 unsigned int y) {
334 if(shown)
335 rb->lcd_bitmap_part(solitaire_deck, CARD_WIDTH*temp_card.num,
336 CARD_HEIGHT*temp_card.suit, BMPWIDTH_solitaire_deck,
337 x+1, y+1, CARD_WIDTH, CARD_HEIGHT);
338 else
339 rb->lcd_bitmap(solitaire_cardback, x+1, y+1,CARD_WIDTH, CARD_HEIGHT);
340#if LCD_DEPTH > 1
341 rb->lcd_set_foreground(LCD_BLACK);
342#endif
343
344 /* Print outlines */
345#if CARD_WIDTH >= 26
346 rb->lcd_hline(x+2, x+CARD_WIDTH-1, y);
347 rb->lcd_hline(x+2, x+CARD_WIDTH-1, y+CARD_HEIGHT+1);
348 rb->lcd_vline(x, y+2, y+CARD_HEIGHT-3);
349 rb->lcd_vline(x+CARD_WIDTH+1, y+2, y+CARD_HEIGHT-1);
350 rb->lcd_drawpixel(x+1, y+1);
351 rb->lcd_drawpixel(x+1, y+CARD_HEIGHT);
352 rb->lcd_drawpixel(x+CARD_WIDTH, y+1);
353 rb->lcd_drawpixel(x+CARD_WIDTH, y+CARD_HEIGHT);
354#else
355 rb->lcd_hline(x+1, x+CARD_WIDTH, y);
356 rb->lcd_hline(x+1, x+CARD_WIDTH, y+CARD_HEIGHT+1);
357 rb->lcd_vline(x, y+1, y+CARD_HEIGHT);
358 rb->lcd_vline(x+CARD_WIDTH+1, y+1, y+CARD_HEIGHT);
359#endif
360
361#if LCD_DEPTH > 1
362 rb->lcd_set_foreground(FG_COLOR);
363#endif
364}
365
366/*****************************************************************************
367* new_card() initializes a new card and gives it values.
368******************************************************************************/
369static struct card new_card(void) {
370 struct card new_card;
371 new_card.suit = rb->rand()%4; /* Random number 0-3 */
372 new_card.num = rb->rand()%13; /* Random number 0-12 */
373 new_card.value = find_value(new_card.num);
374 new_card.is_soft_ace = new_card.num == 0 ? true : false;
375 return new_card;
376}
377
378/*****************************************************************************
379* deal_init_card() deals and draws to the screen the player's and dealer's
380* initial cards.
381******************************************************************************/
382static void deal_init_cards(struct game_context* bj) {
383 bj->dealer_cards[0] = new_card();
384 bj->dealer_total += bj->dealer_cards[0].value;
385
386 draw_card(bj->dealer_cards[0], false, dealer_x, dealer_y);
387
388 bj->dealer_cards[1] = new_card();
389 bj->dealer_total += bj->dealer_cards[1].value;
390 draw_card(bj->dealer_cards[1], true, dealer_x + CARD_WIDTH + 4, dealer_y);
391
392 bj->player_cards[0][0] = new_card();
393 bj->player_total += bj->player_cards[0][0].value;
394 draw_card(bj->player_cards[0][0], true, player_x, player_y);
395 player_x += CARD_WIDTH + 4;
396
397 bj->player_cards[0][1] = new_card();
398 bj->player_total += bj->player_cards[0][1].value;
399 draw_card(bj->player_cards[0][1], true, player_x, player_y);
400 player_x += CARD_WIDTH + 4;
401}
402
403/*****************************************************************************
404* redraw_board() redraws all the cards and the board
405******************************************************************************/
406static void redraw_board(struct game_context* bj) {
407 unsigned int i, n, upper_bound;
408 rb->lcd_clear_display();
409
410 blackjack_drawtable(bj);
411 player_x = 4;
412 dealer_x = 4;
413 upper_bound = bj->split_status > 1 ? 2 : 1;
414
415 for (i = 0; i < bj->num_dealer_cards; i++) {
416 if (!bj->end_hand) {
417 draw_card(bj->dealer_cards[0], false, dealer_x, dealer_y);
418
419 /* increment i so the dealer's first card isn't displayed */
420 i++;
421 dealer_x += CARD_WIDTH + 4;
422 }
423 draw_card(bj->dealer_cards[i], true, dealer_x, dealer_y);
424
425 if (bj->num_dealer_cards > MAX_CARDS-1)
426 dealer_x += 10;
427 else
428 dealer_x += CARD_WIDTH + 4;
429 }
430
431 for (n = 0; n < upper_bound; n++) {
432 for (i = 0; i < bj->num_player_cards[n]; i++) {
433 draw_card(bj->player_cards[n][i], true, player_x, player_y);
434 if (bj->split_status>1 || bj->num_player_cards[n]>MAX_CARDS)
435 player_x += 10;
436 else
437 player_x += CARD_WIDTH + 4;
438 }
439 if (bj->split_status > 1)
440 player_x = LCD_WIDTH/2 + 4;
441 }
442}
443
444/*****************************************************************************
445* update_total updates the player's total
446******************************************************************************/
447static void update_total(struct game_context* bj) {
448 char total[3];
449 unsigned int w, h;
450 rb->snprintf(total, 3, "%d", bj->player_total);
451 rb->lcd_getstringsize(total, &w, &h);
452#if LCD_HEIGHT > 64
453 h *= 2;
454#endif
455 rb->lcd_putsxy(LCD_WIDTH - w, LCD_HEIGHT/2 + h, total);
456 rb->lcd_update_rect(LCD_WIDTH - w, LCD_HEIGHT/2 + h, w, h);
457}
458
459
460/*****************************************************************************
461* check_for_aces() is passed an array of cards and returns where an ace is
462* located. Otherwise, returns -1.
463******************************************************************************/
464static signed int check_for_aces(struct card temp_cards[],
465 unsigned int size) {
466 unsigned int i;
467 for(i = 0; i < size; i++) {
468 if (temp_cards[i].is_soft_ace == true)
469 return i;
470 }
471 return -1;
472}
473
474/*****************************************************************************
475* check_totals() compares player and dealer totals.
476* 0: bust 1: loss, 2: push, 3: win, 4: blackjack, 5: something's not right...
477******************************************************************************/
478static unsigned int check_totals(struct game_context* bj)
479{
480 unsigned int temp;
481 if (bj->player_total > 21)
482 temp = 0;
483 else if (bj->player_total == 21 && bj->is_blackjack)
484 if (bj->dealer_total == 21 && bj->num_dealer_cards == 2)
485 temp = 2;
486 else
487 temp = 4;
488 else if (bj->player_total == bj->dealer_total)
489 temp = 2;
490 else if (bj->dealer_total > 21 && bj->player_total < 22)
491 temp = 3;
492 else if (bj->dealer_total > bj->player_total)
493 temp = 1;
494 else if (bj->player_total > bj->dealer_total)
495 temp = 3;
496 else
497 temp = 5;
498
499 return temp;
500}
501
502/*****************************************************************************
503* finish_dealer() draws cards for the dealer until he has 17 or more.
504******************************************************************************/
505static void finish_dealer(struct game_context* bj) {
506 signed int temp = 0;
507
508 if (bj->dealer_total > 16 && bj->dealer_total < 22)
509 return;
510
511 while (bj->dealer_total < 17) {
512 bj->dealer_cards[bj->num_dealer_cards] = new_card();
513 bj->dealer_total += bj->dealer_cards[bj->num_dealer_cards].value;
514 bj->num_dealer_cards++;
515 }
516
517 while (bj->dealer_total > 21) {
518 temp = check_for_aces(bj->dealer_cards, bj->num_dealer_cards);
519 if(temp != -1) {
520 bj->dealer_cards[temp].is_soft_ace = false;
521 bj->dealer_total -= 10;
522 }
523 else
524 return;
525 }
526}
527
528/*****************************************************************************
529* finish_game() completes the game once player's turn is over.
530******************************************************************************/
531static void finish_game(struct game_context* bj) {
532 unsigned int rValue, w, h;
533 char str[19];
534
535 do {
536 finish_dealer(bj);
537 } while (bj->dealer_total < 17);
538
539 redraw_board(bj);
540 rValue = check_totals(bj);
541
542 if (rValue == 0) {
543 rb->snprintf(str, sizeof(str), " Bust! ");
544 bj->player_money -= bj->current_bet;
545 }
546 else if (rValue == 1) {
547 rb->snprintf(str, sizeof(str), " Sorry, you lost. ");
548 bj->player_money -= bj->current_bet;
549 }
550 else if (rValue == 2) {
551 rb->snprintf(str, sizeof(str), " Push ");
552 }
553 else if (rValue == 3) {
554 rb->snprintf(str, sizeof(str), " You won! ");
555 bj->player_money+= bj->current_bet;
556 }
557 else {
558 rb->snprintf(str, sizeof(str), " Blackjack! ");
559 bj->player_money += bj->current_bet * 3 / 2;
560 }
561 rb->lcd_getstringsize(str, &w, &h);
562
563#if LCD_HEIGHT <= 64
564 rb->lcd_set_drawmode(DRMODE_BG+DRMODE_INVERSEVID);
565 rb->lcd_fillrect(0, LCD_HEIGHT/2, LCD_WIDTH, LCD_HEIGHT/2);
566 rb->lcd_set_drawmode(DRMODE_SOLID);
567 rb->lcd_putsxy(LCD_WIDTH/2 - w/2, LCD_HEIGHT/2 + h, str);
568 rb->snprintf(str, 12, "You have %d", bj->player_total);
569 rb->lcd_getstringsize(str, &w, &h);
570 rb->lcd_putsxy(LCD_WIDTH/2 - w/2, LCD_HEIGHT/2, str);
571#else
572 rb->lcd_putsxy(LCD_WIDTH/2 - w/2, LCD_HEIGHT/2 - h/2, str);
573#endif
574 rb->lcd_update();
575}
576
577/*****************************************************************************
578* blackjack_recordscore() inserts a high score into the high scores list and
579* returns the high score position.
580******************************************************************************/
581static unsigned int blackjack_recordscore(struct game_context* bj) {
582 unsigned int i;
583 unsigned int position = 0;
584 signed short current, temp;
585
586 /* calculate total score */
587 current = bj->player_money;
588 if(current <= 10) return 0;
589
590 /* insert the current score into the high scores */
591 for(i=0; i<NUM_SCORES; i++) {
592 if(current >= bj->highscores[i]) {
593 if(!position) {
594 position = i+1;
595 bj->dirty = true;
596 }
597 temp = bj->highscores[i];
598 bj->highscores[i] = current;
599 current = temp;
600 }
601 }
602
603 return position;
604}
605
606/*****************************************************************************
607* blackjack_loadscores() loads the high scores saved file.
608******************************************************************************/
609static void blackjack_loadscores(struct game_context* bj) {
610 signed int fd;
611
612 bj->dirty = false;
613
614 /* clear high scores */
615 rb->memset(bj->highscores, 0, sizeof(bj->highscores));
616
617 /* open scores file */
618 fd = rb->open(SCORE_FILE, O_RDONLY);
619 if(fd < 0) return;
620
621 /* read in high scores */
622 if(rb->read(fd, bj->highscores, sizeof(bj->highscores)) <= 0) {
623 /* scores are bad, reset */
624 rb->memset(bj->highscores, 0, sizeof(bj->highscores));
625 }
626
627 rb->close(fd);
628}
629
630/*****************************************************************************
631* blackjack_savescores() saves the high scores saved file.
632******************************************************************************/
633static void blackjack_savescores(struct game_context* bj) {
634 unsigned int fd;
635
636 /* write out the high scores to the save file */
637 fd = rb->open(SCORE_FILE, O_WRONLY|O_CREAT);
638 rb->write(fd, bj->highscores, sizeof(bj->highscores));
639 rb->close(fd);
640 bj->dirty = false;
641}
642
643/*****************************************************************************
644* blackjack_loadgame() loads the saved game and returns load success.
645******************************************************************************/
646static bool blackjack_loadgame(struct game_context* bj) {
647 signed int fd;
648 bool loaded = false;
649
650 /* open game file */
651 fd = rb->open(SAVE_FILE, O_RDONLY);
652 if(fd < 0) return loaded;
653
654 /* read in saved game */
655 while(true) {
656 if(rb->read(fd, &bj->player_money, sizeof(bj->player_money)) <= 0) break;
657 if(rb->read(fd, &bj->player_total, sizeof(bj->player_total)) <= 0) break;
658 if(rb->read(fd, &bj->dealer_total, sizeof(bj->dealer_total)) <= 0) break;
659 if(rb->read(fd, &bj->num_player_cards, sizeof(bj->num_player_cards))<=0)
660 break;
661 if(rb->read(fd, &bj->num_dealer_cards, sizeof(bj->num_dealer_cards))<=0)
662 break;
663 if(rb->read(fd, &bj->current_bet, sizeof(bj->current_bet)) <= 0) break;
664 if(rb->read(fd, &bj->is_blackjack, sizeof(bj->is_blackjack)) <= 0) break;
665 if(rb->read(fd, &bj->split_status, sizeof(bj->split_status)) <= 0) break;
666 if(rb->read(fd, &bj->asked_insurance, sizeof(bj->asked_insurance)) <= 0)
667 break;
668 if(rb->read(fd, &bj->end_hand, sizeof(bj->end_hand)) <= 0) break;
669 if(rb->read(fd, &bj->player_cards, sizeof(bj->player_cards)) <= 0) break;
670 if(rb->read(fd, &bj->dealer_cards, sizeof(bj->dealer_cards)) <= 0) break;
671 bj->resume = true;
672 loaded = true;
673 break;
674 }
675
676 rb->close(fd);
677
678 /* delete saved file */
679 rb->remove(SAVE_FILE);
680 return loaded;
681}
682
683/*****************************************************************************
684* blackjack_savegame() saves the current game state.
685******************************************************************************/
686static void blackjack_savegame(struct game_context* bj) {
687 unsigned int fd;
688
689 /* write out the game state to the save file */
690 fd = rb->open(SAVE_FILE, O_WRONLY|O_CREAT);
691 rb->write(fd, &bj->player_money, sizeof(bj->player_money));
692 rb->write(fd, &bj->player_total, sizeof(bj->player_total));
693 rb->write(fd, &bj->dealer_total, sizeof(bj->dealer_total));
694 rb->write(fd, &bj->num_player_cards, sizeof(bj->num_player_cards));
695 rb->write(fd, &bj->num_dealer_cards, sizeof(bj->num_dealer_cards));
696 rb->write(fd, &bj->current_bet, sizeof(bj->current_bet));
697 rb->write(fd, &bj->is_blackjack, sizeof(bj->is_blackjack));
698 rb->write(fd, &bj->split_status, sizeof(bj->split_status));
699 rb->write(fd, &bj->asked_insurance, sizeof(bj->asked_insurance));
700 rb->write(fd, &bj->end_hand, sizeof(bj->end_hand));
701 rb->write(fd, &bj->player_cards, sizeof(bj->player_cards));
702 rb->write(fd, &bj->dealer_cards, sizeof(bj->dealer_cards));
703 rb->close(fd);
704
705 bj->resume = true;
706}
707
708/*****************************************************************************
709* blackjack_callback() is the default event handler callback which is called
710* on usb connect and shutdown.
711******************************************************************************/
712static void blackjack_callback(void* param) {
713 struct game_context* bj = (struct game_context*) param;
714 if(bj->dirty) {
715 rb->splash(HZ, true, "Saving high scores...");
716 blackjack_savescores(bj);
717 }
718}
719
720/*****************************************************************************
721* blackjack_get_yes_no() gets a yes/no answer from the user
722******************************************************************************/
723static unsigned int blackjack_get_yes_no(char message[20]) {
724 int button;
725 unsigned int w, h, b, choice = 0;
726 bool breakout = false;
727 char message_yes[24], message_no[24];
728
729 rb->strcpy(message_yes, message);
730 rb->strcpy(message_no, message);
731 rb->strcat(message_yes, " Yes");
732 rb->strcat(message_no, " No");
733 rb->lcd_getstringsize(message_yes, &w, &h);
734 const char *stg[] = {message_yes, message_no};
735
736#if LCD_HEIGHT <= 64
737 b = 2*h+1;
738#else
739 b = h-1;
740#endif
741
742#ifdef HAVE_LCD_COLOR
743 rb->lcd_fillrect(LCD_WIDTH/2 - w/2, LCD_HEIGHT/2 + b, w+1, h+3);
744 rb->lcd_set_foreground(LCD_BLACK);
745 rb->lcd_set_background(LCD_WHITE);
746#else
747 rb->lcd_set_drawmode(DRMODE_BG+DRMODE_INVERSEVID);
748 rb->lcd_fillrect(LCD_WIDTH/2 - w/2, LCD_HEIGHT/2 + b, w+1, h+3);
749 rb->lcd_set_drawmode(DRMODE_SOLID);
750#endif
751 rb->lcd_drawrect(LCD_WIDTH/2 - w/2 - 1, LCD_HEIGHT/2 + b - 1, w+3, h+4);
752
753 while(!breakout) {
754 rb->lcd_putsxy(LCD_WIDTH/2 - w/2, LCD_HEIGHT/2 + b +1, stg[choice]);
755 rb->lcd_update_rect(LCD_WIDTH/2 - w/2 - 1, LCD_HEIGHT/2 + b -1,
756 w+3, h+4);
757 button = rb->button_get(true);
758
759 switch(button) {
760 case BJACK_LEFT:
761 case (BJACK_LEFT|BUTTON_REPEAT):
762 case BJACK_RIGHT:
763 case (BJACK_RIGHT|BUTTON_REPEAT):
764 choice ^= 1;
765 break;
766 case BJACK_START: breakout = true;
767 break;
768 case BJACK_QUIT: breakout = true;
769 choice = BJ_QUIT;
770 break;
771 }
772 }
773
774#if LCD_DEPTH > 1
775 rb->lcd_set_foreground(FG_COLOR);
776 rb->lcd_set_background(BG_COLOR);
777#endif
778 return choice;
779}
780
781/*****************************************************************************
782* blackjack_get_amount() gets an amount from the player to be used
783******************************************************************************/
784static signed int blackjack_get_amount(char message[20], signed int lower_limit,
785 signed int upper_limit,
786 signed int start) {
787 int button;
788 char str[6];
789 bool changed = false;
790 unsigned int w, h;
791 signed int amount;
792
793 rb->lcd_getstringsize("A", &w, &h); /* find the size of one character */
794
795 if (start > upper_limit)
796 amount = upper_limit;
797 else if (start < lower_limit)
798 amount = lower_limit;
799 else
800 amount = start;
801
802#if LCD_DEPTH > 1
803 rb->lcd_set_background(LCD_WHITE);
804 rb->lcd_set_foreground(LCD_BLACK);
805#endif
806
807#if LCD_HEIGHT <= 64
808 rb->lcd_clear_display();
809 rb->lcd_puts(0, 1, message);
810 rb->snprintf(str, 9, "$%d", amount);
811 rb->lcd_puts(0, 2, str);
812 rb->lcd_puts(0, 3, "RIGHT: +1");
813 rb->lcd_puts(0, 4, "LEFT: -1");
814 rb->lcd_puts(0, 5, "UP: +10");
815 rb->lcd_puts(0, 6, "DOWN: -10");
816 rb->lcd_update();
817#else
818 rb->lcd_set_drawmode(DRMODE_BG+DRMODE_INVERSEVID);
819 rb->lcd_fillrect(LCD_WIDTH/2 - 9*w - 1, LCD_HEIGHT/2 - 4*h - 3, 37*w / 2,
820 8*h -3);
821 rb->lcd_set_drawmode(DRMODE_SOLID);
822 rb->lcd_drawrect(LCD_WIDTH/2 - 9*w - 1, LCD_HEIGHT/2 - 4*h - 3, 37*w / 2,
823 8*h -3);
824 rb->lcd_putsxy(LCD_WIDTH/2 - 9*w, LCD_HEIGHT/2 - 4*h - 1, message);
825 rb->snprintf(str, 9, "$%d", amount);
826 rb->lcd_putsxy(LCD_WIDTH/2 - 9*w, LCD_HEIGHT/2 - 3*h, str);
827#if (CONFIG_KEY == IPOD_3G_PAD) || (CONFIG_KEYPAD == IPOD_4G_PAD)
828 rb->lcd_putsxy(LCD_WIDTH/2 - 9*w, LCD_HEIGHT/2 - h-2, " >>|: +1");
829 rb->lcd_putsxy(LCD_WIDTH/2 - 9*w, LCD_HEIGHT/2 - 1, " |<<: -1");
830 rb->lcd_putsxy(LCD_WIDTH/2 - 9*w, LCD_HEIGHT/2 + h, "SCROLL+: +10");
831 rb->lcd_putsxy(LCD_WIDTH/2 - 9*w, LCD_HEIGHT/2 + 2*h + 1, "SCROLL-: -10");
832#elif CONFIG_KEYPAD == IRIVER_H10_PAD
833 rb->lcd_putsxy(LCD_WIDTH/2 - 9*w, LCD_HEIGHT/2 - h-2, "RIGHT: +1");
834 rb->lcd_putsxy(LCD_WIDTH/2 - 9*w, LCD_HEIGHT/2 - 1, "LEFT: -1");
835 rb->lcd_putsxy(LCD_WIDTH/2 - 9*w, LCD_HEIGHT/2 + h, "SCROLL+: +10");
836 rb->lcd_putsxy(LCD_WIDTH/2 - 9*w, LCD_HEIGHT/2 + 2*h + 1, "SCROLL-: -10");
837#else
838 rb->lcd_putsxy(LCD_WIDTH/2 - 9*w, LCD_HEIGHT/2 - h-2, "RIGHT: +1");
839 rb->lcd_putsxy(LCD_WIDTH/2 - 9*w, LCD_HEIGHT/2 - 1, "LEFT: -1");
840 rb->lcd_putsxy(LCD_WIDTH/2 - 9*w, LCD_HEIGHT/2 + h, "UP: +10");
841 rb->lcd_putsxy(LCD_WIDTH/2 - 9*w, LCD_HEIGHT/2 + 2*h + 1, "DOWN: -10");
842#endif
843 rb->lcd_update_rect(LCD_WIDTH/2 - 9*w - 2, LCD_HEIGHT/2 - 9*h/2, 37*w/2 + 1,
844 8*h-2);
845#endif
846
847 while(true) {
848 button = rb->button_get(true);
849
850 switch(button) {
851 case BJACK_UP:
852 case (BJACK_UP|BUTTON_REPEAT):
853 if (amount + 10 < upper_limit + 1) {
854 amount += 10;
855 changed = true;
856 }
857 break;
858 case BJACK_DOWN:
859 case (BJACK_DOWN|BUTTON_REPEAT):
860 if (amount - 10 > lower_limit - 1) {
861 amount -= 10;
862 changed = true;
863 }
864 break;
865 case BJACK_RIGHT:
866 case (BJACK_RIGHT|BUTTON_REPEAT):
867 if (amount + 1 < upper_limit + 1) {
868 amount++;
869 changed = true;
870 }
871 break;
872 case BJACK_LEFT:
873 case (BJACK_LEFT|BUTTON_REPEAT):
874 if (amount - 1 > lower_limit - 1) {
875 amount--;
876 changed = true;
877 }
878 break;
879 case BJACK_MAX :
880 amount = upper_limit;
881 changed = true;
882 break;
883 case BJACK_MIN :
884 amount = lower_limit;
885 changed = true;
886 break;
887 case BJACK_QUIT:
888 return 0;
889 case BJACK_START:
890#if LCD_DEPTH > 1
891 rb->lcd_set_foreground(FG_COLOR);
892 rb->lcd_set_background(BG_COLOR);
893#endif
894 rb->lcd_clear_display();
895 return amount;
896 }
897
898 if(changed) {
899 rb->snprintf(str, 9, "$%d", amount);
900#if LCD_HEIGHT <= 64
901 rb->lcd_puts(0, 2, str);
902 rb->lcd_update();
903#else
904 rb->lcd_set_drawmode(DRMODE_BG+DRMODE_INVERSEVID);
905 rb->lcd_fillrect(LCD_WIDTH/2 - 9*w, LCD_HEIGHT/2 - 3*h, 5*w, h);
906 rb->lcd_set_drawmode(DRMODE_SOLID);
907 rb->lcd_putsxy(LCD_WIDTH/2 - 9*w, LCD_HEIGHT/2 - 3*h, str);
908 rb->lcd_update_rect(LCD_WIDTH/2 - 9*w, LCD_HEIGHT/2 - 3*h, 5*w, h);
909#endif
910 changed = false;
911 }
912 }
913}
914
915/*****************************************************************************
916* blackjack_get_bet() gets the player's bet.
917******************************************************************************/
918static void blackjack_get_bet(struct game_context* bj) {
919 bj->current_bet = blackjack_get_amount("Please enter a bet", 10,
920 bj->player_money, bj->current_bet);
921}
922
923/*****************************************************************************
924* double_down() returns one final card then finishes the game
925******************************************************************************/
926static void double_down(struct game_context* bj) {
927 bj->current_bet *= 2;
928 bj->player_cards[0][bj->num_player_cards[0]] = new_card();
929 bj->player_total += bj->player_cards[0][bj->num_player_cards[0]].value;
930 bj->num_player_cards[0]++;
931}
932
933/*****************************************************************************
934* split() checks if the player wants to split and acts accordingly.
935* When bj->split_status is 1, no split occurred. 2 means the player split and 3
936* means a split has already occurred and the first hand is done.
937******************************************************************************/
938static void split(struct game_context* bj) {
939 if (blackjack_get_yes_no("Split?") == 1)
940 bj->split_status = 1;
941 else {
942 bj->split_status = 2;
943 bj->current_bet *= 2;
944 bj->num_player_cards[0] = 1;
945 bj->num_player_cards[1] = 1;
946 bj->player_cards[1][0] = bj->player_cards[0][1];
947 bj->player_total = bj->player_cards[0][0].value;
948 }
949}
950
951/*****************************************************************************
952* insurance() see if the player wants to buy insurance and how much.
953******************************************************************************/
954static unsigned int insurance(struct game_context* bj) {
955 unsigned int insurance, max_amount;
956
957 insurance = blackjack_get_yes_no("Buy Insurance?");
958 bj->asked_insurance = true;
959 max_amount = bj->current_bet < (unsigned int)bj->player_money ?
960 bj->current_bet/2 : (unsigned int)bj->player_money;
961 if (insurance == 1) return 0;
962
963 insurance = blackjack_get_amount("How much?", 0, max_amount, 0);
964 redraw_board(bj);
965 return insurance;
966}
967
968/*****************************************************************************
969* play_again() checks to see if the player wants to keep playing.
970******************************************************************************/
971static unsigned int play_again(void) {
972 return blackjack_get_yes_no("Play Again?");
973}
974
975/*****************************************************************************
976* blackjack_menu() is the initial menu at the start of the game.
977******************************************************************************/
978static unsigned int blackjack_menu(struct game_context* bj) {
979 int button;
980 char *title = "Blackjack";
981 char str[18];
982 unsigned int i, w, h;
983 bool breakout = false;
984 bool showscores = false;
985
986 while(true){
987#if LCD_DEPTH > 1
988 rb->lcd_set_background(BG_COLOR);
989 rb->lcd_set_foreground(FG_COLOR);
990#endif
991 rb->lcd_clear_display();
992
993 if(!showscores) {
994 /* welcome screen to display key bindings */
995 rb->lcd_getstringsize(title, &w, &h);
996 rb->lcd_putsxy((LCD_WIDTH-w)/2, 0, title);
997
998#if CONFIG_KEYPAD == RECORDER_PAD
999 rb->lcd_puts(0, 1, "ON: start");
1000 rb->lcd_puts(0, 2, "OFF: exit");
1001 rb->lcd_puts(0, 3, "F1: hit");
1002 rb->lcd_puts(0, 4, "F2: stay");
1003 rb->lcd_puts(0, 5, "F3: double down");
1004 rb->lcd_puts(0, 6, "PLAY: save/resume");
1005 rb->snprintf(str, 21, "High Score: $%d", bj->highscores[0]);
1006 rb->lcd_puts(0, 7, str);
1007#elif CONFIG_KEYPAD == ONDIO_PAD
1008 rb->lcd_puts(0, 1, "MENU: start");
1009 rb->lcd_puts(0, 2, "OFF: exit");
1010 rb->lcd_puts(0, 3, "LEFT: hit");
1011 rb->lcd_puts(0, 4, "RIGHT: stay");
1012 rb->lcd_puts(0, 5, "UP: double down");
1013 rb->lcd_puts(0, 6, "DOWN: save/resume");
1014 rb->snprintf(str, 21, "High Score: $%d", bj->highscores[0]);
1015 rb->lcd_puts(0, 7, str);
1016#elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || (CONFIG_KEYPAD == IRIVER_H300_PAD)
1017 rb->lcd_puts(0, 2, "PLAY to start & to hit");
1018 rb->lcd_puts(0, 3, "STOP to exit");
1019 rb->lcd_puts(0, 4, "REC to stay");
1020 rb->lcd_puts(0, 5, "NAVI to double down ");
1021 rb->lcd_puts(0, 6, " & to view highscores");
1022 rb->lcd_puts(0, 7, "AB to save/resume");
1023 rb->snprintf(str, 21, "High Score: $%d", bj->highscores[0]);
1024 rb->lcd_puts(0, 8, str);
1025#elif CONFIG_KEYPAD == IRIVER_H10_PAD
1026 rb->lcd_puts(0, 2, "PLAY to start & hit");
1027 rb->lcd_puts(0, 3, "POWER to exit");
1028 rb->lcd_puts(0, 4, ">>| to stay");
1029 rb->lcd_puts(0, 5, "|<< to double down");
1030 rb->lcd_puts(0, 6, "LEFT to view scores");
1031 rb->lcd_puts(0, 7, "RIGHT to save/resume");
1032 rb->snprintf(str, 21, "High Score: $%d", bj->highscores[0]);
1033 rb->lcd_puts(0, 8, str);
1034
1035#elif (CONFIG_KEYPAD == IPOD_3G_PAD) || (CONFIG_KEYPAD == IPOD_4G_PAD)
1036#if LCD_WIDTH >=176
1037 rb->lcd_puts(0, 2, "SELECT to start & to hit");
1038 rb->lcd_puts(0, 3, "MENU to exit");
1039 rb->lcd_puts(0, 4, ">>| to stay & to view highscores");
1040 rb->lcd_puts(0, 5, "|<< to double down");
1041 rb->lcd_puts(0, 6, "PLAY to save/resume");
1042 rb->snprintf(str, 21, "High Score: $%d", bj->highscores[0]);
1043 rb->lcd_puts(0, 7, str);
1044#else
1045 rb->lcd_puts(0, 2, "SELECT to start & to ");
1046 rb->lcd_puts(0, 3, " hit");
1047 rb->lcd_puts(0, 4, "MENU to exit");
1048 rb->lcd_puts(0, 5, ">>| to stay & to view ");
1049 rb->lcd_puts(0, 6, " highscores");
1050 rb->lcd_puts(0, 7, "|<< to double down");
1051 rb->lcd_puts(0, 8, "PLAY to save/resume");
1052 rb->snprintf(str, 21, "High Score: $%d", bj->highscores[0]);
1053 rb->lcd_puts(0, 9, str);
1054#endif
1055#elif CONFIG_KEYPAD == IAUDIO_X5_PAD
1056 rb->lcd_puts(0, 2, "PLAY to start to hit");
1057 rb->lcd_puts(0, 3, "POWER to exit");
1058 rb->lcd_puts(0, 4, "SELECT to hit");
1059 rb->lcd_puts(0, 5, "REC to stay");
1060 rb->lcd_puts(0, 6, "PLAY to double down");
1061 rb->lcd_puts(0, 7, "RIGHT to view highscores ");
1062 rb->lcd_puts(0, 8, "DOWN to save/resume");
1063 rb->snprintf(str, 21, "High Score: $%d", bj->highscores[0]);
1064 rb->lcd_puts(0, 9, str);
1065#elif CONFIG_KEYPAD == IRIVER_IFP7XX_PAD
1066 rb->lcd_puts(0, 2, "AB to start & to");
1067 rb->lcd_puts(0, 3, " stay");
1068 rb->lcd_puts(0, 4, "EQ to hit");
1069 rb->lcd_puts(0, 5, "PLAY to exit");
1070 rb->lcd_puts(0, 6, "CLICK to double down");
1071 rb->lcd_puts(0, 7, "& to view highscores");
1072 rb->lcd_puts(0, 8, "AB+EQ to save/resume");
1073 rb->snprintf(str, 21, "High Score: $%d", bj->highscores[0]);
1074 rb->lcd_puts(0, 9, str);
1075#elif CONFIG_KEYPAD == GIGABEAT_PAD
1076 rb->lcd_puts(0, 2, "POWER to start");
1077 rb->lcd_puts(0, 3, "A to exit");
1078 rb->lcd_puts(0, 4, "VOL+ to hit");
1079 rb->lcd_puts(0, 5, "VOL- to stay");
1080 rb->lcd_puts(0, 6, "CENTER to double down");
1081 rb->lcd_puts(0, 6, "RIGHT to view highscores ");
1082 rb->lcd_puts(0, 8, "MENU to save/resume");
1083 rb->snprintf(str, 21, "High Score: $%d", bj->highscores[0]);
1084 rb->lcd_puts(0, 9, str);
1085#elif (CONFIG_KEYPAD == SANSA_E200_PAD)
1086 rb->lcd_puts(0, 2, "SELECT to start & to hit");
1087 rb->lcd_puts(0, 3, "POWER to exit");
1088 rb->lcd_puts(0, 4, "RIGHT to stay");
1089 rb->lcd_puts(0, 5, "LEFT to double down");
1090 rb->lcd_puts(0, 6, "REC to save/resume");
1091 rb->lcd_puts(0, 7, "UP to view scores");
1092 rb->snprintf(str, 21, "High Score: $%d", bj->highscores[0]);
1093 rb->lcd_puts(0, 8, str);
1094
1095#endif
1096 } else {
1097 rb->snprintf(str, 12, "%s", "High Scores");
1098 rb->lcd_getstringsize(str, &w, &h);
1099 rb->lcd_putsxy((LCD_WIDTH-w)/2, 0, str);
1100
1101 /* print high scores */
1102 for(i=0; i<NUM_SCORES; i++) {
1103 rb->snprintf(str, 14, "#%02d: $%d", i+1, bj->highscores[i]);
1104 rb->lcd_puts(0, i+1, str);
1105 }
1106 }
1107
1108 rb->lcd_update();
1109
1110 /* handle menu button presses */
1111 button = rb->button_get(true);
1112
1113 switch(button) {
1114 case BJACK_START: /* start playing */
1115 breakout = true;
1116 break;
1117
1118 case BJACK_QUIT: /* quit program */
1119 if(showscores) {
1120 showscores = 0;
1121 break;
1122 }
1123 return BJ_QUIT;
1124
1125 case BJACK_RESUME:/* resume game */
1126 if(!blackjack_loadgame(bj)) {
1127 rb->splash(HZ*2, true, "Nothing to resume");
1128 } else {
1129 rb->splash(HZ*2, true, "Loading...");
1130 breakout = true;
1131 }
1132 break;
1133
1134 case BJACK_SCORES:/* toggle high scores */
1135 showscores = !showscores;
1136 break;
1137
1138 default:
1139 if(rb->default_event_handler_ex(button, blackjack_callback,
1140 (void*) bj) == SYS_USB_CONNECTED)
1141 return BJ_USB;
1142 break;
1143 }
1144
1145 if(breakout) break;
1146 }
1147
1148 return(0);
1149}
1150
1151/*****************************************************************************
1152* blackjack() is the main game subroutine, it returns the final game status.
1153******************************************************************************/
1154static int blackjack(struct game_context* bj) {
1155 int button;
1156 unsigned int w, h, temp_var, done = 0, todo = 1;
1157 signed int temp;
1158 bool breakout = false;
1159 bool dbl_down = false;
1160
1161 /* don't resume by default */
1162 bj->resume = false;
1163
1164 /********************
1165 * menu *
1166 ********************/
1167 temp_var = blackjack_menu(bj);
1168 if (temp_var == BJ_QUIT || temp_var == BJ_USB)
1169 return temp_var;
1170
1171
1172 /********************
1173 * init *
1174 ********************/
1175 blackjack_init(bj);
1176 bj->current_bet=10;
1177
1178 /********************
1179 * play *
1180 ********************/
1181
1182 /* check for resumed game */
1183 if(bj->resume) {
1184 bj->resume = false;
1185 redraw_board(bj);
1186 if (bj->split_status == 2) {
1187 todo=2;
1188 player_x = bj->num_player_cards[0] * 10 + 4;
1189 }
1190 else if (bj->split_status == 3) {
1191 player_x = bj->num_player_cards[1] * 10 + LCD_WIDTH/2 + 4;
1192 todo=2;
1193 done=1;
1194 }
1195
1196 }
1197 else {
1198 bj->player_money = 1000;
1199 blackjack_get_bet(bj);
1200 if (bj->current_bet == 0)
1201 return BJ_QUIT;
1202 rb->lcd_clear_display();
1203 deal_init_cards(bj);
1204 blackjack_drawtable(bj);
1205 }
1206
1207 rb->lcd_update();
1208
1209 breakout = false;
1210
1211 while(true){
1212 if(bj->player_total == 21 && bj->num_player_cards[0] == 2) {
1213 bj->is_blackjack = true;
1214 bj->end_hand = true;
1215 finish_game(bj);
1216 }
1217 else if(bj->dealer_cards[1].is_soft_ace && !breakout &&
1218 !bj->asked_insurance) {
1219 temp_var = insurance(bj);
1220 if (bj->dealer_total == 21) {
1221 rb->splash(HZ, true, "Dealer has blackjack");
1222 bj->player_money += temp_var;
1223 bj->end_hand = true;
1224 breakout = true;
1225 redraw_board(bj);
1226 finish_game(bj);
1227 }
1228 else {
1229 rb->splash(HZ, true, "Dealer does not have blackjack");
1230 bj->player_money -= temp_var;
1231 breakout = true;
1232 redraw_board(bj);
1233 rb->lcd_update();
1234 }
1235 }
1236 if(bj->split_status == 0 &&
1237 bj->player_cards[0][0].num == bj->player_cards[0][1].num) {
1238 split(bj);
1239 redraw_board(bj);
1240 rb->lcd_update_rect(0, LCD_HEIGHT/2, LCD_WIDTH, LCD_HEIGHT/2);
1241 if (bj->split_status == 2) {
1242 todo++;
1243 player_x = bj->num_player_cards[0] * 10 + 4;
1244 }
1245 }
1246
1247 while(done < todo) {
1248 button = rb->button_get(true);
1249
1250 switch(button) {
1251 case BJACK_HIT:
1252 NEXT_CARD = new_card();
1253 bj->player_total += NEXT_CARD.value;
1254 draw_card(NEXT_CARD, true, player_x, player_y);
1255 bj->num_player_cards[done]++;
1256 if (bj->num_player_cards[done] == MAX_CARDS + 1) {
1257 redraw_board(bj);
1258 rb->lcd_update_rect(0, LCD_HEIGHT/2, LCD_WIDTH,
1259 LCD_HEIGHT/2);
1260 }
1261 else if (bj->num_player_cards[done]>MAX_CARDS || todo > 1) {
1262 rb->lcd_update_rect(player_x, player_y, CARD_WIDTH+2,
1263 CARD_HEIGHT+2);
1264 player_x += 10;
1265 }
1266 else {
1267 rb->lcd_update_rect(player_x, player_y, CARD_WIDTH+2,
1268 CARD_HEIGHT+2);
1269 player_x += CARD_WIDTH + 4;
1270 }
1271 update_total(bj);
1272
1273 break;
1274 case BJACK_STAY:
1275 bj->end_hand = true;
1276 break;
1277 case BJACK_DOUBLEDOWN:
1278 if ((signed int)bj->current_bet * 2 < bj->player_money + 1 &&
1279 bj->num_player_cards[0]==2 && todo==1) {
1280 double_down(bj);
1281 dbl_down = true;
1282 if (bj->player_total < 22) {
1283 bj->end_hand = true;
1284 finish_game(bj);
1285 }
1286 }
1287 else if((signed int)bj->current_bet * 2 > bj->player_money) {
1288 rb->splash(HZ, true, "Not enough money to double down.");
1289 redraw_board(bj);
1290 rb->lcd_update();
1291 }
1292 break;
1293 case BJACK_RESUME: /* save and end game */
1294 rb->splash(HZ, true, "Saving game...");
1295 blackjack_savegame(bj);
1296 /* fall through to BJACK_QUIT */
1297
1298 case BJACK_QUIT:
1299 return BJ_END;
1300 }
1301
1302 while (bj->player_total > 21 && !bj->end_hand) {
1303 temp = check_for_aces(bj->player_cards[done],
1304 bj->num_player_cards[done]);
1305 if(temp != -1) {
1306 bj->player_cards[done][temp].is_soft_ace = false;
1307 bj->player_total -= 10;
1308 update_total(bj);
1309 if (dbl_down) {
1310 bj->end_hand = true;
1311 finish_game(bj);
1312 }
1313 }
1314 else
1315 bj->end_hand = true;
1316 }
1317
1318 if (bj->end_hand) {
1319 done++;
1320 if(todo > 1) {
1321 if (done == 2) {
1322 temp = bj->player_total;
1323 bj->player_total = temp_var;
1324 temp_var = temp;
1325 finish_game(bj);
1326 rb->lcd_getstringsize(" Split 1 ", &w, &h);
1327 rb->lcd_putsxy(LCD_WIDTH/2-w/2, LCD_HEIGHT/2-3*h/2,
1328 " Split 1 ");
1329 rb->lcd_update_rect(LCD_WIDTH/2-w/2, LCD_HEIGHT/2-3*h/2,
1330 w,h);
1331 bj->current_bet /= 2;
1332 rb->lcd_update_rect(LCD_WIDTH/2-w/2, LCD_HEIGHT/2-3*h/2,
1333 w,h);
1334 rb->sleep(HZ*2);
1335 bj->player_total = temp_var;
1336 finish_game(bj);
1337 rb->lcd_getstringsize(" Split 2 ", &w, &h);
1338 rb->lcd_putsxy(LCD_WIDTH/2-w/2, LCD_HEIGHT/2-3*h/2,
1339 " Split 2 ");
1340 rb->lcd_update_rect(LCD_WIDTH/2-w/2, LCD_HEIGHT/2-3*h/2,
1341 w,h);
1342 rb->sleep(HZ*2);
1343 }
1344 else {
1345 bj->end_hand = false;
1346 bj->split_status = 3;
1347 temp_var = bj->player_total;
1348 bj->player_total = bj->player_cards[1][0].value;
1349 update_total(bj);
1350 redraw_board(bj);
1351 player_x += 10;
1352 rb->lcd_update();
1353 }
1354 }
1355 else
1356 finish_game(bj);
1357 }
1358 }
1359
1360 if (bj->player_money < 10) {
1361 rb->sleep(HZ);
1362 return BJ_LOSE;
1363 }
1364
1365 if (bj->end_hand) { /* If hand is over */
1366 if (play_again() != 0) /* User wants to quit */
1367 return BJ_END;
1368 else { /* User keeps playing */
1369 breakout = false;
1370 redraw_board(bj);
1371 if(dbl_down) {
1372 bj->current_bet /= 2;
1373 dbl_down = false;
1374 }
1375 done = 0;
1376 todo = 1;
1377 blackjack_init(bj);
1378 blackjack_get_bet(bj);
1379 if (bj->current_bet == 0)
1380 return BJ_END;
1381 deal_init_cards(bj);
1382 blackjack_drawtable(bj);
1383 rb->lcd_update();
1384 }
1385 }
1386 }
1387 /* Never reached */
1388 return PLUGIN_OK;
1389}
1390
1391/*****************************************************************************
1392* plugin entry point.
1393******************************************************************************/
1394enum plugin_status plugin_start(struct plugin_api* api, void* parameter) {
1395 struct game_context bj;
1396 bool exit = false;
1397 unsigned int position;
1398 char str[19];
1399
1400 (void)parameter;
1401 rb = api;
1402
1403 /* load high scores */
1404 blackjack_loadscores(&bj);
1405
1406 rb->lcd_setfont(FONT_SYSFIXED);
1407
1408 while(!exit) {
1409 switch(blackjack(&bj)){
1410 case BJ_LOSE:
1411 rb->splash(HZ, true, "Not enough money to continue");
1412 /* fall through to BJ_END */
1413
1414 case BJ_END:
1415 if(!bj.resume) {
1416 if((position = blackjack_recordscore(&bj))) {
1417 rb->snprintf(str, 19, "New high score #%d!", position);
1418 rb->splash(HZ*2, true, str);
1419 }
1420 }
1421 break;
1422
1423 case BJ_USB:
1424 rb->lcd_setfont(FONT_UI);
1425 return PLUGIN_USB_CONNECTED;
1426
1427 case BJ_QUIT:
1428 if(bj.dirty) {
1429 rb->splash(HZ, true, "Saving high scores...");
1430 blackjack_savescores(&bj);
1431 }
1432 exit = true;
1433 break;
1434
1435 default:
1436 break;
1437 }
1438 }
1439
1440 rb->lcd_setfont(FONT_UI);
1441 return PLUGIN_OK;
1442}
diff --git a/manual/plugins/blackjack.tex b/manual/plugins/blackjack.tex
new file mode 100644
index 0000000000..7a7caa491a
--- /dev/null
+++ b/manual/plugins/blackjack.tex
@@ -0,0 +1,81 @@
1\subsection{Blackjack}
2\screenshot{plugins/images/ss-blackjack}{Blackjack}{fig:blackjack}
3
4Blackjack, a game played in casinos around the world, is now available
5in the palm of your hand! The rules are simple: try to get as close to 21
6without going over or simply beat out the dealer for the best hand.
7Although this may not seem difficult, blackjack is a game renowned for the
8strategy involved. This version includes the ability to split, buy insurance,
9and double down.
10
11For the full set of rules to the game, and other facinating information
12visit\\
13\url{http://www.blackjackinfo.com/blackjack-rules.php}
14
15\begin{table}
16 \begin{btnmap}{}{}
17 \multicolumn{2}{c}{\textbf{In menu}}\\\hline
18 \opt{RECORDER_PAD,IRIVER_H100_PAD,IRIVER_H300_PAD}{\ButtonOn}
19 \opt{GIGABEAT_PAD}{\ButtonPower}
20 \opt{IAUDIO_X5_PAD,IRIVER_H10_PAD}{\ButtonPlay}
21 \opt{IPOD_4G_PAD,IPOD_3G_PAD,SANSA_E200_PAD}{\ButtonSelect}
22 \opt{ONDIO_PAD}{\ButtonMenu}
23 & Start new game\\
24 \opt{IRIVER_H100_PAD,IRIVER_H300_PAD}{\ButtonMode}
25 \opt{RECORDER_PAD,IPOD_4G_PAD,IPOD_3G_PAD}{\ButtonPlay}
26 \opt{ONDIO_PAD,IAUDIO_X5_PAD}{\ButtonDown}
27 \opt{IRIVER_H10_PAD}{\ButtonRight}
28 \opt{SANSA_E200_PAD}{\ButtonRec}
29 \opt{GIGABEAT_PAD}{\ButtonMenu}
30 & Resume saved game\\
31 \opt{IRIVER_H100_PAD,IRIVER_H300_PAD}{\ButtonSelect}
32 \opt{RECORDER_PAD,IAUDIO_X5_PAD,IPOD_4G_PAD,IPOD_3G_PAD,GIGABEAT_PAD}{\ButtonRight}
33 \opt{ONDIO_PAD,SANSA_E200_PAD}{\ButtonUp}
34 \opt{IRIVER_H10_PAD}{\ButtonLeft}
35 & Show high scores\\
36 \opt{RECORDER_PAD,ONDIO_PAD,IRIVER_H100_PAD,IRIVER_H300_PAD}{\ButtonOff}
37 \opt{IPOD_4G_PAD,IPOD_3G_PAD}{\ButtonMenu}
38 \opt{IAUDIO_X5_PAD,IRIVER_H10_PAD,SANSA_E200_PAD}{\ButtonPower}
39 \opt{GIGABEAT_PAD}{\ButtonA}
40 & Quit\\\hline
41 \multicolumn{2}{c}{\textbf{In game}}\\\hline
42 \ButtonLeft/\ButtonRight/\\
43 \opt{RECORDER_PAD,ONDIO_PAD,IRIVER_H100_PAD,IRIVER_H300_PAD,IAUDIO_X5_PAD,GIGABEAT_PAD}
44 {\ButtonUp/\ButtonDown}
45 \opt{IPOD_4G_PAD,IPOD_3G_PAD}{\ButtonScrollFwd/\ButtonScrollBack}
46 \opt{IRIVER_H10_PAD,SANSA_E200_PAD}{\ButtonScrollUp/\ButtonScrollDown}
47 & Enter betting amount\\
48 \opt{RECORDER_PAD}{\ButtonFOne}
49 \opt{IRIVER_H100_PAD,IRIVER_H300_PAD}{\ButtonOn}
50 \opt{IRIVER_H10_PAD}{\ButtonPlay}
51 \opt{IPOD_4G_PAD,IPOD_3G_PAD,IAUDIO_X5_PAD,SANSA_E200_PAD}{\ButtonSelect}
52 \opt{ONDIO_PAD}{\ButtonLeft}
53 \opt{GIGABEAT_PAD}{\ButtonVolUp}
54 & Hit (Draw new card)\\
55 \opt{RECORDER_PAD}{\ButtonFTwo}
56 \opt{IRIVER_H100_PAD,IRIVER_H300_PAD,IAUDIO_X5_PAD}{\ButtonRec}
57 \opt{IRIVER_H10_PAD}{\ButtonFF}
58 \opt{ONDIO_PAD,IPOD_4G_PAD,IPOD_3G_PAD,SANSA_E200_PAD}{\ButtonRight}
59 \opt{GIGABEAT_PAD}{\ButtonVolDown}
60 & Stay (End hand)\\
61 \opt{RECORDER_PAD}{\ButtonFThree}
62 \opt{IRIVER_H100_PAD,IRIVER_H300_PAD,GIGABEAT_PAD}{\ButtonSelect}
63 \opt{IAUDIO_X5_PAD}{\ButtonPlay}
64 \opt{IRIVER_H10_PAD}{\ButtonRew}
65 \opt{ONDIO_PAD}{\ButtonUp}
66 \opt{IPOD_4G_PAD,IPOD_3G_PAD,SANSA_E200_PAD}{\ButtonLeft}
67 & Double down\\
68 \opt{IRIVER_H100_PAD,IRIVER_H300_PAD}{\ButtonMode}
69 \opt{RECORDER_PAD,IPOD_4G_PAD,IPOD_3G_PAD}{\ButtonPlay}
70 \opt{ONDIO_PAD,IAUDIO_X5_PAD}{\ButtonDown}
71 \opt{IRIVER_H10_PAD}{\ButtonRight}
72 \opt{SANSA_E200_PAD}{\ButtonRec}
73 \opt{GIGABEAT_PAD}{\ButtonMenu}
74 & Save game\\
75 \opt{RECORDER_PAD,ONDIO_PAD,IRIVER_H100_PAD,IRIVER_H300_PAD}{\ButtonOff}
76 \opt{IPOD_4G_PAD,IPOD_3G_PAD}{\ButtonMenu}
77 \opt{IAUDIO_X5_PAD,IRIVER_H10_PAD,SANSA_E200_PAD}{\ButtonPower}
78 \opt{GIGABEAT_PAD}{\ButtonA}
79 & Return to menu or cancel\\\hline
80 \end{btnmap}
81\end{table}
diff --git a/manual/plugins/images/ss-blackjack-112x64x1.png b/manual/plugins/images/ss-blackjack-112x64x1.png
new file mode 100644
index 0000000000..851c80e7c6
--- /dev/null
+++ b/manual/plugins/images/ss-blackjack-112x64x1.png
Binary files differ
diff --git a/manual/plugins/images/ss-blackjack-128x128x16.png b/manual/plugins/images/ss-blackjack-128x128x16.png
new file mode 100644
index 0000000000..6fe59e22c3
--- /dev/null
+++ b/manual/plugins/images/ss-blackjack-128x128x16.png
Binary files differ
diff --git a/manual/plugins/images/ss-blackjack-138x110x2.png b/manual/plugins/images/ss-blackjack-138x110x2.png
new file mode 100644
index 0000000000..c1669b354e
--- /dev/null
+++ b/manual/plugins/images/ss-blackjack-138x110x2.png
Binary files differ
diff --git a/manual/plugins/images/ss-blackjack-160x128x16.png b/manual/plugins/images/ss-blackjack-160x128x16.png
new file mode 100644
index 0000000000..464b8f8114
--- /dev/null
+++ b/manual/plugins/images/ss-blackjack-160x128x16.png
Binary files differ
diff --git a/manual/plugins/images/ss-blackjack-160x128x2.png b/manual/plugins/images/ss-blackjack-160x128x2.png
new file mode 100644
index 0000000000..5a28aace39
--- /dev/null
+++ b/manual/plugins/images/ss-blackjack-160x128x2.png
Binary files differ
diff --git a/manual/plugins/images/ss-blackjack-176x132x16.png b/manual/plugins/images/ss-blackjack-176x132x16.png
new file mode 100644
index 0000000000..304373306f
--- /dev/null
+++ b/manual/plugins/images/ss-blackjack-176x132x16.png
Binary files differ
diff --git a/manual/plugins/images/ss-blackjack-176x220x16.png b/manual/plugins/images/ss-blackjack-176x220x16.png
new file mode 100644
index 0000000000..258e222dfa
--- /dev/null
+++ b/manual/plugins/images/ss-blackjack-176x220x16.png
Binary files differ
diff --git a/manual/plugins/images/ss-blackjack-220x176x16.png b/manual/plugins/images/ss-blackjack-220x176x16.png
new file mode 100644
index 0000000000..ea1237ae47
--- /dev/null
+++ b/manual/plugins/images/ss-blackjack-220x176x16.png
Binary files differ
diff --git a/manual/plugins/images/ss-blackjack-240x320x16.png b/manual/plugins/images/ss-blackjack-240x320x16.png
new file mode 100644
index 0000000000..7516ed9afc
--- /dev/null
+++ b/manual/plugins/images/ss-blackjack-240x320x16.png
Binary files differ
diff --git a/manual/plugins/images/ss-blackjack-320x240x16.png b/manual/plugins/images/ss-blackjack-320x240x16.png
new file mode 100644
index 0000000000..c26e4866b1
--- /dev/null
+++ b/manual/plugins/images/ss-blackjack-320x240x16.png
Binary files differ
diff --git a/manual/plugins/main.tex b/manual/plugins/main.tex
index a92c3e2a8c..2d10ffe81b 100644
--- a/manual/plugins/main.tex
+++ b/manual/plugins/main.tex
@@ -18,6 +18,8 @@ text files, chip8 games), or from the \setting{Open with} option on the
18 \opt{recorder,recorderv2fm,h1xx,h300,ipodcolor,ipodvideo,sansa} 18 \opt{recorder,recorderv2fm,h1xx,h300,ipodcolor,ipodvideo,sansa}
19 {and Rockboy in \reference{ref:Rockboy}}.} 19 {and Rockboy in \reference{ref:Rockboy}}.}
20 20
21\opt{HAVE_LCD_BITMAP}{\input{plugins/blackjack.tex}}
22
21\opt{HAVE_LCD_BITMAP}{\input{plugins/brickmania.tex}} 23\opt{HAVE_LCD_BITMAP}{\input{plugins/brickmania.tex}}
22 24
23\opt{HAVE_LCD_BITMAP}{\input{plugins/bubbles.tex}} 25\opt{HAVE_LCD_BITMAP}{\input{plugins/bubbles.tex}}