summaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
authorLinus Nielsen Feltzing <linus@haxx.se>2004-08-21 23:05:36 +0000
committerLinus Nielsen Feltzing <linus@haxx.se>2004-08-21 23:05:36 +0000
commit1e9de584f604f7d9da4e2e1ee7ce25c909ec1969 (patch)
tree501ce92d31f0232c5702b702482d5df9540e7b4d /apps
parentae7df4d0ac4c88d77a95f6056d105f7c0ccf608a (diff)
downloadrockbox-1e9de584f604f7d9da4e2e1ee7ce25c909ec1969.tar.gz
rockbox-1e9de584f604f7d9da4e2e1ee7ce25c909ec1969.zip
Patch #1011849 by Antoine Cellerier
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@5003 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps')
-rw-r--r--apps/plugins/solitaire.c637
1 files changed, 349 insertions, 288 deletions
diff --git a/apps/plugins/solitaire.c b/apps/plugins/solitaire.c
index 04fde17415..f2d26638af 100644
--- a/apps/plugins/solitaire.c
+++ b/apps/plugins/solitaire.c
@@ -21,8 +21,7 @@
21Solitaire by dionoea 21Solitaire by dionoea
22 22
23use arrows to move the cursor 23use arrows to move the cursor
24use ON to select cards in the columns, move cards inside the columns, 24use ON to select cards, move cards, reveal hidden cards, ...
25 reveal hidden cards, ...
26use PLAY to move a card from the remains' stack to the top of the cursor 25use PLAY to move a card from the remains' stack to the top of the cursor
27use F1 to put card under cursor on one of the 4 final color stacks 26use F1 to put card under cursor on one of the 4 final color stacks
28use F2 to un-select card if a card was selected, else draw 3 new cards 27use F2 to un-select card if a card was selected, else draw 3 new cards
@@ -57,7 +56,7 @@ static struct plugin_api* rb;
57#define HELP_BUTTON_F2 "Un-select a card if it was selected. Else, draw 3 new cards out of the remains' stack." 56#define HELP_BUTTON_F2 "Un-select a card if it was selected. Else, draw 3 new cards out of the remains' stack."
58#define HELP_BUTTON_F3 "Put the card on top of the remains' stack on one of the 4 final color stacks." 57#define HELP_BUTTON_F3 "Put the card on top of the remains' stack on one of the 4 final color stacks."
59#define HELP_BUTTON_PLAY "Put the card on top of the remains' stack on top of the cursor." 58#define HELP_BUTTON_PLAY "Put the card on top of the remains' stack on top of the cursor."
60#define HELP_BUTTON_ON "Select cards in the columns, Move cards inside the columns, reveal hidden cards ..." 59#define HELP_BUTTON_ON "Select cards, Move cards, reveal hidden cards ..."
61 60
62static unsigned char colors[4][8] = { 61static unsigned char colors[4][8] = {
63/* Spades */ 62/* Spades */
@@ -229,6 +228,14 @@ static unsigned char numbers[13][8] = {
229/* number of columns */ 228/* number of columns */
230#define COL_NUM 7 229#define COL_NUM 7
231 230
231/* pseudo column numbers to be used for cursor coordinates */
232/* columns COL_NUM t COL_NUM + COLORS - 1 correspond to the color stacks */
233#define STACKS_COL COL_NUM
234/* column COL_NUM + COLORS corresponds to the remains' stack */
235#define REM_COL (STACKS_COL + COLORS)
236
237#define NOT_A_COL 255
238
232/* number of cards that are drawn on the remains' stack (by pressing F2) */ 239/* number of cards that are drawn on the remains' stack (by pressing F2) */
233#define CARDS_PER_DRAW 3 240#define CARDS_PER_DRAW 3
234 241
@@ -261,14 +268,17 @@ unsigned char next_random_card(card *deck){
261} 268}
262 269
263/* help for the not so intuitive interface */ 270/* help for the not so intuitive interface */
264void solitaire_help(void) 271void solitaire_help(void){
265{ 272
266 rb->lcd_clear_display(); 273 rb->lcd_clear_display();
267 274
268 rb->lcd_putsxy(0, 0, "Press a key to see"); 275 rb->lcd_putsxy(0, 0, "Press a key to see");
269 rb->lcd_putsxy(0, 7, "it's role."); 276 rb->lcd_putsxy(0, 7, "it's role.");
270 rb->lcd_putsxy(0, 21, "Press OFF to"); 277 rb->lcd_putsxy(0, 21, "Press OFF to");
271 rb->lcd_putsxy(0, 28, "return to menu"); 278 rb->lcd_putsxy(0, 28, "return to menu.");
279 rb->lcd_putsxy(0, 42, "All actions can");
280 rb->lcd_putsxy(0, 49, "be done using");
281 rb->lcd_putsxy(0, 56, "arrows, ON and F2.");
272 282
273 rb->lcd_update(); 283 rb->lcd_update();
274 284
@@ -363,6 +373,7 @@ int solitaire_menu(unsigned char when) {
363 solitaire_help(); 373 solitaire_help();
364 break; 374 break;
365 } 375 }
376 break;
366 377
367 case BUTTON_F1: 378 case BUTTON_F1:
368 case BUTTON_F2: 379 case BUTTON_F2:
@@ -410,7 +421,7 @@ void solitaire_init(void){
410 for(j=0;j<CARDS_PER_COLOR;j++){ 421 for(j=0;j<CARDS_PER_COLOR;j++){
411 deck[i*CARDS_PER_COLOR+j].color = i; 422 deck[i*CARDS_PER_COLOR+j].color = i;
412 deck[i*CARDS_PER_COLOR+j].num = j; 423 deck[i*CARDS_PER_COLOR+j].num = j;
413 deck[i*CARDS_PER_COLOR+j].known = 0; 424 deck[i*CARDS_PER_COLOR+j].known = 1;
414 deck[i*CARDS_PER_COLOR+j].used = 0; 425 deck[i*CARDS_PER_COLOR+j].used = 0;
415 deck[i*CARDS_PER_COLOR+j].next = NOT_A_CARD; 426 deck[i*CARDS_PER_COLOR+j].next = NOT_A_CARD;
416 } 427 }
@@ -428,7 +439,7 @@ void solitaire_init(void){
428 deck[c].next = next_random_card(deck); 439 deck[c].next = next_random_card(deck);
429 c = deck[c].next; 440 c = deck[c].next;
430 } 441 }
431 if(j==i) deck[c].known = 1; 442 if(j<i) deck[c].known = 0;
432 } 443 }
433 } 444 }
434 445
@@ -459,15 +470,187 @@ void solitaire_init(void){
459 cur_rem = NOT_A_CARD; 470 cur_rem = NOT_A_CARD;
460} 471}
461 472
473/* find the column number in which 'card' can be found */
474unsigned char find_card_col(unsigned char card){
475 int i;
476 unsigned char c;
477
478 if(card == NOT_A_CARD) return NOT_A_COL;
479
480 for(i=0; i<COL_NUM; i++){
481 c = cols[i];
482 while(c!=NOT_A_CARD){
483 if(c == card) return i;
484 c = deck[c].next;
485 }
486 }
487
488 for(i=0; i<COLORS; i++){
489 c = stacks[i];
490 while(c!=NOT_A_CARD){
491 if(c == card) return STACKS_COL + i;
492 c = deck[c].next;
493 }
494 }
495
496 return REM_COL;
497}
498
499/* find the card preceding 'card' */
500/* if it doesn't exist, return NOT_A_CARD */
501unsigned char find_prev_card(unsigned char card){
502 int i;
503
504 for(i=0; i<COLORS*CARDS_PER_COLOR; i++){
505 if(deck[i].next == card) return i;
506 }
507
508 return NOT_A_CARD;
509}
510
511/* find the last card of a given column */
512unsigned char find_last_card(unsigned char col){
513 unsigned char c;
514
515 if(col < COL_NUM){
516 c = cols[col];
517 } else if(col < REM_COL){
518 c = stacks[col - STACKS_COL];
519 } else {
520 c = rem;
521 }
522
523 if(c == NOT_A_CARD)
524 return c;
525 else {
526 while(deck[c].next != NOT_A_CARD){
527 c = deck[c].next;
528 }
529 return c;
530 }
531}
532
533#define MOVE_OK 0
534#define MOVE_NOT_OK 1
535unsigned char move_card(unsigned char dest_col, unsigned char src_card){
536 /* the column on which to take src_card */
537 unsigned char src_col;
538
539 /* the last card of dest_col */
540 unsigned char dest_card;
541
542 /* the card under src_card */
543 unsigned char src_card_prev;
544
545 /* you can't move no card (at least, it doesn't have any consequence) */
546 if(src_card == NOT_A_CARD) return MOVE_NOT_OK;
547 /* you can't put a card back on the remains' stack */
548 if(dest_col == REM_COL) return MOVE_NOT_OK;
549
550 src_col = find_card_col(src_card);
551 dest_card = find_last_card(dest_col);
552 src_card_prev = find_prev_card(src_card);
553
554 /* you can't move more than one card at a time from the colors stack */
555 /* to the rest of the game */
556 if(src_col >= COL_NUM && src_col < REM_COL
557 && deck[src_card].next != NOT_A_CARD){
558 return MOVE_NOT_OK;
559 }
560
561 /* if we (that means dest) are on one of the 7 columns ... */
562 if(dest_col < COL_NUM){
563 /* ... check is we are on an empty color and that the src is a king */
564 if(dest_card == NOT_A_CARD
565 && deck[src_card].num == CARDS_PER_COLOR - 1){
566 /* this is a winning combination */
567 cols[dest_col] = src_card;
568 }
569 /* ... or check if the cards follow one another and have same color */
570 else if((deck[dest_card].color + deck[src_card].color)%2==1
571 && deck[dest_card].num == deck[src_card].num + 1){
572 /* this is a winning combination */
573 deck[dest_card].next = src_card;
574 }
575 /* ... or, humpf, well that's not good news */
576 else {
577 /* this is not a winning combination */
578 return MOVE_NOT_OK;
579 }
580 }
581 /* if we are on one of the 4 color stacks ... */
582 else if(dest_col < REM_COL){
583 /* ... check if we are on an empty stack, that the src is an
584 * ace and that this is the good color stack */
585 if(dest_card == NOT_A_CARD
586 && deck[src_card].num == 0
587 && deck[src_card].color == dest_col - STACKS_COL){
588 /* this is a winning combination */
589 stacks[dest_col - STACKS_COL] = src_card;
590 }
591 /* ... or check if the cards follow one another, have the same
592 * color and {that src has no .next element or is from the remains'
593 * stack} */
594 else if(deck[dest_card].color == deck[src_card].color
595 && deck[dest_card].num + 1 == deck[src_card].num
596 && (deck[src_card].next == NOT_A_CARD || src_col == REM_COL) ){
597 /* this is a winning combination */
598 deck[dest_card].next = src_card;
599 }
600 /* ... or, well that's not good news */
601 else {
602 /* this is not a winnong combination */
603 return MOVE_NOT_OK;
604 }
605 }
606 /* if we are on the remains' stack */
607 else {
608 /* you can't move a card back to the remains' stack */
609 return MOVE_NOT_OK;
610 }
611
612 /* if the src card is from the remains' stack, we don't want to take
613 * the following cards */
614 if(src_col == REM_COL){
615 /* if src card is the first card from the stack */
616 if(src_card_prev == NOT_A_CARD){
617 rem = deck[src_card].next;
618 }
619 /* if src card is not the first card from the stack */
620 else {
621 deck[src_card_prev].next = deck[src_card].next;
622 }
623 cur_rem = src_card_prev;
624 deck[src_card].next = NOT_A_CARD;
625 }
626 /* if the src card is from somewhere else, just take everything */
627 else {
628 if(src_card_prev == NOT_A_CARD){
629 if(src_col < COL_NUM){
630 cols[src_col] = NOT_A_CARD;
631 } else {
632 stacks[src_col - STACKS_COL] = NOT_A_CARD;
633 }
634 } else {
635 deck[src_card_prev].next = NOT_A_CARD;
636 }
637 }
638
639 /* tada ! */
640 return MOVE_OK;
641}
642
643#define SOLITAIRE_WIN 0
644#define SOLITAIRE_QUIT 1
462 645
463/* the game */ 646/* the game */
464void solitaire(void){ 647int solitaire(void){
465 648
466 int i,j; 649 int i,j;
467 unsigned char c; 650 unsigned char c;
468 int biggest_col_length; 651 int biggest_col_length;
469 652
470 if(solitaire_menu(MENU_BEFOREGAME) == MENU_QUIT) return; 653 if(solitaire_menu(MENU_BEFOREGAME) == MENU_QUIT) return SOLITAIRE_QUIT;
471 solitaire_init(); 654 solitaire_init();
472 655
473 while(true){ 656 while(true){
@@ -491,7 +674,7 @@ void solitaire(void){
491 /* if there aren't any, that means you won :) */ 674 /* if there aren't any, that means you won :) */
492 if(biggest_col_length == 0 && rem == NOT_A_CARD){ 675 if(biggest_col_length == 0 && rem == NOT_A_CARD){
493 rb->splash(HZ*2, true, "You Won :)"); 676 rb->splash(HZ*2, true, "You Won :)");
494 return; 677 return SOLITAIRE_WIN;
495 } 678 }
496 679
497 /* draw the columns */ 680 /* draw the columns */
@@ -499,59 +682,48 @@ void solitaire(void){
499 c = cols[i]; 682 c = cols[i];
500 j = 0; 683 j = 0;
501 while(true){ 684 while(true){
502 if(c==NOT_A_CARD) break; 685 if(c==NOT_A_CARD) {
686 /* draw the cursor on empty columns */
687 if(cur_col == i){
688 rb->lcd_invertrect(i*(LCD_WIDTH - CARD_WIDTH)/COL_NUM+2, 2, CARD_WIDTH-3, CARD_HEIGHT-1);
689 }
690 break;
691 }
503 /* clear the card's spot */ 692 /* clear the card's spot */
504 rb->lcd_clearrect(i*(LCD_WIDTH - CARD_WIDTH)/COL_NUM, 693 rb->lcd_clearrect(i*(LCD_WIDTH - CARD_WIDTH)/COL_NUM, j+1, CARD_WIDTH, CARD_HEIGHT-1);
505 j+1, CARD_WIDTH, CARD_HEIGHT-1);
506 /* known card */ 694 /* known card */
507 if(deck[c].known) { 695 if(deck[c].known){
508 rb->lcd_bitmap(numbers[deck[c].num], 696 rb->lcd_bitmap(numbers[deck[c].num], i*(LCD_WIDTH - CARD_WIDTH)/COL_NUM+1, j, 8, 8, true);
509 i*(LCD_WIDTH - CARD_WIDTH)/COL_NUM+1, 697 rb->lcd_bitmap(colors[deck[c].color], i*(LCD_WIDTH - CARD_WIDTH)/COL_NUM+7, j, 8, 8, true);
510 j, 8, 8, true);
511 rb->lcd_bitmap(colors[deck[c].color],
512 i*(LCD_WIDTH - CARD_WIDTH)/COL_NUM+7,
513 j, 8, 8, true);
514 } 698 }
515 /* draw top line of the card */ 699 /* draw top line of the card */
516 rb->lcd_drawline(i*(LCD_WIDTH - CARD_WIDTH)/COL_NUM+1, 700 rb->lcd_drawline(i*(LCD_WIDTH - CARD_WIDTH)/COL_NUM+1,j,i*(LCD_WIDTH - CARD_WIDTH)/COL_NUM+CARD_WIDTH-1,j);
517 j,i*(LCD_WIDTH - CARD_WIDTH)/
518 COL_NUM+CARD_WIDTH-1,j);
519 /* selected card */ 701 /* selected card */
520 if(c == sel_card && sel_card != NOT_A_CARD){ 702 if(c == sel_card && sel_card != NOT_A_CARD){
521 rb->lcd_drawrect(i*(LCD_WIDTH - CARD_WIDTH)/COL_NUM+1, 703 rb->lcd_drawrect(i*(LCD_WIDTH - CARD_WIDTH)/COL_NUM+1, j+1, CARD_WIDTH-1, CARD_HEIGHT-1);
522 j+1, CARD_WIDTH-1, CARD_HEIGHT-1);
523 } 704 }
524 /* cursor (or not) */ 705 /* cursor (or not) */
525 if(c == cur_card){ 706 if(c == cur_card){
526 rb->lcd_invertrect(i*(LCD_WIDTH - CARD_WIDTH)/COL_NUM+1, 707 rb->lcd_invertrect(i*(LCD_WIDTH - CARD_WIDTH)/COL_NUM+1, j+1, CARD_WIDTH-1, CARD_HEIGHT-1);
527 j+1, CARD_WIDTH-1, CARD_HEIGHT-1);
528 /* go to the next card */ 708 /* go to the next card */
529 c = deck[c].next; 709 c = deck[c].next;
530 if(c == NOT_A_CARD) 710 if(c == NOT_A_CARD) break;
531 break;
532 j += CARD_HEIGHT - 2; 711 j += CARD_HEIGHT - 2;
533 } 712 } else {
534 else {
535 /* go to the next card */ 713 /* go to the next card */
536 c = deck[c].next; 714 c = deck[c].next;
537 if(c == NOT_A_CARD) 715 if(c == NOT_A_CARD) break;
538 break; 716 j += min(CARD_HEIGHT - 2, (LCD_HEIGHT - CARD_HEIGHT)/biggest_col_length);
539 j += min(CARD_HEIGHT - 2,
540 (LCD_HEIGHT - CARD_HEIGHT)/biggest_col_length);
541 } 717 }
542 } 718 }
543 /* draw line to the left of the column */ 719 if(cols[i]!=NOT_A_CARD){
544 rb->lcd_drawline(i*(LCD_WIDTH - CARD_WIDTH)/COL_NUM, 720 /* draw line to the left of the column */
545 1,i*(LCD_WIDTH - CARD_WIDTH)/COL_NUM, 721 rb->lcd_drawline(i*(LCD_WIDTH - CARD_WIDTH)/COL_NUM,1,i*(LCD_WIDTH - CARD_WIDTH)/COL_NUM,j+CARD_HEIGHT-1);
546 j+CARD_HEIGHT-1); 722 /* draw line to the right of the column */
547 /* draw line to the right of the column */ 723 rb->lcd_drawline(i*(LCD_WIDTH - CARD_WIDTH)/COL_NUM+CARD_WIDTH,1,i*(LCD_WIDTH - CARD_WIDTH)/COL_NUM+CARD_WIDTH,j+CARD_HEIGHT-1);
548 rb->lcd_drawline(i*(LCD_WIDTH - CARD_WIDTH)/COL_NUM+CARD_WIDTH, 724 /* draw bottom of the last card */
549 1,i*(LCD_WIDTH - CARD_WIDTH)/COL_NUM+CARD_WIDTH, 725 rb->lcd_drawline(i*(LCD_WIDTH - CARD_WIDTH)/COL_NUM+1,j+CARD_HEIGHT,i*(LCD_WIDTH - CARD_WIDTH)/COL_NUM+CARD_WIDTH-1,j+CARD_HEIGHT);
550 j+CARD_HEIGHT-1); 726 }
551 /* draw bottom of the last card */
552 rb->lcd_drawline(i*(LCD_WIDTH - CARD_WIDTH)/COL_NUM+1,
553 j+CARD_HEIGHT,i*(LCD_WIDTH - CARD_WIDTH)/COL_NUM+
554 CARD_WIDTH-1,j+CARD_HEIGHT);
555 } 727 }
556 728
557 /* draw the stacks */ 729 /* draw the stacks */
@@ -563,32 +735,43 @@ void solitaire(void){
563 } 735 }
564 } 736 }
565 if(c != NOT_A_CARD) { 737 if(c != NOT_A_CARD) {
566 rb->lcd_bitmap(numbers[deck[c].num], LCD_WIDTH - CARD_WIDTH+1, 738 rb->lcd_bitmap(numbers[deck[c].num], LCD_WIDTH - CARD_WIDTH+1, i*CARD_HEIGHT, 8, 8, true);
567 i*CARD_HEIGHT, 8, 8, true); 739 }
740 rb->lcd_bitmap(colors[i], LCD_WIDTH - CARD_WIDTH+7, i*CARD_HEIGHT, 8, 8, true);
741 /* draw a selected card */
742 if(c != NOT_A_CARD) {
743 if(sel_card == c){
744 rb->lcd_drawrect(LCD_WIDTH - CARD_WIDTH+1, i*CARD_HEIGHT + 1, CARD_WIDTH-1, CARD_HEIGHT-1);
745 }
746 }
747 rb->lcd_drawline(LCD_WIDTH - CARD_WIDTH+1,i*CARD_HEIGHT,LCD_WIDTH - 1,i*CARD_HEIGHT);
748 rb->lcd_drawline(LCD_WIDTH - CARD_WIDTH,i*CARD_HEIGHT+1,LCD_WIDTH - CARD_WIDTH,(i+1)*CARD_HEIGHT-1);
749 rb->lcd_drawline(LCD_WIDTH - CARD_WIDTH+1,(i+1)*CARD_HEIGHT,LCD_WIDTH - 1,(i+1)*CARD_HEIGHT);
750 /* draw the cursor on one of the stacks */
751 if(cur_col == STACKS_COL + i){
752 rb->lcd_invertrect(LCD_WIDTH - CARD_WIDTH+1, i*CARD_HEIGHT + 1, CARD_WIDTH-1, CARD_HEIGHT-1);
568 } 753 }
569 rb->lcd_bitmap(colors[i], LCD_WIDTH - CARD_WIDTH+7,
570 i*CARD_HEIGHT, 8, 8, true);
571 rb->lcd_drawline(LCD_WIDTH - CARD_WIDTH+1,
572 i*CARD_HEIGHT,LCD_WIDTH - 1,i*CARD_HEIGHT);
573 rb->lcd_drawline(LCD_WIDTH - CARD_WIDTH+1,
574 (i+1)*CARD_HEIGHT,LCD_WIDTH - 1,
575 (i+1)*CARD_HEIGHT);
576 } 754 }
577 755
578 /* draw the remains */ 756 /* draw the remains */
579 rb->lcd_drawline(LCD_WIDTH - CARD_WIDTH+1, 757 if(rem != NOT_A_CARD) {
580 LCD_HEIGHT-CARD_HEIGHT-1, 758 rb->lcd_drawline(LCD_WIDTH - CARD_WIDTH+1,LCD_HEIGHT-CARD_HEIGHT-1,LCD_WIDTH - 1,LCD_HEIGHT-CARD_HEIGHT-1);
581 LCD_WIDTH - 1,LCD_HEIGHT-CARD_HEIGHT-1); 759 rb->lcd_drawline(LCD_WIDTH - CARD_WIDTH,LCD_HEIGHT-CARD_HEIGHT,LCD_WIDTH - CARD_WIDTH,LCD_HEIGHT-2);
582 rb->lcd_drawline(LCD_WIDTH - CARD_WIDTH+1, 760 rb->lcd_drawline(LCD_WIDTH - CARD_WIDTH+1,LCD_HEIGHT-1,LCD_WIDTH - 1,LCD_HEIGHT-1);
583 LCD_HEIGHT-1,LCD_WIDTH - 1,LCD_HEIGHT-1); 761 if(cur_rem != NOT_A_CARD){
584 if(cur_rem != NOT_A_CARD){ 762 rb->lcd_bitmap(numbers[deck[cur_rem].num], LCD_WIDTH - CARD_WIDTH+1, LCD_HEIGHT-CARD_HEIGHT, 8, 8, true);
585 rb->lcd_bitmap(numbers[deck[cur_rem].num], 763 rb->lcd_bitmap(colors[deck[cur_rem].color], LCD_WIDTH - CARD_WIDTH+7, LCD_HEIGHT-CARD_HEIGHT, 8, 8, true);
586 LCD_WIDTH - CARD_WIDTH+1, LCD_HEIGHT-CARD_HEIGHT, 764 /* draw a selected card */
587 8, 8, true); 765 if(sel_card == cur_rem){
588 rb->lcd_bitmap(colors[deck[cur_rem].color], 766 rb->lcd_drawrect(LCD_WIDTH - CARD_WIDTH+1, LCD_HEIGHT-CARD_HEIGHT,CARD_WIDTH-1, CARD_HEIGHT-1);
589 LCD_WIDTH - CARD_WIDTH+7, 767 }
590 LCD_HEIGHT-CARD_HEIGHT, 8, 8, true); 768 }
591 } 769 }
770 /* draw the cursor */
771 if(cur_col == REM_COL){
772 rb->lcd_invertrect(LCD_WIDTH - CARD_WIDTH+1, LCD_HEIGHT-CARD_HEIGHT,CARD_WIDTH-1, CARD_HEIGHT-1);
773 }
774
592 775
593 rb->lcd_update(); 776 rb->lcd_update();
594 777
@@ -596,269 +779,139 @@ void solitaire(void){
596 switch(rb->button_get(true)){ 779 switch(rb->button_get(true)){
597 780
598 /* move cursor to the last card of the previous column */ 781 /* move cursor to the last card of the previous column */
782 /* or to the previous color stack */
783 /* or to the remains stack */
599 case BUTTON_RIGHT: 784 case BUTTON_RIGHT:
600 cur_col = (cur_col+1)%COL_NUM; 785 if(cur_col >= COL_NUM){
601 cur_card = cols[cur_col]; 786 cur_col = 0;
602 if(cur_card != NOT_A_CARD){ 787 } else if(cur_col == COL_NUM - 1){
603 while(deck[cur_card].next != NOT_A_CARD){ 788 cur_col = REM_COL;
604 cur_card = deck[cur_card].next; 789 } else {
605 } 790 cur_col = (cur_col+1)%(REM_COL+1);
606 } 791 }
792 if(cur_col == REM_COL){
793 cur_card = cur_rem;
794 break;
795 }
796 cur_card = find_last_card(cur_col);
607 break; 797 break;
608 798
609 /* move cursor to the last card of the next column */ 799 /* move cursor to the last card of the next column */
800 /* or to the next color stack */
801 /* or to the remains stack */
610 case BUTTON_LEFT: 802 case BUTTON_LEFT:
611 cur_col = (cur_col + COL_NUM - 1)%COL_NUM; 803 if(cur_col == 0){
612 cur_card = cols[cur_col]; 804 cur_col = REM_COL;
613 if(cur_card != NOT_A_CARD){ 805 } else if(cur_col >= COL_NUM) {
614 while(deck[cur_card].next != NOT_A_CARD){ 806 cur_col = COL_NUM - 1;
615 cur_card = deck[cur_card].next; 807 } else {
616 } 808 cur_col = (cur_col + REM_COL)%(REM_COL+1);
809 }
810 if(cur_col == REM_COL){
811 cur_card = cur_rem;
812 break;
617 } 813 }
814 cur_card = find_last_card(cur_col);
618 break; 815 break;
619 816
620 /* move cursor to card that's bellow */ 817 /* move cursor to card that's bellow */
621 case BUTTON_DOWN: 818 case BUTTON_DOWN:
819 if(cur_col >= COL_NUM) {
820 cur_col = (cur_col - COL_NUM + 1)%(COLORS + 1) + COL_NUM;
821 if(cur_col == REM_COL){
822 cur_card = cur_rem;
823 } else {
824 cur_card = find_last_card(cur_col);
825 }
826 break;
827 }
622 if(cur_card == NOT_A_CARD) break; 828 if(cur_card == NOT_A_CARD) break;
623 if(deck[cur_card].next != NOT_A_CARD){ 829 if(deck[cur_card].next != NOT_A_CARD){
624 cur_card = deck[cur_card].next; 830 cur_card = deck[cur_card].next;
625 } else { 831 } else {
626 cur_card = cols[cur_col]; 832 cur_card = cols[cur_col];
833 while(deck[cur_card].known == 0
834 && deck[cur_card].next != NOT_A_CARD){
835 cur_card = deck[cur_card].next;
836 }
627 } 837 }
628 break; 838 break;
629 839
630 /* move cursor to card that's above */ 840 /* move cursor to card that's above */
631 case BUTTON_UP: 841 case BUTTON_UP:
632 if(cur_card == NOT_A_CARD) break; 842 if(cur_col >= COL_NUM) {
633 if(cols[cur_col] == cur_card){ 843 cur_col = (cur_col - COL_NUM + COLORS)%(COLORS + 1) + COL_NUM;
634 while(deck[cur_card].next != NOT_A_CARD){ 844 if(cur_col == REM_COL){
635 cur_card = deck[cur_card].next; 845 cur_card = cur_rem;
636 } 846 } else {
637 } else { 847 cur_card = find_last_card(cur_col);
638 c = cols[cur_col];
639 while(deck[c].next != cur_card){
640 c = deck[c].next;
641 } 848 }
642 cur_card = c; 849 break;
643 } 850 }
851 if(cur_card == NOT_A_CARD) break;
852 do{
853 cur_card = find_prev_card(cur_card);
854 if(cur_card == NOT_A_CARD){
855 cur_card = find_last_card(cur_col);
856 }
857 } while (deck[cur_card].next != NOT_A_CARD
858 && deck[cur_card].known == 0);
644 break; 859 break;
645 860
646 /* Try to put card under cursor on one of the stacks */ 861 /* Try to put card under cursor on one of the stacks */
647 case BUTTON_F1: 862 case BUTTON_F1:
648 /* check if a card is selected */
649 /* else there would be nothing to move on the stacks ! */
650 if(cur_card != NOT_A_CARD){ 863 if(cur_card != NOT_A_CARD){
651 /* find the last card in the color's stack and put it's number in 'c'. */ 864 move_card(deck[cur_card].color + STACKS_COL, cur_card);
652 c = stacks[deck[cur_card].color];
653 if(c!=NOT_A_CARD){
654 while(deck[c].next!=NOT_A_CARD){
655 c = deck[c].next;
656 }
657 }
658 /* if 'c' isn't a card, that means that the stack is empty */
659 /* which implies that only an ace can be moved */
660 if(c == NOT_A_CARD){
661 /* check if the selected card is an ace */
662 /* we don't have to check if any card is in the *.next */
663 /* position since the ace is the last possible card */
664 if(deck[cur_card].num == 0){
665 /* remove 'cur_card' from any *.next postition ... */
666 /* ... by looking in the columns */
667 for(i=0;i<COL_NUM;i++){
668 if(cols[i]==cur_card) cols[i] = NOT_A_CARD;
669 }
670 /* ... and in the entire deck */
671 /* TODO : check if looking in the cols is really needed */
672 for(i=0;i<COLORS*CARDS_PER_COLOR;i++){
673 if(deck[i].next==cur_card) deck[i].next = NOT_A_CARD;
674 }
675 /* move cur_card on top of the stack */
676 stacks[deck[cur_card].color] = cur_card;
677 /* assign the card at the bottom of cur_col to cur_card */
678 cur_card = cols[cur_col];
679 if(cur_card != NOT_A_CARD){
680 while(deck[cur_card].next != NOT_A_CARD){
681 cur_card = deck[cur_card].next;
682 }
683 }
684 /* clear the selection indicator */
685 sel_card = NOT_A_CARD;
686 }
687 }
688 /* the stack is not empty */
689 /* so we can move any card other than an ace */
690 /* we thus check that the card we are moving is the next on the stack and that it isn't under any card */
691 else if(deck[cur_card].num == deck[c].num + 1 &&
692 deck[cur_card].next == NOT_A_CARD) {
693 /* same as above */
694 for(i=0;i<COL_NUM;i++) {
695 if(cols[i]==cur_card)
696 cols[i] = NOT_A_CARD;
697 }
698 /* re same */
699 for(i=0;i<COLORS*CARDS_PER_COLOR;i++){
700 if(deck[i].next==cur_card)
701 deck[i].next = NOT_A_CARD;
702 }
703 /* ... */
704 deck[c].next = cur_card;
705 cur_card = cols[cur_col];
706 if(cur_card != NOT_A_CARD){
707 while(deck[cur_card].next != NOT_A_CARD){
708 cur_card = deck[cur_card].next;
709 }
710 }
711 sel_card = NOT_A_CARD;
712 }
713 } 865 }
714 break; 866 break;
715 867
716 /* Move cards arround, Uncover cards, ... */ 868 /* Move cards arround, Uncover cards, ... */
717 case BUTTON_ON: 869 case BUTTON_ON:
718 if(sel_card == NOT_A_CARD) { 870 if(sel_card == NOT_A_CARD) {
719 if((cur_card != NOT_A_CARD? 871 if(cur_card != NOT_A_CARD){
720 deck[cur_card].next == NOT_A_CARD && 872 /* reveal a hidden card */
721 deck[cur_card].known==0:0)) { 873 if(deck[cur_card].next == NOT_A_CARD && deck[cur_card].known==0){
722 deck[cur_card].known = 1; 874 deck[cur_card].known = 1;
723 } else { 875 /* select a card */
724 sel_card = cur_card; 876 } else {
877 sel_card = cur_card;
878 }
725 } 879 }
880 /* unselect card or try putting card on one of the 4 stacks */
726 } else if(sel_card == cur_card) { 881 } else if(sel_card == cur_card) {
882 move_card(deck[sel_card].color + COL_NUM, sel_card);
727 sel_card = NOT_A_CARD; 883 sel_card = NOT_A_CARD;
728 } else if(cur_card != NOT_A_CARD){ 884 /* try moving cards */
729 if(deck[cur_card].num == deck[sel_card].num + 1 && 885 } else {
730 (deck[cur_card].color + deck[sel_card].color)%2 == 1 ){ 886 if(move_card(cur_col, sel_card) == MOVE_OK){
731 for(i=0;i<COL_NUM;i++){
732 if(cols[i]==sel_card)
733 cols[i] = NOT_A_CARD;
734 }
735 for(i=0;i<COLORS*CARDS_PER_COLOR;i++){
736 if(deck[i].next==sel_card)
737 deck[i].next = NOT_A_CARD;
738 }
739 deck[cur_card].next = sel_card;
740 sel_card = NOT_A_CARD;
741 }
742 } else if(cur_card == NOT_A_CARD){
743 if(deck[sel_card].num == CARDS_PER_COLOR - 1){
744 for(i=0;i<COL_NUM;i++){
745 if(cols[i]==sel_card)
746 cols[i] = NOT_A_CARD;
747 }
748 for(i=0;i<COLORS*CARDS_PER_COLOR;i++){
749 if(deck[i].next==sel_card)
750 deck[i].next = NOT_A_CARD;
751 }
752 cols[cur_col] = sel_card;
753 sel_card = NOT_A_CARD; 887 sel_card = NOT_A_CARD;
754 } 888 }
755 } 889 }
756 break; 890 break;
757 891
758 /* If the card on the top of the remains can be put where */ 892 /* If the card on the top of the remains can be put where */
759 /* the cursor is, go ahead */ 893 /* the cursor is, go ahead */
760 case BUTTON_PLAY: 894 case BUTTON_PLAY:
761 /* check if a card is face up on the remains' stack */ 895 move_card(cur_col, cur_rem);
762 if(cur_rem != NOT_A_CARD){
763 /* if no card is selected, it means the col is empty */
764 /* thus, only a king can be moved */
765 if(cur_card == NOT_A_CARD){
766 /* check if selcted card is a king */
767 if(deck[cur_rem].num == CARDS_PER_COLOR - 1){
768 /* find the previous card on the remains' stack */
769 c = rem;
770 /* if the current card on the remains' stack */
771 /* is the first card of the stack, then ... */
772 if(c == cur_rem){
773 c = NOT_A_CARD;
774 rem = deck[cur_rem].next;
775 }
776 /* else ... */
777 else {
778 while(deck[c].next != cur_rem){
779 c = deck[c].next;
780 }
781 deck[c].next = deck[cur_rem].next;
782 }
783 cols[cur_col] = cur_rem;
784 deck[cur_rem].next = NOT_A_CARD;
785 deck[cur_rem].known = 1;
786 cur_rem = c;
787 }
788 } else if(deck[cur_rem].num + 1 == deck[cur_card].num &&
789 (deck[cur_rem].color +
790 deck[cur_card].color)%2==1) {
791 c = rem;
792 if(c == cur_rem){
793 c = NOT_A_CARD;
794 rem = deck[cur_rem].next;
795 } else {
796 while(deck[c].next != cur_rem){
797 c = deck[c].next;
798 }
799 deck[c].next = deck[cur_rem].next;
800 }
801 deck[cur_card].next = cur_rem;
802 deck[cur_rem].next = NOT_A_CARD;
803 deck[cur_rem].known = 1;
804 cur_rem = c;
805 }
806 }
807 break; 896 break;
808 897
809 /* If the card on top of the remains can be put on one */ 898 /* If the card on top of the remains can be put on one */
810 /* of the stacks, do so */ 899 /* of the stacks, do so */
811 case BUTTON_F3: 900 case BUTTON_F3:
812 if(cur_rem != NOT_A_CARD){ 901 if(cur_rem != NOT_A_CARD){
813 if(deck[cur_rem].num == 0){ 902 move_card(deck[cur_rem].color + COL_NUM, cur_rem);
814 c = rem;
815 if(c == cur_rem){
816 c = NOT_A_CARD;
817 rem = deck[cur_rem].next;
818 } else {
819 while(deck[c].next != cur_rem){
820 c = deck[c].next;
821 }
822 deck[c].next = deck[cur_rem].next;
823 }
824 deck[cur_rem].next = NOT_A_CARD;
825 deck[cur_rem].known = 1;
826 stacks[deck[cur_rem].color] = cur_rem;
827 cur_rem = c;
828 } else {
829
830 i = stacks[deck[cur_rem].color];
831 if(i==NOT_A_CARD) break;
832 while(deck[i].next != NOT_A_CARD){
833 i = deck[i].next;
834 }
835 if(deck[i].num + 1 == deck[cur_rem].num){
836 c = rem;
837 if(c == cur_rem){
838 c = NOT_A_CARD;
839 rem = deck[cur_rem].next;
840 } else {
841 while(deck[c].next != cur_rem){
842 c = deck[c].next;
843 }
844 deck[c].next = deck[cur_rem].next;
845 }
846 deck[i].next = cur_rem;
847 deck[cur_rem].next = NOT_A_CARD;
848 deck[cur_rem].known = 1;
849 cur_rem = c;
850 }
851 }
852 } 903 }
853 break; 904 break;
854 905
855 /* unselect selected card or ... */ 906 /* unselect selected card or ... */
856 /* draw new cards from the remains of the deck */ 907 /* draw new cards from the remains of the deck */
857 case BUTTON_F2: 908 case BUTTON_F2:
858 if(sel_card != NOT_A_CARD){ 909 if(sel_card != NOT_A_CARD){
859 /* unselect selected card */ 910 /* unselect selected card */
860 sel_card = NOT_A_CARD; 911 sel_card = NOT_A_CARD;
861 } else if(rem != NOT_A_CARD) { 912 break;
913 }
914 if(rem != NOT_A_CARD) {
862 /* draw new cards form the remains of the deck */ 915 /* draw new cards form the remains of the deck */
863 if(cur_rem == NOT_A_CARD){ 916 if(cur_rem == NOT_A_CARD){
864 cur_rem = rem; 917 cur_rem = rem;
@@ -870,24 +923,30 @@ void solitaire(void){
870 cur_rem = deck[cur_rem].next; 923 cur_rem = deck[cur_rem].next;
871 i--; 924 i--;
872 } 925 }
873 /* test if any cards are really left on the remains' stack */ 926 /* test if any cards are really left on */
927 /* the remains' stack */
874 if(i == CARDS_PER_DRAW){ 928 if(i == CARDS_PER_DRAW){
875 cur_rem = NOT_A_CARD; 929 cur_rem = NOT_A_CARD;
876 } 930 }
877 } 931 }
878 break; 932 break;
879 933
880 /* Show the menu */ 934 /* Show the menu */
881 case BUTTON_OFF: 935 case BUTTON_OFF:
882 switch(solitaire_menu(MENU_DURINGGAME)){ 936 switch(solitaire_menu(MENU_DURINGGAME)){
883 case MENU_QUIT: 937 case MENU_QUIT:
884 return; 938 return SOLITAIRE_QUIT;
885 939
886 case MENU_RESTART: 940 case MENU_RESTART:
887 solitaire_init(); 941 solitaire_init();
888 break; 942 break;
889 } 943 }
890 } 944 }
945
946 /* fix incoherences concerning cur_col and cur_card */
947 c = find_card_col(cur_card);
948 if(c != NOT_A_COL && c != cur_col)
949 cur_card = find_last_card(cur_col);
891 } 950 }
892} 951}
893 952
@@ -903,7 +962,9 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
903 rb->splash(HZ*2, true, "Welcome to Solitaire !"); 962 rb->splash(HZ*2, true, "Welcome to Solitaire !");
904 963
905 /* play the game :) */ 964 /* play the game :) */
906 solitaire(); 965 /* Keep playing if a game was won (that means display the menu after */
966 /* winning instead of quiting) */
967 while(solitaire() == SOLITAIRE_WIN);
907 968
908 /* Exit the plugin */ 969 /* Exit the plugin */
909 return PLUGIN_OK; 970 return PLUGIN_OK;