Update the french translation regarding the previous revision.
[kugel-rb.git] / apps / plugins / blackjack.c
blobf7cda90eb4dda199c388d1275523d2ae756da81d
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2006 Tom Ross
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
22 #include "plugin.h"
23 #include "pluginbitmaps/card_deck.h"
24 #include "pluginbitmaps/card_back.h"
25 #include "lib/display_text.h"
26 #include "lib/highscore.h"
27 #include "lib/playback_control.h"
31 /* save files */
32 #define SCORE_FILE PLUGIN_GAMES_DIR "/blackjack.score"
33 #define SAVE_FILE PLUGIN_GAMES_DIR "/blackjack.save"
34 #define NUM_SCORES 5
36 /* final game return status */
37 enum {
38 BJ_LOSE,
39 BJ_QUIT_WITHOUT_SAVING,
40 BJ_QUIT,
41 BJ_USB,
42 BJ_END,
45 #if CONFIG_KEYPAD == RECORDER_PAD
46 #define BJACK_SELECT_NAME "PLAY"
47 #define BJACK_STAY_NAME "F1"
48 #define BJACK_QUIT_NAME "OFF"
49 #define BJACK_DOUBLE_NAME "F2"
50 #define BJACK_SELECT BUTTON_PLAY
51 #define BJACK_QUIT BUTTON_OFF
52 #define BJACK_MAX (BUTTON_ON|BUTTON_UP)
53 #define BJACK_MIN (BUTTON_ON|BUTTON_DOWN)
54 #define BJACK_STAY BUTTON_F1
55 #define BJACK_DOUBLEDOWN BUTTON_F2
56 #define BJACK_UP BUTTON_UP
57 #define BJACK_DOWN BUTTON_DOWN
58 #define BJACK_RIGHT BUTTON_RIGHT
59 #define BJACK_LEFT BUTTON_LEFT
61 #elif CONFIG_KEYPAD == ONDIO_PAD
62 #define BJACK_SELECT_NAME "MENU"
63 #define BJACK_STAY_NAME "RIGHT"
64 #define BJACK_QUIT_NAME "OFF"
65 #define BJACK_DOUBLE_NAME "UP"
66 #define BJACK_SELECT BUTTON_MENU
67 #define BJACK_QUIT BUTTON_OFF
68 #define BJACK_STAY BUTTON_RIGHT
69 #define BJACK_DOUBLEDOWN BUTTON_UP
70 #define BJACK_UP BUTTON_UP
71 #define BJACK_DOWN BUTTON_DOWN
72 #define BJACK_RIGHT BUTTON_RIGHT
73 #define BJACK_LEFT BUTTON_LEFT
75 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
76 #define BJACK_SELECT_NAME "PLAY"
77 #define BJACK_STAY_NAME ">>|"
78 #define BJACK_QUIT_NAME "POWER"
79 #define BJACK_DOUBLE_NAME "|<<"
80 #define BJACK_SELECT BUTTON_PLAY
81 #define BJACK_QUIT BUTTON_POWER
82 #define BJACK_STAY BUTTON_FF
83 #define BJACK_DOUBLEDOWN BUTTON_REW
84 #define BJACK_UP BUTTON_SCROLL_UP
85 #define BJACK_DOWN BUTTON_SCROLL_DOWN
86 #define BJACK_RIGHT BUTTON_RIGHT
87 #define BJACK_LEFT BUTTON_LEFT
89 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
90 (CONFIG_KEYPAD == IRIVER_H300_PAD)
91 #define BJACK_SELECT_NAME "ON"
92 #define BJACK_STAY_NAME "REC"
93 #define BJACK_QUIT_NAME "OFF"
94 #define BJACK_DOUBLE_NAME "SELECT"
95 #define BJACK_SELECT BUTTON_ON
96 #define BJACK_QUIT BUTTON_OFF
97 #define BJACK_STAY BUTTON_REC
98 #define BJACK_DOUBLEDOWN BUTTON_SELECT
99 #define BJACK_UP BUTTON_UP
100 #define BJACK_DOWN BUTTON_DOWN
101 #define BJACK_RIGHT BUTTON_RIGHT
102 #define BJACK_LEFT BUTTON_LEFT
104 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
105 (CONFIG_KEYPAD == IPOD_3G_PAD) || \
106 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
107 #define BJACK_SELECT_NAME "SELECT"
108 #define BJACK_STAY_NAME "RIGHT"
109 #define BJACK_RESUME_NAME "PLAY"
110 #define BJACK_QUIT_NAME "MENU"
111 #define BJACK_DOUBLE_NAME "LEFT"
112 #define BJACK_SELECT BUTTON_SELECT
113 #define BJACK_QUIT BUTTON_MENU
114 #define BJACK_STAY BUTTON_RIGHT
115 #define BJACK_DOUBLEDOWN BUTTON_LEFT
116 #define BJACK_UP BUTTON_SCROLL_FWD
117 #define BJACK_DOWN BUTTON_SCROLL_BACK
118 #define BJACK_RIGHT BUTTON_RIGHT
119 #define BJACK_LEFT BUTTON_LEFT
121 #elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
122 #define BJACK_SELECT_NAME "SELECT"
123 #define BJACK_STAY_NAME "REC"
124 #define BJACK_QUIT_NAME "POWER"
125 #define BJACK_DOUBLE_NAME "PLAY"
126 #define BJACK_SELECT BUTTON_SELECT
127 #define BJACK_QUIT BUTTON_POWER
128 #define BJACK_MAX (BUTTON_PLAY|BUTTON_UP)
129 #define BJACK_MIN (BUTTON_PLAY|BUTTON_DOWN)
130 #define BJACK_STAY BUTTON_REC
131 #define BJACK_DOUBLEDOWN BUTTON_PLAY
132 #define BJACK_UP BUTTON_UP
133 #define BJACK_DOWN BUTTON_DOWN
134 #define BJACK_RIGHT BUTTON_RIGHT
135 #define BJACK_LEFT BUTTON_LEFT
137 #elif CONFIG_KEYPAD == IRIVER_IFP7XX_PAD
138 #define BJACK_SELECT_NAME "MODE"
139 #define BJACK_STAY_NAME "MODE"
140 #define BJACK_QUIT_NAME "PLAY"
141 #define BJACK_DOUBLE_NAME "SELECT"
142 #define BJACK_SELECT BUTTON_MODE
143 #define BJACK_QUIT BUTTON_PLAY
144 #define BJACK_MAX (BUTTON_EQ|BUTTON_UP)
145 #define BJACK_MIN (BUTTON_EQ|BUTTON_DOWN)
146 #define BJACK_STAY BUTTON_MODE
147 #define BJACK_DOUBLEDOWN BUTTON_SELECT
148 #define BJACK_UP BUTTON_UP
149 #define BJACK_DOWN BUTTON_DOWN
150 #define BJACK_RIGHT BUTTON_RIGHT
151 #define BJACK_LEFT BUTTON_LEFT
153 #elif CONFIG_KEYPAD == GIGABEAT_PAD
154 #define BJACK_SELECT_NAME "SELECT"
155 #define BJACK_STAY_NAME "VOL-"
156 #define BJACK_QUIT_NAME "POWER"
157 #define BJACK_DOUBLE_NAME "A"
158 #define BJACK_SELECT BUTTON_SELECT
159 #define BJACK_QUIT BUTTON_POWER
160 #define BJACK_MAX BUTTON_VOL_UP
161 #define BJACK_MIN BUTTON_VOL_DOWN
162 #define BJACK_STAY BUTTON_VOL_DOWN
163 #define BJACK_DOUBLEDOWN BUTTON_A
164 #define BJACK_UP BUTTON_UP
165 #define BJACK_DOWN BUTTON_DOWN
166 #define BJACK_RIGHT BUTTON_RIGHT
167 #define BJACK_LEFT BUTTON_LEFT
169 #elif CONFIG_KEYPAD == SANSA_E200_PAD
170 #define BJACK_SELECT_NAME "SELECT"
171 #define BJACK_STAY_NAME "RIGHT"
172 #define BJACK_QUIT_NAME "POWER"
173 #define BJACK_DOUBLE_NAME "LEFT"
174 #define BJACK_SELECT BUTTON_SELECT
175 #define BJACK_QUIT BUTTON_POWER
176 #define BJACK_MAX BUTTON_UP
177 #define BJACK_MIN BUTTON_DOWN
178 #define BJACK_STAY BUTTON_RIGHT
179 #define BJACK_DOUBLEDOWN BUTTON_LEFT
180 #define BJACK_UP BUTTON_SCROLL_FWD
181 #define BJACK_DOWN BUTTON_SCROLL_BACK
182 #define BJACK_RIGHT BUTTON_RIGHT
183 #define BJACK_LEFT BUTTON_LEFT
185 #elif CONFIG_KEYPAD == SANSA_FUZE_PAD
186 #define BJACK_SELECT_NAME "SELECT"
187 #define BJACK_STAY_NAME "RIGHT"
188 #define BJACK_QUIT_NAME "HOME"
189 #define BJACK_DOUBLE_NAME "LEFT"
190 #define BJACK_SELECT BUTTON_SELECT
191 #define BJACK_QUIT (BUTTON_HOME|BUTTON_REPEAT)
192 #define BJACK_MAX BUTTON_UP
193 #define BJACK_MIN BUTTON_DOWN
194 #define BJACK_STAY BUTTON_RIGHT
195 #define BJACK_DOUBLEDOWN BUTTON_LEFT
196 #define BJACK_UP BUTTON_SCROLL_FWD
197 #define BJACK_DOWN BUTTON_SCROLL_BACK
198 #define BJACK_RIGHT BUTTON_RIGHT
199 #define BJACK_LEFT BUTTON_LEFT
201 #elif CONFIG_KEYPAD == SANSA_C200_PAD
202 #define BJACK_SELECT_NAME "SELECT"
203 #define BJACK_STAY_NAME "RIGHT"
204 #define BJACK_QUIT_NAME "POWER"
205 #define BJACK_DOUBLE_NAME "LEFT"
206 #define BJACK_SELECT BUTTON_SELECT
207 #define BJACK_QUIT BUTTON_POWER
208 #define BJACK_MAX BUTTON_VOL_UP
209 #define BJACK_MIN BUTTON_VOL_DOWN
210 #define BJACK_STAY BUTTON_RIGHT
211 #define BJACK_DOUBLEDOWN BUTTON_LEFT
212 #define BJACK_UP BUTTON_UP
213 #define BJACK_DOWN BUTTON_DOWN
214 #define BJACK_RIGHT BUTTON_RIGHT
215 #define BJACK_LEFT BUTTON_LEFT
217 #elif CONFIG_KEYPAD == SANSA_CLIP_PAD
218 #define BJACK_SELECT_NAME "SELECT"
219 #define BJACK_STAY_NAME "RIGHT"
220 #define BJACK_QUIT_NAME "POWER"
221 #define BJACK_DOUBLE_NAME "LEFT"
222 #define BJACK_SELECT BUTTON_SELECT
223 #define BJACK_QUIT BUTTON_POWER
224 #define BJACK_MAX BUTTON_VOL_UP
225 #define BJACK_MIN BUTTON_VOL_DOWN
226 #define BJACK_STAY BUTTON_RIGHT
227 #define BJACK_DOUBLEDOWN BUTTON_LEFT
228 #define BJACK_UP BUTTON_UP
229 #define BJACK_DOWN BUTTON_DOWN
230 #define BJACK_RIGHT BUTTON_RIGHT
231 #define BJACK_LEFT BUTTON_LEFT
233 #elif CONFIG_KEYPAD == SANSA_M200_PAD
234 #define BJACK_SELECT_NAME "SELECT"
235 #define BJACK_STAY_NAME "RIGHT"
236 #define BJACK_QUIT_NAME "POWER"
237 #define BJACK_DOUBLE_NAME "LEFT"
238 #define BJACK_SELECT (BUTTON_SELECT | BUTTON_REL)
239 #define BJACK_QUIT BUTTON_POWER
240 #define BJACK_MAX BUTTON_VOL_UP
241 #define BJACK_MIN BUTTON_VOL_DOWN
242 #define BJACK_STAY BUTTON_RIGHT
243 #define BJACK_DOUBLEDOWN BUTTON_LEFT
244 #define BJACK_UP BUTTON_UP
245 #define BJACK_DOWN BUTTON_DOWN
246 #define BJACK_RIGHT BUTTON_RIGHT
247 #define BJACK_LEFT BUTTON_LEFT
249 #elif CONFIG_KEYPAD == TATUNG_TPJ1022_PAD
250 #define BJACK_SELECT_NAME "MAIN"
251 #define BJACK_STAY_NAME "MENU"
252 #define BJACK_QUIT_NAME "POWER"
253 #define BJACK_DOUBLE_NAME "DOWN"
254 #define BJACK_SELECT BUTTON_MAIN
255 #define BJACK_QUIT BUTTON_POWER
256 #define BJACK_MAX (BUTTON_REC|BUTTON_UP)
257 #define BJACK_MIN (BUTTON_REC|BUTTON_DOWN)
258 #define BJACK_STAY BUTTON_MENU
259 #define BJACK_DOUBLEDOWN BUTTON_DOWN
260 #define BJACK_UP BUTTON_UP
261 #define BJACK_DOWN BUTTON_DOWN
262 #define BJACK_RIGHT BUTTON_RIGHT
263 #define BJACK_LEFT BUTTON_LEFT
265 #elif CONFIG_KEYPAD == GIGABEAT_S_PAD
266 #define BJACK_SELECT_NAME "PLAY"
267 #define BJACK_STAY_NAME "VOL-"
268 #define BJACK_QUIT_NAME "BACK"
269 #define BJACK_DOUBLE_NAME "SELECT"
270 #define BJACK_SELECT BUTTON_PLAY
271 #define BJACK_QUIT BUTTON_BACK
272 #define BJACK_MAX BUTTON_VOL_UP
273 #define BJACK_MIN BUTTON_VOL_DOWN
274 #define BJACK_STAY BUTTON_VOL_DOWN
275 #define BJACK_DOUBLEDOWN BUTTON_SELECT
276 #define BJACK_UP BUTTON_UP
277 #define BJACK_DOWN BUTTON_DOWN
278 #define BJACK_RIGHT BUTTON_RIGHT
279 #define BJACK_LEFT BUTTON_LEFT
281 #elif CONFIG_KEYPAD == MROBE100_PAD
282 #define BJACK_SELECT_NAME "SELECT"
283 #define BJACK_STAY_NAME "DISPLAY"
284 #define BJACK_QUIT_NAME "POWER"
285 #define BJACK_DOUBLE_NAME "DOWN"
286 #define BJACK_SELECT BUTTON_SELECT
287 #define BJACK_QUIT BUTTON_POWER
288 #define BJACK_MAX BUTTON_MENU
289 #define BJACK_MIN BUTTON_DISPLAY
290 #define BJACK_STAY BUTTON_DISPLAY
291 #define BJACK_DOUBLEDOWN BUTTON_DOWN
292 #define BJACK_UP BUTTON_UP
293 #define BJACK_DOWN BUTTON_DOWN
294 #define BJACK_RIGHT BUTTON_RIGHT
295 #define BJACK_LEFT BUTTON_LEFT
297 #elif CONFIG_KEYPAD == IAUDIO_M3_PAD
298 #define BJACK_SELECT_NAME "RC","PLAY"
299 #define BJACK_STAY_NAME "RC", ">>|"
300 #define BJACK_QUIT_NAME "RC_REC"
301 #define BJACK_DOUBLE_NAME "RC_REW"
302 #define BJACK_SELECT BUTTON_RC_PLAY
303 #define BJACK_QUIT BUTTON_RC_REC
304 #define BJACK_STAY BUTTON_RC_FF
305 #define BJACK_DOUBLEDOWN BUTTON_RC_REW
306 #define BJACK_UP BUTTON_RC_VOL_UP
307 #define BJACK_DOWN BUTTON_RC_VOL_DOWN
308 #define BJACK_RIGHT BUTTON_RC_FF
309 #define BJACK_LEFT BUTTON_RC_REW
311 #elif CONFIG_KEYPAD == COWON_D2_PAD
312 #define BJACK_QUIT_NAME "POWER"
313 #define BJACK_DOUBLE_NAME "-"
314 #define BJACK_QUIT BUTTON_POWER
315 #define BJACK_DOUBLEDOWN BUTTON_MINUS
317 #elif CONFIG_KEYPAD == CREATIVEZVM_PAD
318 #define BJACK_SELECT_NAME "SELECT"
319 #define BJACK_STAY_NAME "PLAY"
320 #define BJACK_QUIT_NAME "POWER"
321 #define BJACK_DOUBLE_NAME "CUSTOM"
322 #define BJACK_SELECT BUTTON_SELECT
323 #define BJACK_QUIT BUTTON_POWER
324 #define BJACK_STAY BUTTON_PLAY
325 #define BJACK_MAX (BUTTON_CUSTOM|BUTTON_UP)
326 #define BJACK_MIN (BUTTON_CUSTOM|BUTTON_DOWN)
327 #define BJACK_DOUBLEDOWN BUTTON_CUSTOM
328 #define BJACK_UP BUTTON_UP
329 #define BJACK_DOWN BUTTON_DOWN
330 #define BJACK_RIGHT BUTTON_RIGHT
331 #define BJACK_LEFT BUTTON_LEFT
333 #elif CONFIG_KEYPAD == PHILIPS_HDD1630_PAD
334 #define BJACK_SELECT_NAME "SELECT"
335 #define BJACK_STAY_NAME "VOL-"
336 #define BJACK_QUIT_NAME "POWER"
337 #define BJACK_DOUBLE_NAME "MENU"
338 #define BJACK_SELECT BUTTON_SELECT
339 #define BJACK_QUIT BUTTON_POWER
340 #define BJACK_MAX BUTTON_VOL_UP
341 #define BJACK_MIN BUTTON_VOL_DOWN
342 #define BJACK_STAY BUTTON_VOL_DOWN
343 #define BJACK_DOUBLEDOWN BUTTON_MENU
344 #define BJACK_UP BUTTON_UP
345 #define BJACK_DOWN BUTTON_DOWN
346 #define BJACK_RIGHT BUTTON_RIGHT
347 #define BJACK_LEFT BUTTON_LEFT
349 #elif CONFIG_KEYPAD == PHILIPS_HDD6330_PAD
350 #define BJACK_SELECT_NAME "PLAY"
351 #define BJACK_STAY_NAME "VOL-"
352 #define BJACK_QUIT_NAME "POWER"
353 #define BJACK_DOUBLE_NAME "MENU"
354 #define BJACK_SELECT BUTTON_PLAY
355 #define BJACK_QUIT BUTTON_POWER
356 #define BJACK_MAX BUTTON_VOL_UP
357 #define BJACK_MIN BUTTON_VOL_DOWN
358 #define BJACK_STAY BUTTON_VOL_DOWN
359 #define BJACK_DOUBLEDOWN BUTTON_MENU
360 #define BJACK_UP BUTTON_UP
361 #define BJACK_DOWN BUTTON_DOWN
362 #define BJACK_RIGHT BUTTON_RIGHT
363 #define BJACK_LEFT BUTTON_LEFT
365 #elif CONFIG_KEYPAD == PHILIPS_SA9200_PAD
366 #define BJACK_SELECT_NAME "MENU"
367 #define BJACK_STAY_NAME "VOL-"
368 #define BJACK_QUIT_NAME "POWER"
369 #define BJACK_DOUBLE_NAME "PLAY"
370 #define BJACK_SELECT BUTTON_MENU
371 #define BJACK_QUIT BUTTON_POWER
372 #define BJACK_MAX BUTTON_VOL_UP
373 #define BJACK_MIN BUTTON_VOL_DOWN
374 #define BJACK_STAY BUTTON_VOL_DOWN
375 #define BJACK_DOUBLEDOWN BUTTON_PLAY
376 #define BJACK_UP BUTTON_UP
377 #define BJACK_DOWN BUTTON_DOWN
378 #define BJACK_RIGHT BUTTON_NEXT
379 #define BJACK_LEFT BUTTON_PREV
381 #elif CONFIG_KEYPAD == ONDAVX747_PAD
382 #define BJACK_QUIT_NAME "POWER"
383 #define BJACK_DOUBLE_NAME "Vol-"
384 #define BJACK_QUIT BUTTON_POWER
385 #define BJACK_DOUBLEDOWN BUTTON_VOL_DOWN
387 #elif CONFIG_KEYPAD == ONDAVX777_PAD
388 #define BJACK_QUIT_NAME "POWER"
389 #define BJACK_QUIT BUTTON_POWER
391 #elif CONFIG_KEYPAD == MROBE500_PAD
392 #define BJACK_QUIT_NAME "POWER"
393 #define BJACK_QUIT BUTTON_POWER
395 #elif CONFIG_KEYPAD == SAMSUNG_YH_PAD
396 #define BJACK_SELECT_NAME "PLAY"
397 #define BJACK_STAY_NAME "RECORD"
398 #define BJACK_QUIT_NAME "REW"
399 #define BJACK_DOUBLE_NAME "FFWD"
400 #define BJACK_SELECT BUTTON_PLAY
401 #define BJACK_QUIT BUTTON_REW
402 #define BJACK_STAY BUTTON_REC
403 #define BJACK_DOUBLEDOWN BUTTON_FFWD
404 #define BJACK_UP BUTTON_UP
405 #define BJACK_DOWN BUTTON_DOWN
406 #define BJACK_RIGHT BUTTON_RIGHT
407 #define BJACK_LEFT BUTTON_LEFT
409 #elif CONFIG_KEYPAD == PBELL_VIBE500_PAD
410 #define BJACK_SELECT_NAME "OK"
411 #define BJACK_STAY_NAME "CANCEL"
412 #define BJACK_QUIT_NAME "REC"
413 #define BJACK_DOUBLE_NAME "MENU"
414 #define BJACK_SELECT BUTTON_OK
415 #define BJACK_QUIT BUTTON_REC
416 #define BJACK_STAY BUTTON_CANCEL
417 #define BJACK_DOUBLEDOWN BUTTON_MENU
418 #define BJACK_UP BUTTON_UP
419 #define BJACK_DOWN BUTTON_DOWN
420 #define BJACK_RIGHT BUTTON_NEXT
421 #define BJACK_LEFT BUTTON_PREV
423 #elif CONFIG_KEYPAD == MPIO_HD200_PAD
424 #define BJACK_SELECT_NAME "FUNC"
425 #define BJACK_STAY_NAME "VOL +"
426 #define BJACK_RESUME_NAME "PLAY"
427 #define BJACK_QUIT_NAME "REC+PLAY"
428 #define BJACK_DOUBLE_NAME "VOL -"
429 #define BJACK_SELECT BUTTON_FUNC
430 #define BJACK_QUIT (BUTTON_REC|BUTTON_PLAY)
431 #define BJACK_STAY BUTTON_VOL_UP
432 #define BJACK_DOUBLEDOWN BUTTON_VOL_DOWN
433 #define BJACK_UP BUTTON_REW
434 #define BJACK_DOWN BUTTON_FF
435 #define BJACK_RIGHT BUTTON_VOL_UP
436 #define BJACK_LEFT BUTTON_VOL_DOWN
438 #else
439 #error No keymap defined!
440 #endif
442 #ifdef HAVE_TOUCHSCREEN
443 #ifndef BJACK_DOUBLEDOWN
444 #define BJACK_DOUBLEDOWN BUTTON_MIDLEFT
445 #define BJACK_DOUBLE_NAME "BUTTON_MIDLEFT"
446 #endif
447 #ifndef BJACK_SELECT
448 #define BJACK_SELECT BUTTON_CENTER
449 #define BJACK_SELECT_NAME "BUTTON_CENTER"
450 #endif
451 #ifndef BJACK_MAX
452 #define BJACK_MAX BUTTON_TOPRIGHT
453 #endif
454 #ifndef BJACK_MIN
455 #define BJACK_MIN BUTTON_TOPLEFT
456 #endif
457 #ifndef BJACK_STAY
458 #define BJACK_STAY BUTTON_BOTTOMLEFT
459 #define BJACK_STAY_NAME "BUTTON_BOTTOMLEFT"
460 #endif
461 #ifndef BJACK_UP
462 #define BJACK_UP BUTTON_TOPMIDDLE
463 #endif
464 #ifndef BJACK_DOWN
465 #define BJACK_DOWN BUTTON_BOTTOMMIDDLE
466 #endif
467 #ifndef BJACK_RIGHT
468 #define BJACK_RIGHT BUTTON_MIDRIGHT
469 #endif
470 #ifndef BJACK_LEFT
471 #define BJACK_LEFT BUTTON_MIDLEFT
472 #endif
474 #endif
476 #ifdef HAVE_LCD_COLOR
477 #define BG_COLOR LCD_RGBPACK(0,157,0)
478 #define FG_COLOR LCD_WHITE
479 #elif LCD_DEPTH > 1
480 #define BG_COLOR LCD_WHITE
481 #define FG_COLOR LCD_BLACK
482 #endif
484 #define CARD_WIDTH BMPWIDTH_card_back
485 #define CARD_HEIGHT BMPHEIGHT_card_back
487 /* This is the max amount of cards onscreen before condensing */
488 #define MAX_CARDS LCD_WIDTH/(CARD_WIDTH+4)
490 extern const fb_data card_deck[];
491 extern const fb_data card_back[];
493 #define NEXT_CARD bj->player_cards[done][bj->num_player_cards[done]]
495 /* dealer and player card positions */
496 unsigned int dealer_x, dealer_y, player_x, player_y;
498 typedef struct card {
499 unsigned int value; /* Card's value in Blackjack */
500 unsigned int num; /* Value on card face 0-12 (0=Ace, 1=2, 11=Q) */
501 unsigned int suit; /* 0:Spades, 1:Hearts, 2: Clubs; 3: Diamonds */
502 bool is_soft_ace;
503 } card;
505 typedef struct game_context {
506 struct card player_cards[2][22]; /* 22 Cards means the deal was all aces */
507 struct card dealer_cards[22]; /* That is the worst-case scenario */
508 unsigned int player_total;
509 unsigned int dealer_total;
510 signed int player_money;
511 unsigned int num_player_cards[2];
512 unsigned int num_dealer_cards;
513 unsigned int current_bet;
514 unsigned int split_status; /* 0 = split hasn't been asked, *
515 * 1 = split did not occur *
516 * 2 = split occurred *
517 * 3 = split occurred and 1st hand done */
518 bool is_blackjack;
519 bool end_hand;
520 bool asked_insurance;
521 } game_context;
523 static bool resume = false;
524 static bool resume_file = false;
525 static struct highscore highscores[NUM_SCORES];
527 /*****************************************************************************
528 * blackjack_init() initializes blackjack data structures.
529 ******************************************************************************/
530 static void blackjack_init(struct game_context* bj) {
531 /* seed the rand generator */
532 rb->srand(*rb->current_tick);
534 /* reset card positions */
535 dealer_x = 4;
536 dealer_y = LCD_HEIGHT/4 - CARD_HEIGHT/2;
537 player_x = 4;
538 player_y = LCD_HEIGHT - LCD_HEIGHT/4 - CARD_HEIGHT/2;
540 /* check for resumed game */
541 if(resume) return;
543 /* reset scoring */
544 bj->player_total = 0;
545 bj->dealer_total = 0;
546 bj->num_player_cards[0] = 2;
547 bj->num_player_cards[1] = 0;
548 bj->num_dealer_cards = 2;
549 bj->end_hand = false;
550 bj->split_status = 0;
551 bj->is_blackjack = false;
552 bj->asked_insurance = false;
555 /*****************************************************************************
556 * blackjack_drawtable() draws the table and some text.
557 ******************************************************************************/
558 static void blackjack_drawtable(struct game_context* bj) {
559 unsigned int w, h, y_loc;
560 char str[10];
562 #if LCD_HEIGHT <= 64
563 rb->lcd_getstringsize("Bet", &w, &h);
564 rb->lcd_putsxy(LCD_WIDTH - w, 2*h + 1, "Bet");
565 rb->snprintf(str, 9, "$%d", bj->current_bet);
566 rb->lcd_getstringsize(str, &w, &h);
567 rb->lcd_putsxy(LCD_WIDTH - w, 3*h + 1, str);
568 y_loc = LCD_HEIGHT/2;
569 #else
570 rb->lcd_getstringsize("Bet", &w, &h);
571 rb->lcd_putsxy(LCD_WIDTH - w, 5*h / 2, "Bet");
572 rb->snprintf(str, 9, "$%d", bj->current_bet);
573 rb->lcd_getstringsize(str, &w, &h);
574 rb->lcd_putsxy(LCD_WIDTH - w, 7*h / 2, str);
575 rb->lcd_hline(0, LCD_WIDTH, LCD_HEIGHT/2);
576 y_loc = LCD_HEIGHT/2 + h;
577 #endif
579 rb->lcd_putsxy(0,0, "Dealer");
580 rb->lcd_getstringsize("Player", &w, &h);
581 rb->lcd_putsxy(0, y_loc, "Player");
582 rb->lcd_getstringsize("Total", &w, &h);
583 rb->lcd_putsxy(LCD_WIDTH - w, y_loc, "Total");
584 rb->lcd_getstringsize("Money", &w, &h);
585 rb->lcd_putsxy(LCD_WIDTH - w, 0, "Money");
586 rb->snprintf(str, 9, "$%d", bj->player_money - bj->current_bet);
587 rb->lcd_getstringsize(str, &w, &h);
588 rb->lcd_putsxy(LCD_WIDTH - w, h + 1, str);
589 rb->snprintf(str, 3, "%d", bj->player_total);
590 rb->lcd_getstringsize(str, &w, &h);
591 rb->lcd_putsxy(LCD_WIDTH - w, y_loc + h, str);
594 /*****************************************************************************
595 * find_value() is passed a card and returns its blackjack value.
596 ******************************************************************************/
597 static unsigned int find_value(unsigned int number) {
598 unsigned int thisValue;
599 if (number == 0)
600 thisValue = 11; /* Aces get a value of 11 at first */
601 else if (number < 10)
602 thisValue = number + 1;
603 else
604 thisValue = 10; /* Anything 10 or higher gets a value of 10 */
606 return thisValue;
609 /*****************************************************************************
610 * draw_card() draws a card to the screen.
611 ******************************************************************************/
612 static void draw_card(struct card temp_card, bool shown,
613 unsigned int x, unsigned int y) {
614 if(shown)
615 rb->lcd_bitmap_part(card_deck, CARD_WIDTH*temp_card.num,
616 CARD_HEIGHT*temp_card.suit,
617 STRIDE( SCREEN_MAIN, BMPWIDTH_card_deck,
618 BMPHEIGHT_card_deck),
619 x+1, y+1, CARD_WIDTH, CARD_HEIGHT);
620 else
621 rb->lcd_bitmap(card_back, x+1, y+1,CARD_WIDTH, CARD_HEIGHT);
622 #if LCD_DEPTH > 1
623 rb->lcd_set_foreground(LCD_BLACK);
624 #endif
626 /* Print outlines */
627 #if CARD_WIDTH >= 26
628 rb->lcd_hline(x+2, x+CARD_WIDTH-1, y);
629 rb->lcd_hline(x+2, x+CARD_WIDTH-1, y+CARD_HEIGHT+1);
630 rb->lcd_vline(x, y+2, y+CARD_HEIGHT-3);
631 rb->lcd_vline(x+CARD_WIDTH+1, y+2, y+CARD_HEIGHT-1);
632 rb->lcd_drawpixel(x+1, y+1);
633 rb->lcd_drawpixel(x+1, y+CARD_HEIGHT);
634 rb->lcd_drawpixel(x+CARD_WIDTH, y+1);
635 rb->lcd_drawpixel(x+CARD_WIDTH, y+CARD_HEIGHT);
636 #else
637 rb->lcd_hline(x+1, x+CARD_WIDTH, y);
638 rb->lcd_hline(x+1, x+CARD_WIDTH, y+CARD_HEIGHT+1);
639 rb->lcd_vline(x, y+1, y+CARD_HEIGHT);
640 rb->lcd_vline(x+CARD_WIDTH+1, y+1, y+CARD_HEIGHT);
641 #endif
643 #if LCD_DEPTH > 1
644 rb->lcd_set_foreground(FG_COLOR);
645 #endif
648 /*****************************************************************************
649 * new_card() initializes a new card and gives it values.
650 ******************************************************************************/
651 static struct card new_card(void) {
652 struct card new_card;
653 new_card.suit = rb->rand()%4; /* Random number 0-3 */
654 new_card.num = rb->rand()%13; /* Random number 0-12 */
655 new_card.value = find_value(new_card.num);
656 new_card.is_soft_ace = (new_card.num == 0);
657 return new_card;
660 /*****************************************************************************
661 * deal_init_card() deals and draws to the screen the player's and dealer's
662 * initial cards.
663 ******************************************************************************/
664 static void deal_init_cards(struct game_context* bj) {
665 bj->dealer_cards[0] = new_card();
666 bj->dealer_total += bj->dealer_cards[0].value;
668 draw_card(bj->dealer_cards[0], false, dealer_x, dealer_y);
670 bj->dealer_cards[1] = new_card();
671 bj->dealer_total += bj->dealer_cards[1].value;
672 draw_card(bj->dealer_cards[1], true, dealer_x + CARD_WIDTH + 4, dealer_y);
674 bj->player_cards[0][0] = new_card();
675 bj->player_total += bj->player_cards[0][0].value;
676 draw_card(bj->player_cards[0][0], true, player_x, player_y);
677 player_x += CARD_WIDTH + 4;
679 bj->player_cards[0][1] = new_card();
680 bj->player_total += bj->player_cards[0][1].value;
681 draw_card(bj->player_cards[0][1], true, player_x, player_y);
682 player_x += CARD_WIDTH + 4;
685 /*****************************************************************************
686 * redraw_board() redraws all the cards and the board
687 ******************************************************************************/
688 static void redraw_board(struct game_context* bj) {
689 unsigned int i, n, upper_bound;
690 rb->lcd_clear_display();
692 blackjack_drawtable(bj);
693 player_x = 4;
694 dealer_x = 4;
695 upper_bound = bj->split_status > 1 ? 2 : 1;
697 for (i = 0; i < bj->num_dealer_cards; i++) {
698 if (!bj->end_hand) {
699 draw_card(bj->dealer_cards[0], false, dealer_x, dealer_y);
701 /* increment i so the dealer's first card isn't displayed */
702 i++;
703 dealer_x += CARD_WIDTH + 4;
705 draw_card(bj->dealer_cards[i], true, dealer_x, dealer_y);
707 if (bj->num_dealer_cards > MAX_CARDS-1)
708 dealer_x += 10;
709 else
710 dealer_x += CARD_WIDTH + 4;
713 for (n = 0; n < upper_bound; n++) {
714 for (i = 0; i < bj->num_player_cards[n]; i++) {
715 draw_card(bj->player_cards[n][i], true, player_x, player_y);
716 if (bj->split_status>1 || bj->num_player_cards[n]>MAX_CARDS)
717 player_x += 10;
718 else
719 player_x += CARD_WIDTH + 4;
721 if (bj->split_status > 1)
722 player_x = LCD_WIDTH/2 + 4;
726 /*****************************************************************************
727 * update_total updates the player's total
728 ******************************************************************************/
729 static void update_total(struct game_context* bj) {
730 char total[3];
731 unsigned int w, h;
732 rb->snprintf(total, 3, "%d", bj->player_total);
733 rb->lcd_getstringsize(total, &w, &h);
734 #if LCD_HEIGHT > 64
735 h *= 2;
736 #endif
737 rb->lcd_putsxy(LCD_WIDTH - w, LCD_HEIGHT/2 + h, total);
738 rb->lcd_update_rect(LCD_WIDTH - w, LCD_HEIGHT/2 + h, w, h);
742 /*****************************************************************************
743 * check_for_aces() is passed an array of cards and returns where an ace is
744 * located. Otherwise, returns -1.
745 ******************************************************************************/
746 static signed int check_for_aces(struct card temp_cards[], unsigned int size) {
747 unsigned int i;
748 for(i = 0; i < size; i++) {
749 if (temp_cards[i].is_soft_ace)
750 return i;
752 return -1;
755 /*****************************************************************************
756 * check_totals() compares player and dealer totals.
757 * 0: bust 1: loss, 2: push, 3: win, 4: blackjack, 5: something's not right...
758 ******************************************************************************/
759 static unsigned int check_totals(struct game_context* bj) {
760 unsigned int temp;
761 if (bj->player_total > 21)
762 temp = 0;
763 else if (bj->player_total == 21 && bj->is_blackjack) {
764 if (bj->dealer_total == 21 && bj->num_dealer_cards == 2)
765 temp = 2;
766 else
767 temp = 4;
769 else if (bj->player_total == bj->dealer_total)
770 temp = 2;
771 else if (bj->dealer_total > 21 && bj->player_total < 22)
772 temp = 3;
773 else if (bj->dealer_total > bj->player_total)
774 temp = 1;
775 else if (bj->player_total > bj->dealer_total)
776 temp = 3;
777 else
778 temp = 5;
780 return temp;
783 /*****************************************************************************
784 * finish_dealer() draws cards for the dealer until he has 17 or more.
785 ******************************************************************************/
786 static void finish_dealer(struct game_context* bj) {
787 signed int temp = 0;
789 if (bj->dealer_total > 16 && bj->dealer_total < 22)
790 return;
792 while (bj->dealer_total < 17) {
793 bj->dealer_cards[bj->num_dealer_cards] = new_card();
794 bj->dealer_total += bj->dealer_cards[bj->num_dealer_cards].value;
795 bj->num_dealer_cards++;
798 while (bj->dealer_total > 21) {
799 temp = check_for_aces(bj->dealer_cards, bj->num_dealer_cards);
800 if(temp != -1) {
801 bj->dealer_cards[temp].is_soft_ace = false;
802 bj->dealer_total -= 10;
804 else
805 return;
809 /*****************************************************************************
810 * finish_game() completes the game once player's turn is over.
811 ******************************************************************************/
812 static void finish_game(struct game_context* bj) {
813 unsigned int rValue, w, h;
814 char str[19];
816 do {
817 finish_dealer(bj);
818 } while (bj->dealer_total < 17);
820 redraw_board(bj);
821 rValue = check_totals(bj);
823 if (rValue == 0) {
824 rb->snprintf(str, sizeof(str), " Bust! ");
825 bj->player_money -= bj->current_bet;
827 else if (rValue == 1) {
828 rb->snprintf(str, sizeof(str), " Sorry, you lost. ");
829 bj->player_money -= bj->current_bet;
831 else if (rValue == 2) {
832 rb->snprintf(str, sizeof(str), " Push ");
834 else if (rValue == 3) {
835 rb->snprintf(str, sizeof(str), " You won! ");
836 bj->player_money+= bj->current_bet;
838 else {
839 rb->snprintf(str, sizeof(str), " Blackjack! ");
840 bj->player_money += bj->current_bet * 3 / 2;
842 rb->lcd_getstringsize(str, &w, &h);
844 #if LCD_HEIGHT <= 64
845 rb->lcd_set_drawmode(DRMODE_BG+DRMODE_INVERSEVID);
846 rb->lcd_fillrect(0, LCD_HEIGHT/2, LCD_WIDTH, LCD_HEIGHT/2);
847 rb->lcd_set_drawmode(DRMODE_SOLID);
848 rb->lcd_putsxy(LCD_WIDTH/2 - w/2, LCD_HEIGHT/2 + h, str);
849 rb->snprintf(str, 12, "You have %d", bj->player_total);
850 rb->lcd_getstringsize(str, &w, &h);
851 rb->lcd_putsxy(LCD_WIDTH/2 - w/2, LCD_HEIGHT/2, str);
852 #else
853 rb->lcd_putsxy(LCD_WIDTH/2 - w/2, LCD_HEIGHT/2 - h/2, str);
854 #endif
855 rb->lcd_update();
858 /*****************************************************************************
859 * blackjack_loadgame() loads the saved game and returns load success.
860 ******************************************************************************/
861 static bool blackjack_loadgame(struct game_context* bj) {
862 signed int fd;
863 bool loaded = false;
865 /* open game file */
866 fd = rb->open(SAVE_FILE, O_RDONLY);
867 if(fd < 0) return false;
869 /* read in saved game */
870 if(rb->read(fd, bj, sizeof(struct game_context))
871 == (long)sizeof(struct game_context))
873 loaded = true;
876 rb->close(fd);
878 return loaded;
881 /*****************************************************************************
882 * blackjack_savegame() saves the current game state.
883 ******************************************************************************/
884 static void blackjack_savegame(struct game_context* bj) {
885 int fd;
887 if(!resume)
888 return;
889 /* write out the game state to the save file */
890 fd = rb->open(SAVE_FILE, O_WRONLY|O_CREAT, 0666);
891 if(fd < 0)
892 return;
893 rb->write(fd, bj, sizeof(struct game_context));
894 rb->close(fd);
897 /*****************************************************************************
898 * blackjack_get_yes_no() gets a yes/no answer from the user
899 ******************************************************************************/
900 static unsigned int blackjack_get_yes_no(char message[20]) {
901 int button;
902 unsigned int w, h, b, choice = 0;
903 bool breakout = false;
904 char message_yes[24], message_no[24];
906 rb->strcpy(message_yes, message);
907 rb->strcpy(message_no, message);
908 rb->strcat(message_yes, " Yes");
909 rb->strcat(message_no, " No");
910 rb->lcd_getstringsize(message_yes, &w, &h);
911 const char *stg[] = {message_yes, message_no};
913 #if LCD_HEIGHT <= 64
914 b = 2*h+1;
915 #else
916 b = h-1;
917 #endif
919 #ifdef HAVE_LCD_COLOR
920 rb->lcd_fillrect(LCD_WIDTH/2 - w/2, LCD_HEIGHT/2 + b, w+1, h+3);
921 rb->lcd_set_foreground(LCD_BLACK);
922 rb->lcd_set_background(LCD_WHITE);
923 #else
924 rb->lcd_set_drawmode(DRMODE_BG+DRMODE_INVERSEVID);
925 rb->lcd_fillrect(LCD_WIDTH/2 - w/2, LCD_HEIGHT/2 + b, w+1, h+3);
926 rb->lcd_set_drawmode(DRMODE_SOLID);
927 #endif
928 rb->lcd_drawrect(LCD_WIDTH/2 - w/2 - 1, LCD_HEIGHT/2 + b - 1, w+3, h+4);
930 while(!breakout) {
931 rb->lcd_putsxy(LCD_WIDTH/2 - w/2, LCD_HEIGHT/2 + b +1, stg[choice]);
932 rb->lcd_update_rect(LCD_WIDTH/2 - w/2 - 1, LCD_HEIGHT/2 + b -1,
933 w+3, h+4);
934 button = rb->button_get(true);
936 switch(button) {
937 case BJACK_LEFT:
938 case (BJACK_LEFT|BUTTON_REPEAT):
939 case BJACK_RIGHT:
940 case (BJACK_RIGHT|BUTTON_REPEAT):
941 choice ^= 1;
942 break;
943 case BJACK_SELECT: breakout = true;
944 break;
945 case BJACK_QUIT: breakout = true;
946 choice = 1;
947 break;
951 #if LCD_DEPTH > 1
952 rb->lcd_set_foreground(FG_COLOR);
953 rb->lcd_set_background(BG_COLOR);
954 #endif
955 return choice;
958 /*****************************************************************************
959 * blackjack_get_amount() gets an amount from the player to be used
960 ******************************************************************************/
961 static signed int blackjack_get_amount(char message[20], signed int lower_limit,
962 signed int upper_limit,
963 signed int start) {
964 int button;
965 bool breakout = false, changed = false;
966 unsigned int w, h;
967 signed int amount;
969 rb->lcd_getstringsize("A", &w, &h); /* find the size of one character */
971 if (start > upper_limit)
972 amount = upper_limit;
973 else if (start < lower_limit)
974 amount = lower_limit;
975 else
976 amount = start;
978 #if LCD_DEPTH > 1
979 rb->lcd_set_background(LCD_WHITE);
980 rb->lcd_set_foreground(LCD_BLACK);
981 #endif
983 #if LCD_HEIGHT <= 64
984 rb->lcd_clear_display();
985 rb->lcd_puts(0, 1, message);
986 rb->lcd_putsf(0, 2, "$%d", amount);
987 rb->lcd_puts(0, 3, "RIGHT: +1");
988 rb->lcd_puts(0, 4, "LEFT: -1");
989 rb->lcd_puts(0, 5, "UP: +10");
990 rb->lcd_puts(0, 6, "DOWN: -10");
991 rb->lcd_update();
992 #else
993 rb->lcd_set_drawmode(DRMODE_BG+DRMODE_INVERSEVID);
994 rb->lcd_fillrect(LCD_WIDTH/2 - 9*w - 1, LCD_HEIGHT/2 - 4*h - 3,
995 37*w / 2, 8*h -3);
996 rb->lcd_set_drawmode(DRMODE_SOLID);
997 rb->lcd_drawrect(LCD_WIDTH/2 - 9*w - 1, LCD_HEIGHT/2 - 4*h - 3,
998 37*w / 2, 8*h -3);
999 rb->lcd_putsxy(LCD_WIDTH/2 - 9*w, LCD_HEIGHT/2 - 4*h - 1, message);
1000 rb->lcd_putsxyf(LCD_WIDTH/2 - 9*w, LCD_HEIGHT/2 - 3*h, "$%d", amount);
1001 #if (CONFIG_KEYPAD == IPOD_4G_PAD) || \
1002 (CONFIG_KEYPAD == IPOD_3G_PAD) || \
1003 (CONFIG_KEYPAD == IPOD_1G2G_PAD) || \
1004 (CONFIG_KEYPAD == SANSA_E200_PAD) || \
1005 (CONFIG_KEYPAD == SANSA_FUZE_PAD)
1006 rb->lcd_putsxy(LCD_WIDTH/2 - 9*w, LCD_HEIGHT/2 - h-2, " >>|: +1");
1007 rb->lcd_putsxy(LCD_WIDTH/2 - 9*w, LCD_HEIGHT/2 - 1, " |<<: -1");
1008 rb->lcd_putsxy(LCD_WIDTH/2 - 9*w, LCD_HEIGHT/2 + h, "SCROLL+: +10");
1009 rb->lcd_putsxy(LCD_WIDTH/2 - 9*w, LCD_HEIGHT/2 + 2*h + 1, "SCROLL-: -10");
1010 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
1011 rb->lcd_putsxy(LCD_WIDTH/2 - 9*w, LCD_HEIGHT/2 - h-2, "RIGHT: +1");
1012 rb->lcd_putsxy(LCD_WIDTH/2 - 9*w, LCD_HEIGHT/2 - 1, "LEFT: -1");
1013 rb->lcd_putsxy(LCD_WIDTH/2 - 9*w, LCD_HEIGHT/2 + h, "SCROLL+: +10");
1014 rb->lcd_putsxy(LCD_WIDTH/2 - 9*w, LCD_HEIGHT/2 + 2*h + 1, "SCROLL-: -10");
1015 #else
1016 rb->lcd_putsxy(LCD_WIDTH/2 - 9*w, LCD_HEIGHT/2 - h-2, "RIGHT: +1");
1017 rb->lcd_putsxy(LCD_WIDTH/2 - 9*w, LCD_HEIGHT/2 - 1, "LEFT: -1");
1018 rb->lcd_putsxy(LCD_WIDTH/2 - 9*w, LCD_HEIGHT/2 + h, "UP: +10");
1019 rb->lcd_putsxy(LCD_WIDTH/2 - 9*w, LCD_HEIGHT/2 + 2*h + 1, "DOWN: -10");
1020 #endif
1021 rb->lcd_update_rect(LCD_WIDTH/2 - 9*w - 1, LCD_HEIGHT/2 - 4*h - 3,
1022 37*w / 2, 8*h -3);
1023 #endif
1025 while(!breakout) {
1026 button = rb->button_get(true);
1028 switch(button) {
1029 case BJACK_UP:
1030 case (BJACK_UP|BUTTON_REPEAT):
1031 if (amount + 10 < upper_limit + 1) {
1032 amount += 10;
1033 changed = true;
1035 break;
1036 case BJACK_DOWN:
1037 case (BJACK_DOWN|BUTTON_REPEAT):
1038 if (amount - 10 > lower_limit - 1) {
1039 amount -= 10;
1040 changed = true;
1042 break;
1043 case BJACK_RIGHT:
1044 case (BJACK_RIGHT|BUTTON_REPEAT):
1045 if (amount + 1 < upper_limit + 1) {
1046 amount++;
1047 changed = true;
1049 break;
1050 case BJACK_LEFT:
1051 case (BJACK_LEFT|BUTTON_REPEAT):
1052 if (amount - 1 > lower_limit - 1) {
1053 amount--;
1054 changed = true;
1056 break;
1057 #ifdef BJACK_MAX
1058 case BJACK_MAX :
1059 amount = upper_limit;
1060 changed = true;
1061 break;
1062 #endif
1063 #ifdef BJACK_MIN
1064 case BJACK_MIN :
1065 amount = lower_limit;
1066 changed = true;
1067 break;
1068 #endif
1069 case BJACK_QUIT:
1070 breakout = true;
1071 amount = 0;
1072 break;
1073 case BJACK_SELECT:
1074 breakout = true;
1075 break;
1078 if(changed) {
1079 #if LCD_HEIGHT <= 64
1080 rb->lcd_putsf(0, 2, "$%d", amount);
1081 rb->lcd_update();
1082 #else
1083 rb->lcd_set_drawmode(DRMODE_BG+DRMODE_INVERSEVID);
1084 rb->lcd_fillrect(LCD_WIDTH/2 - 9*w, LCD_HEIGHT/2 - 3*h, 5*w, h);
1085 rb->lcd_set_drawmode(DRMODE_SOLID);
1086 rb->lcd_putsxyf(LCD_WIDTH/2 - 9*w, LCD_HEIGHT/2 - 3*h, "$%d", amount);
1087 rb->lcd_update_rect(LCD_WIDTH/2 - 9*w, LCD_HEIGHT/2 - 3*h, 5*w, h);
1088 #endif
1089 changed = false;
1093 #if LCD_DEPTH > 1
1094 rb->lcd_set_foreground(FG_COLOR);
1095 rb->lcd_set_background(BG_COLOR);
1096 #endif
1097 rb->lcd_clear_display();
1098 return amount;
1101 /*****************************************************************************
1102 * blackjack_get_bet() gets the player's bet.
1103 ******************************************************************************/
1104 static void blackjack_get_bet(struct game_context* bj) {
1105 bj->current_bet = blackjack_get_amount("Please enter a bet", 10,
1106 bj->player_money, bj->current_bet);
1109 /*****************************************************************************
1110 * double_down() returns one final card then finishes the game
1111 ******************************************************************************/
1112 static void double_down(struct game_context* bj) {
1113 bj->current_bet *= 2;
1114 bj->player_cards[0][bj->num_player_cards[0]] = new_card();
1115 bj->player_total += bj->player_cards[0][bj->num_player_cards[0]].value;
1116 bj->num_player_cards[0]++;
1119 /*****************************************************************************
1120 * split() checks if the player wants to split and acts accordingly.
1121 * When bj->split_status is 1, no split occurred. 2 means the player split and 3
1122 * means a split has already occurred and the first hand is done.
1123 ******************************************************************************/
1124 static void split(struct game_context* bj) {
1125 if (blackjack_get_yes_no("Split?") != 0)
1126 bj->split_status = 1;
1127 else {
1128 bj->split_status = 2;
1129 bj->current_bet *= 2;
1130 bj->num_player_cards[0] = 1;
1131 bj->num_player_cards[1] = 1;
1132 bj->player_cards[1][0] = bj->player_cards[0][1];
1133 bj->player_total = bj->player_cards[0][0].value;
1137 /*****************************************************************************
1138 * insurance() see if the player wants to buy insurance and how much.
1139 ******************************************************************************/
1140 static unsigned int insurance(struct game_context* bj) {
1141 unsigned int insurance, max_amount;
1143 insurance = blackjack_get_yes_no("Buy Insurance?");
1144 bj->asked_insurance = true;
1145 max_amount = bj->current_bet < (unsigned int)bj->player_money ?
1146 bj->current_bet/2 : (unsigned int)bj->player_money;
1147 if (insurance != 0) return 0;
1149 insurance = blackjack_get_amount("How much?", 0, max_amount, 0);
1150 redraw_board(bj);
1151 return insurance;
1154 /*****************************************************************************
1155 * play_again() checks to see if the player wants to keep playing.
1156 ******************************************************************************/
1157 static unsigned int play_again(void) {
1158 return blackjack_get_yes_no("Play Again?");
1161 /*****************************************************************************
1162 * blackjack_help() displays help text.
1163 ******************************************************************************/
1164 static bool blackjack_help(void) {
1165 static char *help_text[] = {
1166 "Blackjack", "", "Aim", "",
1167 "Try", "to", "get", "as", "close", "to", "21", "without", "going",
1168 "over", "or", "simply", "beat", "out", "the", "dealer", "for", "the",
1169 "best", "hand.", "", "",
1170 "Controls", "",
1171 BJACK_SELECT_NAME, ":", "hit", "/", "select", "",
1172 BJACK_STAY_NAME, ":", "stay", "",
1173 BJACK_DOUBLE_NAME, ":", "double", "down", "",
1174 BJACK_QUIT_NAME, ":", "go", "to", "menu", "",
1176 static struct style_text formation[]={
1177 { 0, TEXT_CENTER|TEXT_UNDERLINE },
1178 { 2, C_RED },
1179 { 26, C_RED },
1180 LAST_STYLE_ITEM
1183 rb->lcd_setfont(FONT_UI);
1184 #ifdef HAVE_LCD_COLOR
1185 rb->lcd_set_background(LCD_BLACK);
1186 rb->lcd_set_foreground(LCD_WHITE);
1187 #endif
1188 if (display_text(ARRAYLEN(help_text), help_text, formation, NULL, true))
1189 return true;
1190 rb->lcd_setfont(FONT_SYSFIXED);
1192 return false;
1195 static int blackjack_menu_cb(int action, const struct menu_item_ex *this_item)
1197 int i = ((intptr_t)this_item);
1198 if(action == ACTION_REQUEST_MENUITEM
1199 && !resume && (i==0 || i==5))
1200 return ACTION_EXIT_MENUITEM;
1201 return action;
1204 /*****************************************************************************
1205 * blackjack_menu() is the initial menu at the start of the game.
1206 ******************************************************************************/
1207 static unsigned int blackjack_menu(void) {
1208 int selection = 0;
1209 bool breakout = false;
1211 MENUITEM_STRINGLIST(menu, "BlackJack Menu", blackjack_menu_cb,
1212 "Resume Game", "Start New Game",
1213 "High Scores", "Help",
1214 "Playback Control",
1215 "Quit without Saving", "Quit");
1217 while(!breakout) {
1218 switch(rb->do_menu(&menu, &selection, NULL, false)) {
1219 case 0:
1220 breakout = true;
1221 if(resume_file)
1222 rb->remove(SAVE_FILE);
1223 resume_file = false;
1224 break;
1225 case 1:
1226 breakout = true;
1227 resume = false;
1228 break;
1229 case 2:
1230 highscore_show(-1, highscores, NUM_SCORES, false);
1231 break;
1232 case 3:
1233 if(blackjack_help())
1234 return BJ_USB;
1235 break;
1236 case 4:
1237 if (playback_control(NULL))
1238 return BJ_USB;
1239 break;
1240 case 5:
1241 return BJ_QUIT_WITHOUT_SAVING;
1242 case 6:
1243 if (resume)
1244 return BJ_QUIT;
1245 else
1246 return BJ_QUIT_WITHOUT_SAVING;
1248 case MENU_ATTACHED_USB:
1249 return BJ_USB;
1251 default:
1252 break;
1256 return 0;
1259 /*****************************************************************************
1260 * blackjack() is the main game subroutine, it returns the final game status.
1261 ******************************************************************************/
1262 static int blackjack(struct game_context* bj) {
1263 int button;
1264 unsigned int w, h, temp_var, done = 0, todo = 1;
1265 signed int temp;
1266 bool breakout = false;
1267 bool dbl_down = false;
1269 /********************
1270 * menu *
1271 ********************/
1272 temp_var = blackjack_menu();
1273 if (temp_var != 0)
1274 return temp_var;
1276 #if LCD_DEPTH > 1
1277 rb->lcd_set_background(BG_COLOR);
1278 rb->lcd_set_foreground(FG_COLOR);
1279 #endif
1281 /********************
1282 * init *
1283 ********************/
1284 blackjack_init(bj);
1286 /********************
1287 * play *
1288 ********************/
1290 resume_file = false;
1291 /* check for resumed game */
1292 if(resume) {
1293 resume = false;
1294 redraw_board(bj);
1295 if (bj->split_status == 2) {
1296 todo=2;
1297 player_x = bj->num_player_cards[0] * 10 + 4;
1299 else if (bj->split_status == 3) {
1300 player_x = bj->num_player_cards[1] * 10 + LCD_WIDTH/2 + 4;
1301 todo=2;
1302 done=1;
1305 else {
1306 bj->player_money = 1000;
1307 bj->current_bet = 10;
1308 blackjack_get_bet(bj);
1309 if (bj->current_bet == 0)
1310 return -1;
1311 rb->lcd_clear_display();
1312 deal_init_cards(bj);
1313 blackjack_drawtable(bj);
1316 rb->lcd_update();
1318 breakout = false;
1320 while(true){
1321 if(bj->player_total == 21 && bj->num_player_cards[0] == 2) {
1322 bj->is_blackjack = true;
1323 bj->end_hand = true;
1324 finish_game(bj);
1326 else if(bj->dealer_cards[1].is_soft_ace && !breakout &&
1327 !bj->asked_insurance) {
1328 temp_var = insurance(bj);
1329 if (bj->dealer_total == 21) {
1330 rb->splash(HZ, "Dealer has blackjack");
1331 bj->player_money += temp_var;
1332 bj->end_hand = true;
1333 breakout = true;
1334 redraw_board(bj);
1335 finish_game(bj);
1337 else {
1338 rb->splash(HZ, "Dealer does not have blackjack");
1339 bj->player_money -= temp_var;
1340 breakout = true;
1341 redraw_board(bj);
1342 rb->lcd_update();
1345 if(!bj->end_hand && bj->split_status == 0 &&
1346 bj->player_cards[0][0].num == bj->player_cards[0][1].num) {
1347 split(bj);
1348 redraw_board(bj);
1349 rb->lcd_update_rect(0, LCD_HEIGHT/2, LCD_WIDTH, LCD_HEIGHT/2);
1350 if (bj->split_status == 2) {
1351 todo++;
1352 player_x = bj->num_player_cards[0] * 10 + 4;
1356 while(!bj->end_hand && done < todo) {
1357 button = rb->button_get(true);
1359 switch(button) {
1360 case BJACK_SELECT:
1361 NEXT_CARD = new_card();
1362 bj->player_total += NEXT_CARD.value;
1363 draw_card(NEXT_CARD, true, player_x, player_y);
1364 bj->num_player_cards[done]++;
1365 if (bj->num_player_cards[done] == MAX_CARDS + 1) {
1366 redraw_board(bj);
1367 rb->lcd_update_rect(0, LCD_HEIGHT/2, LCD_WIDTH,
1368 LCD_HEIGHT/2);
1370 else if (bj->num_player_cards[done]>MAX_CARDS || todo > 1) {
1371 rb->lcd_update_rect(player_x, player_y, CARD_WIDTH+2,
1372 CARD_HEIGHT+2);
1373 player_x += 10;
1375 else {
1376 rb->lcd_update_rect(player_x, player_y, CARD_WIDTH+2,
1377 CARD_HEIGHT+2);
1378 player_x += CARD_WIDTH + 4;
1380 update_total(bj);
1382 break;
1383 case BJACK_STAY:
1384 bj->end_hand = true;
1385 break;
1386 case BJACK_DOUBLEDOWN:
1387 if ((signed int)bj->current_bet * 2 <
1388 bj->player_money + 1 &&
1389 bj->num_player_cards[0]==2 && todo==1) {
1390 double_down(bj);
1391 dbl_down = true;
1392 if (bj->player_total < 22) {
1393 bj->end_hand = true;
1394 finish_game(bj);
1397 else if((signed int)bj->current_bet * 2 >
1398 bj->player_money){
1399 rb->splash(HZ, "Not enough money to double down.");
1400 redraw_board(bj);
1401 rb->lcd_update();
1403 break;
1405 case BJACK_QUIT:
1406 resume = true;
1407 return BJ_END;
1410 while (bj->player_total > 21 && !bj->end_hand) {
1411 temp = check_for_aces(bj->player_cards[done],
1412 bj->num_player_cards[done]);
1413 if(temp != -1) {
1414 bj->player_cards[done][temp].is_soft_ace = false;
1415 bj->player_total -= 10;
1416 update_total(bj);
1417 if (dbl_down) {
1418 bj->end_hand = true;
1419 finish_game(bj);
1422 else
1423 bj->end_hand = true;
1426 if (bj->end_hand) {
1427 done++;
1428 if(todo > 1) {
1429 if (done == 2) {
1430 temp = bj->player_total;
1431 bj->player_total = temp_var;
1432 temp_var = temp;
1433 finish_game(bj);
1434 rb->lcd_getstringsize(" Split 1 ", &w, &h);
1435 rb->lcd_putsxy(LCD_WIDTH/2-w/2, LCD_HEIGHT/2-3*h/2,
1436 " Split 1 ");
1437 rb->lcd_update_rect(LCD_WIDTH/2-w/2, LCD_HEIGHT/2-3*h/2,
1438 w,h);
1439 bj->current_bet /= 2;
1440 rb->lcd_update_rect(LCD_WIDTH/2-w/2, LCD_HEIGHT/2-3*h/2,
1441 w,h);
1442 rb->sleep(HZ*2);
1443 bj->player_total = temp_var;
1444 finish_game(bj);
1445 rb->lcd_getstringsize(" Split 2 ", &w, &h);
1446 rb->lcd_putsxy(LCD_WIDTH/2-w/2, LCD_HEIGHT/2-3*h/2,
1447 " Split 2 ");
1448 rb->lcd_update_rect(LCD_WIDTH/2-w/2, LCD_HEIGHT/2-3*h/2,
1449 w,h);
1450 rb->sleep(HZ*2);
1452 else {
1453 bj->end_hand = false;
1454 bj->split_status = 3;
1455 temp_var = bj->player_total;
1456 bj->player_total = bj->player_cards[1][0].value;
1457 update_total(bj);
1458 redraw_board(bj);
1459 player_x += 10;
1460 rb->lcd_update();
1463 else
1464 finish_game(bj);
1468 if (bj->player_money < 10) {
1469 rb->sleep(HZ);
1470 return BJ_LOSE;
1473 if (bj->end_hand) { /* If hand is over */
1474 if (play_again() != 0) /* User wants to quit */
1475 return BJ_END;
1476 else { /* User keeps playing */
1477 breakout = false;
1478 temp = bj->current_bet;
1479 bj->current_bet = 0;
1480 redraw_board(bj);
1481 rb->lcd_update();
1482 bj->current_bet = temp;
1483 if(dbl_down) {
1484 bj->current_bet /= 2;
1485 dbl_down = false;
1487 done = 0;
1488 todo = 1;
1489 blackjack_init(bj);
1490 blackjack_get_bet(bj);
1491 if (bj->current_bet == 0)
1492 return BJ_END;
1493 deal_init_cards(bj);
1494 blackjack_drawtable(bj);
1495 rb->lcd_update();
1499 /* Never reached */
1500 return PLUGIN_OK;
1503 /*****************************************************************************
1504 * plugin entry point.
1505 ******************************************************************************/
1506 enum plugin_status plugin_start(const void* parameter)
1508 struct game_context bj;
1509 bool exit = false;
1511 (void)parameter;
1513 #if LCD_DEPTH > 1
1514 rb->lcd_set_backdrop(NULL);
1515 #endif
1517 /* load high scores */
1518 highscore_load(SCORE_FILE, highscores, NUM_SCORES);
1519 resume = blackjack_loadgame(&bj);
1520 resume_file = resume;
1522 rb->lcd_setfont(FONT_SYSFIXED);
1524 while(!exit) {
1525 switch(blackjack(&bj)){
1526 case BJ_LOSE:
1527 rb->splash(HZ, "Not enough money to continue");
1528 /* fall through to BJ_END */
1530 case BJ_END:
1531 if(!resume && bj.player_money > 10) {
1532 /* There is no level, so store -1 to blank column */
1533 int position = highscore_update(bj.player_money, -1, "",
1534 highscores, NUM_SCORES);
1535 if (position != -1)
1537 if (position==0)
1538 rb->splash(HZ*2, "New High Score");
1539 highscore_show(position, highscores, NUM_SCORES, false);
1542 break;
1544 case BJ_USB:
1545 highscore_save(SCORE_FILE, highscores, NUM_SCORES);
1546 return PLUGIN_USB_CONNECTED;
1548 case BJ_QUIT:
1549 rb->splash(HZ*1, "Saving game...");
1550 blackjack_savegame(&bj);
1551 /* fall through */
1553 case BJ_QUIT_WITHOUT_SAVING:
1554 exit = true;
1555 break;
1557 default:
1558 break;
1561 highscore_save(SCORE_FILE, highscores, NUM_SCORES);
1562 return PLUGIN_OK;