diff options
Diffstat (limited to 'apps/plugins/solitaire.c')
-rw-r--r-- | apps/plugins/solitaire.c | 637 |
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 @@ | |||
21 | Solitaire by dionoea | 21 | Solitaire by dionoea |
22 | 22 | ||
23 | use arrows to move the cursor | 23 | use arrows to move the cursor |
24 | use ON to select cards in the columns, move cards inside the columns, | 24 | use ON to select cards, move cards, reveal hidden cards, ... |
25 | reveal hidden cards, ... | ||
26 | use PLAY to move a card from the remains' stack to the top of the cursor | 25 | use PLAY to move a card from the remains' stack to the top of the cursor |
27 | use F1 to put card under cursor on one of the 4 final color stacks | 26 | use F1 to put card under cursor on one of the 4 final color stacks |
28 | use F2 to un-select card if a card was selected, else draw 3 new cards | 27 | use 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 | ||
62 | static unsigned char colors[4][8] = { | 61 | static 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 */ |
264 | void solitaire_help(void) | 271 | void 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 */ | ||
474 | unsigned 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 */ | ||
501 | unsigned 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 */ | ||
512 | unsigned 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 | ||
535 | unsigned 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 */ |
464 | void solitaire(void){ | 647 | int 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; |