1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
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 ****************************************************************************/
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"
32 #define HIGH_SCORE PLUGIN_GAMES_DIR "/blackjack.score"
33 #define SAVE_FILE PLUGIN_GAMES_DIR "/blackjack.save"
35 struct highscore highest
[NUM_SCORES
];
37 /* final game return status */
43 #if CONFIG_KEYPAD == RECORDER_PAD
44 #define BJACK_SELECT_NAME "PLAY"
45 #define BJACK_STAY_NAME "F1"
46 #define BJACK_RESUME_NAME "F3"
47 #define BJACK_QUIT_NAME "OFF"
48 #define BJACK_DOUBLE_NAME "F2"
49 #define BJACK_SELECT BUTTON_PLAY
50 #define BJACK_QUIT BUTTON_OFF
51 #define BJACK_MAX (BUTTON_ON|BUTTON_UP)
52 #define BJACK_MIN (BUTTON_ON|BUTTON_DOWN)
53 #define BJACK_STAY BUTTON_F1
54 #define BJACK_DOUBLEDOWN BUTTON_F2
55 #define BJACK_RESUME BUTTON_F3
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_RESUME_NAME "DOWN"
65 #define BJACK_QUIT_NAME "OFF"
66 #define BJACK_DOUBLE_NAME "UP"
67 #define BJACK_SELECT BUTTON_MENU
68 #define BJACK_QUIT BUTTON_OFF
69 #define BJACK_MAX (BUTTON_MENU|BUTTON_UP)
70 #define BJACK_MIN (BUTTON_MENU|BUTTON_DOWN)
71 #define BJACK_STAY BUTTON_RIGHT
72 #define BJACK_DOUBLEDOWN BUTTON_UP
73 #define BJACK_RESUME BUTTON_DOWN
74 #define BJACK_UP BUTTON_UP
75 #define BJACK_DOWN BUTTON_DOWN
76 #define BJACK_RIGHT BUTTON_RIGHT
77 #define BJACK_LEFT BUTTON_LEFT
79 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
80 #define BJACK_SELECT_NAME "PLAY"
81 #define BJACK_STAY_NAME ">>|"
82 #define BJACK_RESUME_NAME "RIGHT"
83 #define BJACK_QUIT_NAME "POWER"
84 #define BJACK_DOUBLE_NAME "|<<"
85 #define BJACK_SELECT BUTTON_PLAY
86 #define BJACK_QUIT BUTTON_POWER
87 #define BJACK_MAX (BUTTON_PLAY|BUTTON_SCROLL_UP)
88 #define BJACK_MIN (BUTTON_PLAY|BUTTON_SCROLL_DOWN)
89 #define BJACK_STAY BUTTON_FF
90 #define BJACK_DOUBLEDOWN BUTTON_REW
91 #define BJACK_RESUME BUTTON_RIGHT
92 #define BJACK_UP BUTTON_SCROLL_UP
93 #define BJACK_DOWN BUTTON_SCROLL_DOWN
94 #define BJACK_RIGHT BUTTON_RIGHT
95 #define BJACK_LEFT BUTTON_LEFT
97 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
98 (CONFIG_KEYPAD == IRIVER_H300_PAD)
99 #define BJACK_SELECT_NAME "ON"
100 #define BJACK_STAY_NAME "REC"
101 #define BJACK_RESUME_NAME "MODE"
102 #define BJACK_QUIT_NAME "OFF"
103 #define BJACK_DOUBLE_NAME "SELECT"
104 #define BJACK_SELECT BUTTON_ON
105 #define BJACK_QUIT BUTTON_OFF
106 #define BJACK_MAX (BUTTON_ON|BUTTON_UP)
107 #define BJACK_MIN (BUTTON_ON|BUTTON_DOWN)
108 #define BJACK_STAY BUTTON_REC
109 #define BJACK_DOUBLEDOWN BUTTON_SELECT
110 #define BJACK_RESUME BUTTON_MODE
111 #define BJACK_UP BUTTON_UP
112 #define BJACK_DOWN BUTTON_DOWN
113 #define BJACK_RIGHT BUTTON_RIGHT
114 #define BJACK_LEFT BUTTON_LEFT
116 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
117 (CONFIG_KEYPAD == IPOD_3G_PAD) || \
118 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
119 #define BJACK_SELECT_NAME "SELECT"
120 #define BJACK_STAY_NAME "RIGHT"
121 #define BJACK_RESUME_NAME "PLAY"
122 #define BJACK_QUIT_NAME "MENU"
123 #define BJACK_DOUBLE_NAME "LEFT"
124 #define BJACK_SELECT BUTTON_SELECT
125 #define BJACK_QUIT BUTTON_MENU
126 #define BJACK_MAX (BUTTON_SELECT|BUTTON_SCROLL_FWD)
127 #define BJACK_MIN (BUTTON_SELECT|BUTTON_SCROLL_BACK)
128 #define BJACK_STAY BUTTON_RIGHT
129 #define BJACK_DOUBLEDOWN BUTTON_LEFT
130 #define BJACK_RESUME BUTTON_PLAY
131 #define BJACK_UP BUTTON_SCROLL_FWD
132 #define BJACK_DOWN BUTTON_SCROLL_BACK
133 #define BJACK_RIGHT BUTTON_RIGHT
134 #define BJACK_LEFT BUTTON_LEFT
136 #elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
137 #define BJACK_SELECT_NAME "PLAY"
138 #define BJACK_STAY_NAME "REC"
139 #define BJACK_RESUME_NAME "DOWN"
140 #define BJACK_QUIT_NAME "POWER"
141 #define BJACK_DOUBLE_NAME "PLAY"
142 #define BJACK_SELECT BUTTON_SELECT
143 #define BJACK_QUIT BUTTON_POWER
144 #define BJACK_MAX (BUTTON_PLAY|BUTTON_UP)
145 #define BJACK_MIN (BUTTON_PLAY|BUTTON_DOWN)
146 #define BJACK_STAY BUTTON_REC
147 #define BJACK_DOUBLEDOWN BUTTON_PLAY
148 #define BJACK_RESUME BUTTON_DOWN
149 #define BJACK_UP BUTTON_UP
150 #define BJACK_DOWN BUTTON_DOWN
151 #define BJACK_RIGHT BUTTON_RIGHT
152 #define BJACK_LEFT BUTTON_LEFT
154 #elif CONFIG_KEYPAD == IRIVER_IFP7XX_PAD
155 #define BJACK_SELECT_NAME "MODE"
156 #define BJACK_STAY_NAME "MODE"
157 #define BJACK_RESUME_NAME "EQ+MODE"
158 #define BJACK_QUIT_NAME "PLAY"
159 #define BJACK_DOUBLE_NAME "SELECT"
160 #define BJACK_SELECT BUTTON_MODE
161 #define BJACK_QUIT BUTTON_PLAY
162 #define BJACK_MAX (BUTTON_EQ|BUTTON_UP)
163 #define BJACK_MIN (BUTTON_EQ|BUTTON_DOWN)
164 #define BJACK_STAY BUTTON_MODE
165 #define BJACK_DOUBLEDOWN BUTTON_SELECT
166 #define BJACK_RESUME (BUTTON_EQ|BUTTON_MODE)
167 #define BJACK_UP BUTTON_UP
168 #define BJACK_DOWN BUTTON_DOWN
169 #define BJACK_RIGHT BUTTON_RIGHT
170 #define BJACK_LEFT BUTTON_LEFT
172 #elif CONFIG_KEYPAD == GIGABEAT_PAD
173 #define BJACK_SELECT_NAME "A"
174 #define BJACK_STAY_NAME "VOL-"
175 #define BJACK_RESUME_NAME "MENU"
176 #define BJACK_QUIT_NAME "POWER"
177 #define BJACK_DOUBLE_NAME "SELECT"
178 #define BJACK_SELECT BUTTON_A
179 #define BJACK_QUIT BUTTON_POWER
180 #define BJACK_MAX BUTTON_VOL_UP
181 #define BJACK_MIN BUTTON_VOL_DOWN
182 #define BJACK_STAY BUTTON_VOL_DOWN
183 #define BJACK_DOUBLEDOWN BUTTON_SELECT
184 #define BJACK_RESUME BUTTON_MENU
185 #define BJACK_UP BUTTON_UP
186 #define BJACK_DOWN BUTTON_DOWN
187 #define BJACK_RIGHT BUTTON_RIGHT
188 #define BJACK_LEFT BUTTON_LEFT
190 #elif CONFIG_KEYPAD == SANSA_E200_PAD
191 #define BJACK_SELECT_NAME "SELECT"
192 #define BJACK_STAY_NAME "RIGHT"
193 #define BJACK_RESUME_NAME "DOWN"
194 #define BJACK_QUIT_NAME "POWER"
195 #define BJACK_DOUBLE_NAME "LEFT"
196 #define BJACK_SELECT BUTTON_SELECT
197 #define BJACK_QUIT BUTTON_POWER
198 #define BJACK_MAX (BUTTON_REC|BUTTON_UP)
199 #define BJACK_MIN (BUTTON_REC|BUTTON_DOWN)
200 #define BJACK_STAY BUTTON_RIGHT
201 #define BJACK_DOUBLEDOWN BUTTON_LEFT
202 #define BJACK_RESUME BUTTON_DOWN
203 #define BJACK_UP BUTTON_SCROLL_FWD
204 #define BJACK_DOWN BUTTON_SCROLL_BACK
205 #define BJACK_RIGHT BUTTON_RIGHT
206 #define BJACK_LEFT BUTTON_LEFT
208 #elif CONFIG_KEYPAD == SANSA_FUZE_PAD
209 #define BJACK_SELECT_NAME "SELECT"
210 #define BJACK_STAY_NAME "RIGHT"
211 #define BJACK_RESUME_NAME "UP"
212 #define BJACK_QUIT_NAME "HOME"
213 #define BJACK_DOUBLE_NAME "LEFT"
214 #define BJACK_SELECT BUTTON_SELECT
215 #define BJACK_QUIT (BUTTON_HOME|BUTTON_REPEAT)
216 #define BJACK_MAX (BUTTON_SELECT|BUTTON_UP)
217 #define BJACK_MIN (BUTTON_SELECT|BUTTON_DOWN)
218 #define BJACK_STAY BUTTON_RIGHT
219 #define BJACK_DOUBLEDOWN BUTTON_LEFT
220 #define BJACK_RESUME BUTTON_UP
221 #define BJACK_UP BUTTON_SCROLL_FWD
222 #define BJACK_DOWN BUTTON_SCROLL_BACK
223 #define BJACK_RIGHT BUTTON_RIGHT
224 #define BJACK_LEFT BUTTON_LEFT
226 #elif CONFIG_KEYPAD == SANSA_C200_PAD
227 #define BJACK_SELECT_NAME "SELECT"
228 #define BJACK_STAY_NAME "RIGHT"
229 #define BJACK_RESUME_NAME "DOWN"
230 #define BJACK_QUIT_NAME "POWER"
231 #define BJACK_DOUBLE_NAME "LEFT"
232 #define BJACK_SELECT BUTTON_SELECT
233 #define BJACK_QUIT BUTTON_POWER
234 #define BJACK_MAX BUTTON_VOL_UP
235 #define BJACK_MIN BUTTON_VOL_DOWN
236 #define BJACK_STAY BUTTON_RIGHT
237 #define BJACK_DOUBLEDOWN BUTTON_LEFT
238 #define BJACK_RESUME BUTTON_DOWN
239 #define BJACK_UP BUTTON_UP
240 #define BJACK_DOWN BUTTON_DOWN
241 #define BJACK_RIGHT BUTTON_RIGHT
242 #define BJACK_LEFT BUTTON_LEFT
244 #elif CONFIG_KEYPAD == SANSA_CLIP_PAD
245 #define BJACK_SELECT_NAME "SELECT"
246 #define BJACK_STAY_NAME "RIGHT"
247 #define BJACK_RESUME_NAME "DOWN"
248 #define BJACK_QUIT_NAME "POWER"
249 #define BJACK_DOUBLE_NAME "LEFT"
250 #define BJACK_SELECT BUTTON_SELECT
251 #define BJACK_QUIT BUTTON_POWER
252 #define BJACK_MAX BUTTON_VOL_UP
253 #define BJACK_MIN BUTTON_VOL_DOWN
254 #define BJACK_STAY BUTTON_RIGHT
255 #define BJACK_DOUBLEDOWN BUTTON_LEFT
256 #define BJACK_RESUME BUTTON_DOWN
257 #define BJACK_UP BUTTON_UP
258 #define BJACK_DOWN BUTTON_DOWN
259 #define BJACK_RIGHT BUTTON_RIGHT
260 #define BJACK_LEFT BUTTON_LEFT
262 #elif CONFIG_KEYPAD == SANSA_M200_PAD
263 #define BJACK_SELECT_NAME "SELECT"
264 #define BJACK_STAY_NAME "RIGHT"
265 #define BJACK_RESUME_NAME "DOWN"
266 #define BJACK_QUIT_NAME "POWER"
267 #define BJACK_DOUBLE_NAME "LEFT"
268 #define BJACK_SELECT (BUTTON_SELECT | BUTTON_REL)
269 #define BJACK_QUIT BUTTON_POWER
270 #define BJACK_MAX BUTTON_VOL_UP
271 #define BJACK_MIN BUTTON_VOL_DOWN
272 #define BJACK_STAY BUTTON_RIGHT
273 #define BJACK_DOUBLEDOWN BUTTON_LEFT
274 #define BJACK_RESUME BUTTON_DOWN
275 #define BJACK_UP BUTTON_UP
276 #define BJACK_DOWN BUTTON_DOWN
277 #define BJACK_RIGHT BUTTON_RIGHT
278 #define BJACK_LEFT BUTTON_LEFT
280 #elif CONFIG_KEYPAD == ELIO_TPJ1022_PAD
281 #define BJACK_SELECT_NAME "MAIN"
282 #define BJACK_STAY_NAME "MENU"
283 #define BJACK_RESUME_NAME ">>|"
284 #define BJACK_QUIT_NAME "POWER"
285 #define BJACK_DOUBLE_NAME "DOWN"
286 #define BJACK_SELECT BUTTON_MAIN
287 #define BJACK_QUIT BUTTON_POWER
288 #define BJACK_MAX (BUTTON_REC|BUTTON_UP)
289 #define BJACK_MIN (BUTTON_REC|BUTTON_DOWN)
290 #define BJACK_STAY BUTTON_MENU
291 #define BJACK_DOUBLEDOWN BUTTON_DOWN
292 #define BJACK_RESUME BUTTON_FF
293 #define BJACK_UP BUTTON_UP
294 #define BJACK_DOWN BUTTON_DOWN
295 #define BJACK_RIGHT BUTTON_RIGHT
296 #define BJACK_LEFT BUTTON_LEFT
298 #elif CONFIG_KEYPAD == GIGABEAT_S_PAD
299 #define BJACK_SELECT_NAME "PLAY"
300 #define BJACK_STAY_NAME "VOL-"
301 #define BJACK_RESUME_NAME "MENU"
302 #define BJACK_QUIT_NAME "BACK"
303 #define BJACK_DOUBLE_NAME "SELECT"
304 #define BJACK_SELECT BUTTON_PLAY
305 #define BJACK_QUIT BUTTON_BACK
306 #define BJACK_MAX BUTTON_VOL_UP
307 #define BJACK_MIN BUTTON_VOL_DOWN
308 #define BJACK_STAY BUTTON_VOL_DOWN
309 #define BJACK_DOUBLEDOWN BUTTON_SELECT
310 #define BJACK_RESUME BUTTON_MENU
311 #define BJACK_UP BUTTON_UP
312 #define BJACK_DOWN BUTTON_DOWN
313 #define BJACK_RIGHT BUTTON_RIGHT
314 #define BJACK_LEFT BUTTON_LEFT
316 #elif CONFIG_KEYPAD == MROBE100_PAD
317 #define BJACK_SELECT_NAME "SELECT"
318 #define BJACK_STAY_NAME "DISPLAY"
319 #define BJACK_RESUME_NAME "PLAY"
320 #define BJACK_QUIT_NAME "POWER"
321 #define BJACK_DOUBLE_NAME "DOWN"
322 #define BJACK_SELECT BUTTON_SELECT
323 #define BJACK_QUIT BUTTON_POWER
324 #define BJACK_MAX BUTTON_MENU
325 #define BJACK_MIN BUTTON_DISPLAY
326 #define BJACK_STAY BUTTON_DISPLAY
327 #define BJACK_DOUBLEDOWN BUTTON_DOWN
328 #define BJACK_RESUME BUTTON_PLAY
329 #define BJACK_UP BUTTON_UP
330 #define BJACK_DOWN BUTTON_DOWN
331 #define BJACK_RIGHT BUTTON_RIGHT
332 #define BJACK_LEFT BUTTON_LEFT
334 #elif CONFIG_KEYPAD == IAUDIO_M3_PAD
335 #define BJACK_SELECT_NAME "RC","PLAY"
336 #define BJACK_STAY_NAME "RC", ">>|"
337 #define BJACK_RESUME_NAME "RC_MODE"
338 #define BJACK_QUIT_NAME "RC_REC"
339 #define BJACK_DOUBLE_NAME "RC_REW"
340 #define BJACK_SELECT BUTTON_RC_PLAY
341 #define BJACK_QUIT BUTTON_RC_REC
342 #define BJACK_MAX (BUTTON_RC_PLAY|BUTTON_RC_VOL_UP)
343 #define BJACK_MIN (BUTTON_RC_PLAY|BUTTON_RC_VOL_DOWN)
344 #define BJACK_STAY BUTTON_RC_FF
345 #define BJACK_DOUBLEDOWN BUTTON_RC_REW
346 #define BJACK_RESUME BUTTON_RC_MODE
347 #define BJACK_UP BUTTON_RC_VOL_UP
348 #define BJACK_DOWN BUTTON_RC_VOL_DOWN
349 #define BJACK_RIGHT BUTTON_RC_FF
350 #define BJACK_LEFT BUTTON_RC_REW
352 #elif CONFIG_KEYPAD == COWOND2_PAD
353 #define BJACK_QUIT_NAME "POWER"
354 #define BJACK_DOUBLE_NAME "-"
355 #define BJACK_QUIT BUTTON_POWER
356 #define BJACK_DOUBLEDOWN BUTTON_MINUS
358 #elif CONFIG_KEYPAD == CREATIVEZVM_PAD
359 #define BJACK_SELECT_NAME "SELECT"
360 #define BJACK_STAY_NAME "PLAY"
361 #define BJACK_RESUME_NAME "MENU"
362 #define BJACK_QUIT_NAME "POWER"
363 #define BJACK_DOUBLE_NAME "CUSTOM"
364 #define BJACK_SELECT BUTTON_SELECT
365 #define BJACK_QUIT BUTTON_POWER
366 #define BJACK_STAY BUTTON_PLAY
367 #define BJACK_MAX (BUTTON_CUSTOM|BUTTON_UP)
368 #define BJACK_MIN (BUTTON_CUSTOM|BUTTON_DOWN)
369 #define BJACK_DOUBLEDOWN BUTTON_CUSTOM
370 #define BJACK_RESUME BUTTON_MENU
371 #define BJACK_UP BUTTON_UP
372 #define BJACK_DOWN BUTTON_DOWN
373 #define BJACK_RIGHT BUTTON_RIGHT
374 #define BJACK_LEFT BUTTON_LEFT
376 #elif CONFIG_KEYPAD == PHILIPS_HDD1630_PAD
377 #define BJACK_SELECT_NAME "MENU"
378 #define BJACK_STAY_NAME "VOL-"
379 #define BJACK_RESUME_NAME "VIEW"
380 #define BJACK_QUIT_NAME "POWER"
381 #define BJACK_DOUBLE_NAME "SELECT"
382 #define BJACK_SELECT BUTTON_MENU
383 #define BJACK_QUIT BUTTON_POWER
384 #define BJACK_MAX BUTTON_VOL_UP
385 #define BJACK_MIN BUTTON_VOL_DOWN
386 #define BJACK_STAY BUTTON_VOL_DOWN
387 #define BJACK_DOUBLEDOWN BUTTON_SELECT
388 #define BJACK_RESUME BUTTON_VIEW
389 #define BJACK_UP BUTTON_UP
390 #define BJACK_DOWN BUTTON_DOWN
391 #define BJACK_RIGHT BUTTON_RIGHT
392 #define BJACK_LEFT BUTTON_LEFT
394 #elif CONFIG_KEYPAD == ONDAVX747_PAD
395 #define BJACK_QUIT_NAME "POWER"
396 #define BJACK_DOUBLE_NAME "Vol-"
397 #define BJACK_QUIT BUTTON_POWER
398 #define BJACK_DOUBLEDOWN BUTTON_VOL_DOWN
400 #elif CONFIG_KEYPAD == MROBE500_PAD
401 #define BJACK_QUIT_NAME "POWER"
402 #define BJACK_QUIT BUTTON_POWER
405 #error No keymap defined!
408 #ifdef HAVE_TOUCHSCREEN
409 #ifndef BJACK_DOUBLEDOWN
410 #define BJACK_DOUBLEDOWN BUTTON_MIDLEFT
411 #define BJACK_DOUBLE_NAME "BUTTON_MIDLEFT"
414 #define BJACK_SELECT BUTTON_CENTER
415 #define BJACK_SELECT_NAME "BUTTON_CENTER"
418 #define BJACK_MAX BUTTON_TOPRIGHT
421 #define BJACK_MIN BUTTON_TOPLEFT
424 #define BJACK_RESUME BUTTON_BOTTOMRIGHT
425 #define BJACK_RESUME_NAME "BUTTON_BOTTOMRIGHT"
428 #define BJACK_STAY BUTTON_BOTTOMLEFT
429 #define BJACK_STAY_NAME "BUTTON_BOTTOMLEFT"
432 #define BJACK_UP BUTTON_TOPMIDDLE
435 #define BJACK_DOWN BUTTON_BOTTOMMIDDLE
438 #define BJACK_RIGHT BUTTON_MIDRIGHT
441 #define BJACK_LEFT BUTTON_MIDLEFT
446 #ifdef HAVE_LCD_COLOR
447 #define BG_COLOR LCD_RGBPACK(0,157,0)
448 #define FG_COLOR LCD_WHITE
450 #define BG_COLOR LCD_WHITE
451 #define FG_COLOR LCD_BLACK
454 #define CARD_WIDTH BMPWIDTH_card_back
455 #define CARD_HEIGHT BMPHEIGHT_card_back
457 /* This is the max amount of cards onscreen before condensing */
458 #define MAX_CARDS LCD_WIDTH/(CARD_WIDTH+4)
460 extern const fb_data card_deck
[];
461 extern const fb_data card_back
[];
463 #define NEXT_CARD bj->player_cards[done][bj->num_player_cards[done]]
465 /* dealer and player card positions */
466 unsigned int dealer_x
, dealer_y
, player_x
, player_y
;
468 typedef struct card
{
469 unsigned int value
; /* Card's value in Blackjack */
470 unsigned int num
; /* Value on card face 0-12 (0=Ace, 1=2, 11=Q) */
471 unsigned int suit
; /* 0:Spades, 1:Hearts, 2: Clubs; 3: Diamonds */
475 typedef struct game_context
{
476 struct card player_cards
[2][22]; /* 22 Cards means the deal was all aces */
477 struct card dealer_cards
[22]; /* That is the worst-case scenario */
478 unsigned int player_total
;
479 unsigned int dealer_total
;
480 signed int player_money
;
481 unsigned int num_player_cards
[2];
482 unsigned int num_dealer_cards
;
483 unsigned int current_bet
;
484 unsigned int split_status
; /* 0 = split hasn't been asked, *
485 * 1 = split did not occur *
486 * 2 = split occurred *
487 * 3 = split occurred and 1st hand done */
490 bool asked_insurance
;
494 /*****************************************************************************
495 * blackjack_init() initializes blackjack data structures.
496 ******************************************************************************/
497 static void blackjack_init(struct game_context
* bj
) {
498 /* seed the rand generator */
499 rb
->srand(*rb
->current_tick
);
501 /* reset card positions */
503 dealer_y
= LCD_HEIGHT
/4 - CARD_HEIGHT
/2;
505 player_y
= LCD_HEIGHT
- LCD_HEIGHT
/4 - CARD_HEIGHT
/2;
507 /* check for resumed game */
508 if(bj
->resume
) return;
511 bj
->player_total
= 0;
512 bj
->dealer_total
= 0;
513 bj
->num_player_cards
[0] = 2;
514 bj
->num_player_cards
[1] = 0;
515 bj
->num_dealer_cards
= 2;
516 bj
->end_hand
= false;
517 bj
->split_status
= 0;
518 bj
->is_blackjack
= false;
519 bj
->asked_insurance
= false;
522 /*****************************************************************************
523 * blackjack_drawtable() draws the table and some text.
524 ******************************************************************************/
525 static void blackjack_drawtable(struct game_context
* bj
) {
526 unsigned int w
, h
, y_loc
;
530 rb
->lcd_getstringsize("Bet", &w
, &h
);
531 rb
->lcd_putsxy(LCD_WIDTH
- w
, 2*h
+ 1, "Bet");
532 rb
->snprintf(str
, 9, "$%d", bj
->current_bet
);
533 rb
->lcd_getstringsize(str
, &w
, &h
);
534 rb
->lcd_putsxy(LCD_WIDTH
- w
, 3*h
+ 1, str
);
535 y_loc
= LCD_HEIGHT
/2;
537 rb
->lcd_getstringsize("Bet", &w
, &h
);
538 rb
->lcd_putsxy(LCD_WIDTH
- w
, 5*h
/ 2, "Bet");
539 rb
->snprintf(str
, 9, "$%d", bj
->current_bet
);
540 rb
->lcd_getstringsize(str
, &w
, &h
);
541 rb
->lcd_putsxy(LCD_WIDTH
- w
, 7*h
/ 2, str
);
542 rb
->lcd_hline(0, LCD_WIDTH
, LCD_HEIGHT
/2);
543 y_loc
= LCD_HEIGHT
/2 + h
;
546 rb
->lcd_putsxy(0,0, "Dealer");
547 rb
->lcd_getstringsize("Player", &w
, &h
);
548 rb
->lcd_putsxy(0, y_loc
, "Player");
549 rb
->lcd_getstringsize("Total", &w
, &h
);
550 rb
->lcd_putsxy(LCD_WIDTH
- w
, y_loc
, "Total");
551 rb
->lcd_getstringsize("Money", &w
, &h
);
552 rb
->lcd_putsxy(LCD_WIDTH
- w
, 0, "Money");
553 rb
->snprintf(str
, 9, "$%d", bj
->player_money
- bj
->current_bet
);
554 rb
->lcd_getstringsize(str
, &w
, &h
);
555 rb
->lcd_putsxy(LCD_WIDTH
- w
, h
+ 1, str
);
556 rb
->snprintf(str
, 3, "%d", bj
->player_total
);
557 rb
->lcd_getstringsize(str
, &w
, &h
);
558 rb
->lcd_putsxy(LCD_WIDTH
- w
, y_loc
+ h
, str
);
561 /*****************************************************************************
562 * find_value() is passed a card and returns its blackjack value.
563 ******************************************************************************/
564 static unsigned int find_value(unsigned int number
) {
565 unsigned int thisValue
;
567 thisValue
= 11; /* Aces get a value of 11 at first */
568 else if (number
< 10)
569 thisValue
= number
+ 1;
571 thisValue
= 10; /* Anything 10 or higher gets a value of 10 */
576 /*****************************************************************************
577 * draw_card() draws a card to the screen.
578 ******************************************************************************/
579 static void draw_card(struct card temp_card
, bool shown
,
580 unsigned int x
, unsigned int y
) {
582 rb
->lcd_bitmap_part(card_deck
, CARD_WIDTH
*temp_card
.num
,
583 CARD_HEIGHT
*temp_card
.suit
, BMPWIDTH_card_deck
,
584 x
+1, y
+1, CARD_WIDTH
, CARD_HEIGHT
);
586 rb
->lcd_bitmap(card_back
, x
+1, y
+1,CARD_WIDTH
, CARD_HEIGHT
);
588 rb
->lcd_set_foreground(LCD_BLACK
);
593 rb
->lcd_hline(x
+2, x
+CARD_WIDTH
-1, y
);
594 rb
->lcd_hline(x
+2, x
+CARD_WIDTH
-1, y
+CARD_HEIGHT
+1);
595 rb
->lcd_vline(x
, y
+2, y
+CARD_HEIGHT
-3);
596 rb
->lcd_vline(x
+CARD_WIDTH
+1, y
+2, y
+CARD_HEIGHT
-1);
597 rb
->lcd_drawpixel(x
+1, y
+1);
598 rb
->lcd_drawpixel(x
+1, y
+CARD_HEIGHT
);
599 rb
->lcd_drawpixel(x
+CARD_WIDTH
, y
+1);
600 rb
->lcd_drawpixel(x
+CARD_WIDTH
, y
+CARD_HEIGHT
);
602 rb
->lcd_hline(x
+1, x
+CARD_WIDTH
, y
);
603 rb
->lcd_hline(x
+1, x
+CARD_WIDTH
, y
+CARD_HEIGHT
+1);
604 rb
->lcd_vline(x
, y
+1, y
+CARD_HEIGHT
);
605 rb
->lcd_vline(x
+CARD_WIDTH
+1, y
+1, y
+CARD_HEIGHT
);
609 rb
->lcd_set_foreground(FG_COLOR
);
613 /*****************************************************************************
614 * new_card() initializes a new card and gives it values.
615 ******************************************************************************/
616 static struct card
new_card(void) {
617 struct card new_card
;
618 new_card
.suit
= rb
->rand()%4; /* Random number 0-3 */
619 new_card
.num
= rb
->rand()%13; /* Random number 0-12 */
620 new_card
.value
= find_value(new_card
.num
);
621 new_card
.is_soft_ace
= new_card
.num
== 0 ? true : false;
625 /*****************************************************************************
626 * deal_init_card() deals and draws to the screen the player's and dealer's
628 ******************************************************************************/
629 static void deal_init_cards(struct game_context
* bj
) {
630 bj
->dealer_cards
[0] = new_card();
631 bj
->dealer_total
+= bj
->dealer_cards
[0].value
;
633 draw_card(bj
->dealer_cards
[0], false, dealer_x
, dealer_y
);
635 bj
->dealer_cards
[1] = new_card();
636 bj
->dealer_total
+= bj
->dealer_cards
[1].value
;
637 draw_card(bj
->dealer_cards
[1], true, dealer_x
+ CARD_WIDTH
+ 4, dealer_y
);
639 bj
->player_cards
[0][0] = new_card();
640 bj
->player_total
+= bj
->player_cards
[0][0].value
;
641 draw_card(bj
->player_cards
[0][0], true, player_x
, player_y
);
642 player_x
+= CARD_WIDTH
+ 4;
644 bj
->player_cards
[0][1] = new_card();
645 bj
->player_total
+= bj
->player_cards
[0][1].value
;
646 draw_card(bj
->player_cards
[0][1], true, player_x
, player_y
);
647 player_x
+= CARD_WIDTH
+ 4;
650 /*****************************************************************************
651 * redraw_board() redraws all the cards and the board
652 ******************************************************************************/
653 static void redraw_board(struct game_context
* bj
) {
654 unsigned int i
, n
, upper_bound
;
655 rb
->lcd_clear_display();
657 blackjack_drawtable(bj
);
660 upper_bound
= bj
->split_status
> 1 ? 2 : 1;
662 for (i
= 0; i
< bj
->num_dealer_cards
; i
++) {
664 draw_card(bj
->dealer_cards
[0], false, dealer_x
, dealer_y
);
666 /* increment i so the dealer's first card isn't displayed */
668 dealer_x
+= CARD_WIDTH
+ 4;
670 draw_card(bj
->dealer_cards
[i
], true, dealer_x
, dealer_y
);
672 if (bj
->num_dealer_cards
> MAX_CARDS
-1)
675 dealer_x
+= CARD_WIDTH
+ 4;
678 for (n
= 0; n
< upper_bound
; n
++) {
679 for (i
= 0; i
< bj
->num_player_cards
[n
]; i
++) {
680 draw_card(bj
->player_cards
[n
][i
], true, player_x
, player_y
);
681 if (bj
->split_status
>1 || bj
->num_player_cards
[n
]>MAX_CARDS
)
684 player_x
+= CARD_WIDTH
+ 4;
686 if (bj
->split_status
> 1)
687 player_x
= LCD_WIDTH
/2 + 4;
691 /*****************************************************************************
692 * update_total updates the player's total
693 ******************************************************************************/
694 static void update_total(struct game_context
* bj
) {
697 rb
->snprintf(total
, 3, "%d", bj
->player_total
);
698 rb
->lcd_getstringsize(total
, &w
, &h
);
702 rb
->lcd_putsxy(LCD_WIDTH
- w
, LCD_HEIGHT
/2 + h
, total
);
703 rb
->lcd_update_rect(LCD_WIDTH
- w
, LCD_HEIGHT
/2 + h
, w
, h
);
707 /*****************************************************************************
708 * check_for_aces() is passed an array of cards and returns where an ace is
709 * located. Otherwise, returns -1.
710 ******************************************************************************/
711 static signed int check_for_aces(struct card temp_cards
[], unsigned int size
) {
713 for(i
= 0; i
< size
; i
++) {
714 if (temp_cards
[i
].is_soft_ace
== true)
720 /*****************************************************************************
721 * check_totals() compares player and dealer totals.
722 * 0: bust 1: loss, 2: push, 3: win, 4: blackjack, 5: something's not right...
723 ******************************************************************************/
724 static unsigned int check_totals(struct game_context
* bj
) {
726 if (bj
->player_total
> 21)
728 else if (bj
->player_total
== 21 && bj
->is_blackjack
) {
729 if (bj
->dealer_total
== 21 && bj
->num_dealer_cards
== 2)
734 else if (bj
->player_total
== bj
->dealer_total
)
736 else if (bj
->dealer_total
> 21 && bj
->player_total
< 22)
738 else if (bj
->dealer_total
> bj
->player_total
)
740 else if (bj
->player_total
> bj
->dealer_total
)
748 /*****************************************************************************
749 * finish_dealer() draws cards for the dealer until he has 17 or more.
750 ******************************************************************************/
751 static void finish_dealer(struct game_context
* bj
) {
754 if (bj
->dealer_total
> 16 && bj
->dealer_total
< 22)
757 while (bj
->dealer_total
< 17) {
758 bj
->dealer_cards
[bj
->num_dealer_cards
] = new_card();
759 bj
->dealer_total
+= bj
->dealer_cards
[bj
->num_dealer_cards
].value
;
760 bj
->num_dealer_cards
++;
763 while (bj
->dealer_total
> 21) {
764 temp
= check_for_aces(bj
->dealer_cards
, bj
->num_dealer_cards
);
766 bj
->dealer_cards
[temp
].is_soft_ace
= false;
767 bj
->dealer_total
-= 10;
774 /*****************************************************************************
775 * finish_game() completes the game once player's turn is over.
776 ******************************************************************************/
777 static void finish_game(struct game_context
* bj
) {
778 unsigned int rValue
, w
, h
;
783 } while (bj
->dealer_total
< 17);
786 rValue
= check_totals(bj
);
789 rb
->snprintf(str
, sizeof(str
), " Bust! ");
790 bj
->player_money
-= bj
->current_bet
;
792 else if (rValue
== 1) {
793 rb
->snprintf(str
, sizeof(str
), " Sorry, you lost. ");
794 bj
->player_money
-= bj
->current_bet
;
796 else if (rValue
== 2) {
797 rb
->snprintf(str
, sizeof(str
), " Push ");
799 else if (rValue
== 3) {
800 rb
->snprintf(str
, sizeof(str
), " You won! ");
801 bj
->player_money
+= bj
->current_bet
;
804 rb
->snprintf(str
, sizeof(str
), " Blackjack! ");
805 bj
->player_money
+= bj
->current_bet
* 3 / 2;
807 rb
->lcd_getstringsize(str
, &w
, &h
);
810 rb
->lcd_set_drawmode(DRMODE_BG
+DRMODE_INVERSEVID
);
811 rb
->lcd_fillrect(0, LCD_HEIGHT
/2, LCD_WIDTH
, LCD_HEIGHT
/2);
812 rb
->lcd_set_drawmode(DRMODE_SOLID
);
813 rb
->lcd_putsxy(LCD_WIDTH
/2 - w
/2, LCD_HEIGHT
/2 + h
, str
);
814 rb
->snprintf(str
, 12, "You have %d", bj
->player_total
);
815 rb
->lcd_getstringsize(str
, &w
, &h
);
816 rb
->lcd_putsxy(LCD_WIDTH
/2 - w
/2, LCD_HEIGHT
/2, str
);
818 rb
->lcd_putsxy(LCD_WIDTH
/2 - w
/2, LCD_HEIGHT
/2 - h
/2, str
);
823 /*****************************************************************************
824 * blackjack_loadgame() loads the saved game and returns load success.
825 ******************************************************************************/
826 static bool blackjack_loadgame(struct game_context
* bj
) {
831 fd
= rb
->open(SAVE_FILE
, O_RDONLY
);
832 if(fd
< 0) return loaded
;
834 /* read in saved game */
836 if(rb
->read(fd
, &bj
->player_money
, sizeof(bj
->player_money
)) <= 0)
838 if(rb
->read(fd
, &bj
->player_total
, sizeof(bj
->player_total
)) <= 0)
840 if(rb
->read(fd
, &bj
->dealer_total
, sizeof(bj
->dealer_total
)) <= 0)
842 if(rb
->read(fd
, &bj
->num_player_cards
, sizeof(bj
->num_player_cards
))<=0)
844 if(rb
->read(fd
, &bj
->num_dealer_cards
, sizeof(bj
->num_dealer_cards
))<=0)
846 if(rb
->read(fd
, &bj
->current_bet
, sizeof(bj
->current_bet
)) <= 0)
848 if(rb
->read(fd
, &bj
->is_blackjack
, sizeof(bj
->is_blackjack
)) <= 0)
850 if(rb
->read(fd
, &bj
->split_status
, sizeof(bj
->split_status
)) <= 0)
852 if(rb
->read(fd
, &bj
->asked_insurance
, sizeof(bj
->asked_insurance
)) <= 0)
854 if(rb
->read(fd
, &bj
->end_hand
, sizeof(bj
->end_hand
)) <= 0)
856 if(rb
->read(fd
, &bj
->player_cards
, sizeof(bj
->player_cards
)) <= 0)
858 if(rb
->read(fd
, &bj
->dealer_cards
, sizeof(bj
->dealer_cards
)) <= 0)
867 /* delete saved file */
868 rb
->remove(SAVE_FILE
);
872 /*****************************************************************************
873 * blackjack_savegame() saves the current game state.
874 ******************************************************************************/
875 static void blackjack_savegame(struct game_context
* bj
) {
878 /* write out the game state to the save file */
879 fd
= rb
->open(SAVE_FILE
, O_WRONLY
|O_CREAT
);
880 rb
->write(fd
, &bj
->player_money
, sizeof(bj
->player_money
));
881 rb
->write(fd
, &bj
->player_total
, sizeof(bj
->player_total
));
882 rb
->write(fd
, &bj
->dealer_total
, sizeof(bj
->dealer_total
));
883 rb
->write(fd
, &bj
->num_player_cards
, sizeof(bj
->num_player_cards
));
884 rb
->write(fd
, &bj
->num_dealer_cards
, sizeof(bj
->num_dealer_cards
));
885 rb
->write(fd
, &bj
->current_bet
, sizeof(bj
->current_bet
));
886 rb
->write(fd
, &bj
->is_blackjack
, sizeof(bj
->is_blackjack
));
887 rb
->write(fd
, &bj
->split_status
, sizeof(bj
->split_status
));
888 rb
->write(fd
, &bj
->asked_insurance
, sizeof(bj
->asked_insurance
));
889 rb
->write(fd
, &bj
->end_hand
, sizeof(bj
->end_hand
));
890 rb
->write(fd
, &bj
->player_cards
, sizeof(bj
->player_cards
));
891 rb
->write(fd
, &bj
->dealer_cards
, sizeof(bj
->dealer_cards
));
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]) {
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
};
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
);
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
);
928 rb
->lcd_drawrect(LCD_WIDTH
/2 - w
/2 - 1, LCD_HEIGHT
/2 + b
- 1, w
+3, h
+4);
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,
934 button
= rb
->button_get(true);
938 case (BJACK_LEFT
|BUTTON_REPEAT
):
940 case (BJACK_RIGHT
|BUTTON_REPEAT
):
943 case BJACK_SELECT
: breakout
= true;
945 case BJACK_QUIT
: breakout
= true;
952 rb
->lcd_set_foreground(FG_COLOR
);
953 rb
->lcd_set_background(BG_COLOR
);
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
,
966 bool changed
= false;
970 rb
->lcd_getstringsize("A", &w
, &h
); /* find the size of one character */
972 if (start
> upper_limit
)
973 amount
= upper_limit
;
974 else if (start
< lower_limit
)
975 amount
= lower_limit
;
980 rb
->lcd_set_background(LCD_WHITE
);
981 rb
->lcd_set_foreground(LCD_BLACK
);
985 rb
->lcd_clear_display();
986 rb
->lcd_puts(0, 1, message
);
987 rb
->snprintf(str
, 9, "$%d", amount
);
988 rb
->lcd_puts(0, 2, str
);
989 rb
->lcd_puts(0, 3, "RIGHT: +1");
990 rb
->lcd_puts(0, 4, "LEFT: -1");
991 rb
->lcd_puts(0, 5, "UP: +10");
992 rb
->lcd_puts(0, 6, "DOWN: -10");
995 rb
->lcd_set_drawmode(DRMODE_BG
+DRMODE_INVERSEVID
);
996 rb
->lcd_fillrect(LCD_WIDTH
/2 - 9*w
- 1, LCD_HEIGHT
/2 - 4*h
- 3,
998 rb
->lcd_set_drawmode(DRMODE_SOLID
);
999 rb
->lcd_drawrect(LCD_WIDTH
/2 - 9*w
- 1, LCD_HEIGHT
/2 - 4*h
- 3,
1001 rb
->lcd_putsxy(LCD_WIDTH
/2 - 9*w
, LCD_HEIGHT
/2 - 4*h
- 1, message
);
1002 rb
->snprintf(str
, 9, "$%d", amount
);
1003 rb
->lcd_putsxy(LCD_WIDTH
/2 - 9*w
, LCD_HEIGHT
/2 - 3*h
, str
);
1004 #if (CONFIG_KEYPAD == IPOD_4G_PAD) || \
1005 (CONFIG_KEYPAD == IPOD_3G_PAD) || \
1006 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
1007 rb
->lcd_putsxy(LCD_WIDTH
/2 - 9*w
, LCD_HEIGHT
/2 - h
-2, " >>|: +1");
1008 rb
->lcd_putsxy(LCD_WIDTH
/2 - 9*w
, LCD_HEIGHT
/2 - 1, " |<<: -1");
1009 rb
->lcd_putsxy(LCD_WIDTH
/2 - 9*w
, LCD_HEIGHT
/2 + h
, "SCROLL+: +10");
1010 rb
->lcd_putsxy(LCD_WIDTH
/2 - 9*w
, LCD_HEIGHT
/2 + 2*h
+ 1, "SCROLL-: -10");
1011 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
1012 rb
->lcd_putsxy(LCD_WIDTH
/2 - 9*w
, LCD_HEIGHT
/2 - h
-2, "RIGHT: +1");
1013 rb
->lcd_putsxy(LCD_WIDTH
/2 - 9*w
, LCD_HEIGHT
/2 - 1, "LEFT: -1");
1014 rb
->lcd_putsxy(LCD_WIDTH
/2 - 9*w
, LCD_HEIGHT
/2 + h
, "SCROLL+: +10");
1015 rb
->lcd_putsxy(LCD_WIDTH
/2 - 9*w
, LCD_HEIGHT
/2 + 2*h
+ 1, "SCROLL-: -10");
1017 rb
->lcd_putsxy(LCD_WIDTH
/2 - 9*w
, LCD_HEIGHT
/2 - h
-2, "RIGHT: +1");
1018 rb
->lcd_putsxy(LCD_WIDTH
/2 - 9*w
, LCD_HEIGHT
/2 - 1, "LEFT: -1");
1019 rb
->lcd_putsxy(LCD_WIDTH
/2 - 9*w
, LCD_HEIGHT
/2 + h
, "UP: +10");
1020 rb
->lcd_putsxy(LCD_WIDTH
/2 - 9*w
, LCD_HEIGHT
/2 + 2*h
+ 1, "DOWN: -10");
1022 rb
->lcd_update_rect(LCD_WIDTH
/2 - 9*w
- 1, LCD_HEIGHT
/2 - 4*h
- 3,
1027 button
= rb
->button_get(true);
1031 case (BJACK_UP
|BUTTON_REPEAT
):
1032 if (amount
+ 10 < upper_limit
+ 1) {
1038 case (BJACK_DOWN
|BUTTON_REPEAT
):
1039 if (amount
- 10 > lower_limit
- 1) {
1045 case (BJACK_RIGHT
|BUTTON_REPEAT
):
1046 if (amount
+ 1 < upper_limit
+ 1) {
1052 case (BJACK_LEFT
|BUTTON_REPEAT
):
1053 if (amount
- 1 > lower_limit
- 1) {
1059 amount
= upper_limit
;
1063 amount
= lower_limit
;
1070 rb
->lcd_set_foreground(FG_COLOR
);
1071 rb
->lcd_set_background(BG_COLOR
);
1073 rb
->lcd_clear_display();
1078 rb
->snprintf(str
, 9, "$%d", amount
);
1079 #if LCD_HEIGHT <= 64
1080 rb
->lcd_puts(0, 2, str
);
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_putsxy(LCD_WIDTH
/2 - 9*w
, LCD_HEIGHT
/2 - 3*h
, str
);
1087 rb
->lcd_update_rect(LCD_WIDTH
/2 - 9*w
, LCD_HEIGHT
/2 - 3*h
, 5*w
, h
);
1094 /*****************************************************************************
1095 * blackjack_get_bet() gets the player's bet.
1096 ******************************************************************************/
1097 static void blackjack_get_bet(struct game_context
* bj
) {
1098 bj
->current_bet
= blackjack_get_amount("Please enter a bet", 10,
1099 bj
->player_money
, bj
->current_bet
);
1102 /*****************************************************************************
1103 * double_down() returns one final card then finishes the game
1104 ******************************************************************************/
1105 static void double_down(struct game_context
* bj
) {
1106 bj
->current_bet
*= 2;
1107 bj
->player_cards
[0][bj
->num_player_cards
[0]] = new_card();
1108 bj
->player_total
+= bj
->player_cards
[0][bj
->num_player_cards
[0]].value
;
1109 bj
->num_player_cards
[0]++;
1112 /*****************************************************************************
1113 * split() checks if the player wants to split and acts accordingly.
1114 * When bj->split_status is 1, no split occurred. 2 means the player split and 3
1115 * means a split has already occurred and the first hand is done.
1116 ******************************************************************************/
1117 static void split(struct game_context
* bj
) {
1118 if (blackjack_get_yes_no("Split?") == 1)
1119 bj
->split_status
= 1;
1121 bj
->split_status
= 2;
1122 bj
->current_bet
*= 2;
1123 bj
->num_player_cards
[0] = 1;
1124 bj
->num_player_cards
[1] = 1;
1125 bj
->player_cards
[1][0] = bj
->player_cards
[0][1];
1126 bj
->player_total
= bj
->player_cards
[0][0].value
;
1130 /*****************************************************************************
1131 * insurance() see if the player wants to buy insurance and how much.
1132 ******************************************************************************/
1133 static unsigned int insurance(struct game_context
* bj
) {
1134 unsigned int insurance
, max_amount
;
1136 insurance
= blackjack_get_yes_no("Buy Insurance?");
1137 bj
->asked_insurance
= true;
1138 max_amount
= bj
->current_bet
< (unsigned int)bj
->player_money
?
1139 bj
->current_bet
/2 : (unsigned int)bj
->player_money
;
1140 if (insurance
== 1) return 0;
1142 insurance
= blackjack_get_amount("How much?", 0, max_amount
, 0);
1147 /*****************************************************************************
1148 * play_again() checks to see if the player wants to keep playing.
1149 ******************************************************************************/
1150 static unsigned int play_again(void) {
1151 return blackjack_get_yes_no("Play Again?");
1154 /*****************************************************************************
1155 * blackjack_help() displays help text.
1156 ******************************************************************************/
1157 static bool blackjack_help(void) {
1158 #define WORDS (sizeof help_text / sizeof (char*))
1159 static char *help_text
[] = {
1161 "The", "goal", "is", "to", "get", "21.", "", "",
1163 BJACK_SELECT_NAME
, ":", "hit", "/", "select", "",
1164 BJACK_STAY_NAME
, ":", "stay", "",
1165 BJACK_DOUBLE_NAME
, ":", "double", "down", "",
1166 BJACK_QUIT_NAME
, ":", "Go", "to", "menu", "without", "save", "",
1167 BJACK_RESUME_NAME
, ":", "Save", "and", "go", "to", "menu", "",
1170 static struct style_text formation
[]={
1171 { 0, TEXT_CENTER
|TEXT_UNDERLINE
},
1172 { 12, C_RED
}, /* Hit/Select */
1173 { 18, C_RED
}, /* Stay */
1174 { 22, C_RED
}, /* Double Down */
1175 { 27, C_RED
}, /* Quit */
1176 { 35, C_RED
}, /* Save */
1181 rb
->lcd_setfont(FONT_UI
);
1182 #ifdef HAVE_LCD_COLOR
1183 rb
->lcd_set_background(LCD_BLACK
);
1184 rb
->lcd_set_foreground(LCD_WHITE
);
1187 if (display_text(WORDS
, help_text
, formation
, NULL
))
1190 button
= rb
->button_get(true);
1191 if (rb
->default_event_handler(button
) == SYS_USB_CONNECTED
) {
1194 } while( ( button
== BUTTON_NONE
)
1195 || ( button
& (BUTTON_REL
|BUTTON_REPEAT
) ) );
1196 rb
->lcd_setfont(FONT_SYSFIXED
);
1200 /*****************************************************************************
1201 * blackjack_menu() is the initial menu at the start of the game.
1202 ******************************************************************************/
1203 static unsigned int blackjack_menu(struct game_context
* bj
) {
1205 bool breakout
= false;
1207 MENUITEM_STRINGLIST(menu
, "BlackJack Menu", NULL
,
1208 "Start Game","Resume Game",
1209 "High Scores", "Help",
1210 "Playback Control", "Quit");
1213 switch(rb
->do_menu(&menu
, &selection
, NULL
, false)) {
1218 if(!blackjack_loadgame(bj
)) {
1219 rb
->splash(HZ
*2, "Nothing to resume");
1225 highscore_show(NUM_SCORES
, highest
, NUM_SCORES
, false);
1228 if(blackjack_help())
1232 if (playback_control(NULL
))
1238 case MENU_ATTACHED_USB
:
1249 /*****************************************************************************
1250 * blackjack() is the main game subroutine, it returns the final game status.
1251 ******************************************************************************/
1252 static int blackjack(struct game_context
* bj
) {
1254 unsigned int w
, h
, temp_var
, done
= 0, todo
= 1;
1256 bool breakout
= false;
1257 bool dbl_down
= false;
1260 rb
->lcd_set_background(BG_COLOR
);
1261 rb
->lcd_set_foreground(FG_COLOR
);
1264 /* don't resume by default */
1267 /********************
1269 ********************/
1270 temp_var
= blackjack_menu(bj
);
1271 if (temp_var
== BJ_QUIT
|| temp_var
== BJ_USB
)
1275 /********************
1277 ********************/
1280 /********************
1282 ********************/
1284 /* check for resumed game */
1288 if (bj
->split_status
== 2) {
1290 player_x
= bj
->num_player_cards
[0] * 10 + 4;
1292 else if (bj
->split_status
== 3) {
1293 player_x
= bj
->num_player_cards
[1] * 10 + LCD_WIDTH
/2 + 4;
1299 bj
->player_money
= 1000;
1300 bj
->current_bet
= 10;
1301 blackjack_get_bet(bj
);
1302 if (bj
->current_bet
== 0)
1304 rb
->lcd_clear_display();
1305 deal_init_cards(bj
);
1306 blackjack_drawtable(bj
);
1314 if(bj
->player_total
== 21 && bj
->num_player_cards
[0] == 2) {
1315 bj
->is_blackjack
= true;
1316 bj
->end_hand
= true;
1319 else if(bj
->dealer_cards
[1].is_soft_ace
&& !breakout
&&
1320 !bj
->asked_insurance
) {
1321 temp_var
= insurance(bj
);
1322 if (bj
->dealer_total
== 21) {
1323 rb
->splash(HZ
, "Dealer has blackjack");
1324 bj
->player_money
+= temp_var
;
1325 bj
->end_hand
= true;
1331 rb
->splash(HZ
, "Dealer does not have blackjack");
1332 bj
->player_money
-= temp_var
;
1338 if(!bj
->end_hand
&& bj
->split_status
== 0 &&
1339 bj
->player_cards
[0][0].num
== bj
->player_cards
[0][1].num
) {
1342 rb
->lcd_update_rect(0, LCD_HEIGHT
/2, LCD_WIDTH
, LCD_HEIGHT
/2);
1343 if (bj
->split_status
== 2) {
1345 player_x
= bj
->num_player_cards
[0] * 10 + 4;
1349 while(!bj
->end_hand
&& done
< todo
) {
1350 button
= rb
->button_get(true);
1354 NEXT_CARD
= new_card();
1355 bj
->player_total
+= NEXT_CARD
.value
;
1356 draw_card(NEXT_CARD
, true, player_x
, player_y
);
1357 bj
->num_player_cards
[done
]++;
1358 if (bj
->num_player_cards
[done
] == MAX_CARDS
+ 1) {
1360 rb
->lcd_update_rect(0, LCD_HEIGHT
/2, LCD_WIDTH
,
1363 else if (bj
->num_player_cards
[done
]>MAX_CARDS
|| todo
> 1) {
1364 rb
->lcd_update_rect(player_x
, player_y
, CARD_WIDTH
+2,
1369 rb
->lcd_update_rect(player_x
, player_y
, CARD_WIDTH
+2,
1371 player_x
+= CARD_WIDTH
+ 4;
1377 bj
->end_hand
= true;
1379 case BJACK_DOUBLEDOWN
:
1380 if ((signed int)bj
->current_bet
* 2 <
1381 bj
->player_money
+ 1 &&
1382 bj
->num_player_cards
[0]==2 && todo
==1) {
1385 if (bj
->player_total
< 22) {
1386 bj
->end_hand
= true;
1390 else if((signed int)bj
->current_bet
* 2 >
1392 rb
->splash(HZ
, "Not enough money to double down.");
1397 case BJACK_RESUME
: /* save and end game */
1398 rb
->splash(HZ
, "Saving game...");
1399 blackjack_savegame(bj
);
1400 /* fall through to BJACK_QUIT */
1406 while (bj
->player_total
> 21 && !bj
->end_hand
) {
1407 temp
= check_for_aces(bj
->player_cards
[done
],
1408 bj
->num_player_cards
[done
]);
1410 bj
->player_cards
[done
][temp
].is_soft_ace
= false;
1411 bj
->player_total
-= 10;
1414 bj
->end_hand
= true;
1419 bj
->end_hand
= true;
1426 temp
= bj
->player_total
;
1427 bj
->player_total
= temp_var
;
1430 rb
->lcd_getstringsize(" Split 1 ", &w
, &h
);
1431 rb
->lcd_putsxy(LCD_WIDTH
/2-w
/2, LCD_HEIGHT
/2-3*h
/2,
1433 rb
->lcd_update_rect(LCD_WIDTH
/2-w
/2, LCD_HEIGHT
/2-3*h
/2,
1435 bj
->current_bet
/= 2;
1436 rb
->lcd_update_rect(LCD_WIDTH
/2-w
/2, LCD_HEIGHT
/2-3*h
/2,
1439 bj
->player_total
= temp_var
;
1441 rb
->lcd_getstringsize(" Split 2 ", &w
, &h
);
1442 rb
->lcd_putsxy(LCD_WIDTH
/2-w
/2, LCD_HEIGHT
/2-3*h
/2,
1444 rb
->lcd_update_rect(LCD_WIDTH
/2-w
/2, LCD_HEIGHT
/2-3*h
/2,
1449 bj
->end_hand
= false;
1450 bj
->split_status
= 3;
1451 temp_var
= bj
->player_total
;
1452 bj
->player_total
= bj
->player_cards
[1][0].value
;
1464 if (bj
->player_money
< 10) {
1469 if (bj
->end_hand
) { /* If hand is over */
1470 if (play_again() != 0) /* User wants to quit */
1472 else { /* User keeps playing */
1474 temp
= bj
->current_bet
;
1475 bj
->current_bet
= 0;
1478 bj
->current_bet
= temp
;
1480 bj
->current_bet
/= 2;
1486 blackjack_get_bet(bj
);
1487 if (bj
->current_bet
== 0)
1489 deal_init_cards(bj
);
1490 blackjack_drawtable(bj
);
1499 /*****************************************************************************
1500 * plugin entry point.
1501 ******************************************************************************/
1502 enum plugin_status
plugin_start(const void* parameter
)
1504 struct game_context bj
;
1510 rb
->lcd_set_backdrop(NULL
);
1513 /* load high scores */
1514 highscore_load(HIGH_SCORE
,highest
,NUM_SCORES
);
1516 rb
->lcd_setfont(FONT_SYSFIXED
);
1519 switch(blackjack(&bj
)){
1521 rb
->splash(HZ
, "Not enough money to continue");
1522 /* fall through to BJ_END */
1525 if(!bj
.resume
&& bj
.player_money
> 10) {
1526 /* There is no level, so store -1 to blank column */
1527 int position
= highscore_update(bj
.player_money
, -1, "",
1528 highest
, NUM_SCORES
);
1529 if (position
== 0) {
1530 rb
->splash(HZ
*2, "New High Score");
1532 if (position
!= -1) {
1533 highscore_show(position
, highest
, NUM_SCORES
, false);
1539 rb
->lcd_setfont(FONT_UI
);
1540 highscore_save(HIGH_SCORE
,highest
,NUM_SCORES
);
1541 return PLUGIN_USB_CONNECTED
;
1544 highscore_save(HIGH_SCORE
,highest
,NUM_SCORES
);
1553 rb
->lcd_setfont(FONT_UI
);