diff options
Diffstat (limited to 'apps')
-rw-r--r-- | apps/plugins/wormlet.c | 924 |
1 files changed, 667 insertions, 257 deletions
diff --git a/apps/plugins/wormlet.c b/apps/plugins/wormlet.c index d6929f2bd7..d872e8be19 100644 --- a/apps/plugins/wormlet.c +++ b/apps/plugins/wormlet.c | |||
@@ -17,6 +17,7 @@ | |||
17 | * | 17 | * |
18 | ****************************************************************************/ | 18 | ****************************************************************************/ |
19 | #include "plugin.h" | 19 | #include "plugin.h" |
20 | #include "configfile.h" | ||
20 | 21 | ||
21 | PLUGIN_HEADER | 22 | PLUGIN_HEADER |
22 | 23 | ||
@@ -26,11 +27,6 @@ PLUGIN_HEADER | |||
26 | #define FIELD_RECT_WIDTH (LCD_WIDTH - 45) | 27 | #define FIELD_RECT_WIDTH (LCD_WIDTH - 45) |
27 | #define FIELD_RECT_HEIGHT (LCD_HEIGHT - 2) | 28 | #define FIELD_RECT_HEIGHT (LCD_HEIGHT - 2) |
28 | 29 | ||
29 | /* size of the ring of the worm | ||
30 | choos a value that is a power of 2 to help | ||
31 | the compiler optimize modul operations*/ | ||
32 | #define MAX_WORM_SEGMENTS 64 | ||
33 | |||
34 | /* when the game starts */ | 30 | /* when the game starts */ |
35 | #define INITIAL_WORM_LENGTH 10 | 31 | #define INITIAL_WORM_LENGTH 10 |
36 | 32 | ||
@@ -109,26 +105,40 @@ PLUGIN_HEADER | |||
109 | #define FOOD_SIZE 3 | 105 | #define FOOD_SIZE 3 |
110 | #define ARGH_SIZE 4 | 106 | #define ARGH_SIZE 4 |
111 | #define SPEED 14 | 107 | #define SPEED 14 |
108 | #define MAX_WORM_SEGMENTS 128 | ||
112 | #elif (LCD_WIDTH == 138) && (LCD_HEIGHT == 110) | 109 | #elif (LCD_WIDTH == 138) && (LCD_HEIGHT == 110) |
113 | #define FOOD_SIZE 4 | 110 | #define FOOD_SIZE 4 |
114 | #define ARGH_SIZE 5 | 111 | #define ARGH_SIZE 5 |
115 | #define SPEED 10 | 112 | #define SPEED 10 |
113 | #define MAX_WORM_SEGMENTS 128 | ||
116 | #elif (LCD_WIDTH == 160) && (LCD_HEIGHT == 128) | 114 | #elif (LCD_WIDTH == 160) && (LCD_HEIGHT == 128) |
117 | #define FOOD_SIZE 4 | 115 | #define FOOD_SIZE 4 |
118 | #define ARGH_SIZE 5 | 116 | #define ARGH_SIZE 5 |
119 | #define SPEED 8 | 117 | #define SPEED 8 |
118 | #define MAX_WORM_SEGMENTS 256 | ||
120 | #elif (LCD_WIDTH == 176) && (LCD_HEIGHT == 132) | 119 | #elif (LCD_WIDTH == 176) && (LCD_HEIGHT == 132) |
121 | #define FOOD_SIZE 4 | 120 | #define FOOD_SIZE 4 |
122 | #define ARGH_SIZE 5 | 121 | #define ARGH_SIZE 5 |
123 | #define SPEED 6 | 122 | #define SPEED 6 |
123 | #define MAX_WORM_SEGMENTS 256 | ||
124 | #elif (LCD_WIDTH == 220) && (LCD_HEIGHT == 176) | 124 | #elif (LCD_WIDTH == 220) && (LCD_HEIGHT == 176) |
125 | #define FOOD_SIZE 5 | 125 | #define FOOD_SIZE 5 |
126 | #define ARGH_SIZE 6 | 126 | #define ARGH_SIZE 6 |
127 | #define SPEED 4 | 127 | #define SPEED 4 |
128 | #define MAX_WORM_SEGMENTS 512 | ||
128 | #elif (LCD_WIDTH == 320) && (LCD_HEIGHT == 240) | 129 | #elif (LCD_WIDTH == 320) && (LCD_HEIGHT == 240) |
129 | #define FOOD_SIZE 7 | 130 | #define FOOD_SIZE 7 |
130 | #define ARGH_SIZE 8 | 131 | #define ARGH_SIZE 8 |
131 | #define SPEED 4 | 132 | #define SPEED 4 |
133 | #define MAX_WORM_SEGMENTS 512 | ||
134 | #endif | ||
135 | |||
136 | #ifdef HAVE_LCD_COLOR | ||
137 | #define COLOR_WORM LCD_RGBPACK(80, 40, 0) | ||
138 | #define COLOR_ARGH LCD_RGBPACK(175, 0, 0) | ||
139 | #define COLOR_FOOD LCD_RGBPACK(0, 150, 0) | ||
140 | #define COLOR_FG LCD_RGBPACK(0, 0, 0) | ||
141 | #define COLOR_BG LCD_RGBPACK(181, 199, 231) | ||
132 | #endif | 142 | #endif |
133 | 143 | ||
134 | /** | 144 | /** |
@@ -162,19 +172,32 @@ static int highscore; | |||
162 | #define MAX_FOOD 5 /* maximal number of food items */ | 172 | #define MAX_FOOD 5 /* maximal number of food items */ |
163 | 173 | ||
164 | /* The arrays store the food coordinates */ | 174 | /* The arrays store the food coordinates */ |
165 | static char foodx[MAX_FOOD]; | 175 | static int foodx[MAX_FOOD]; |
166 | static char foody[MAX_FOOD]; | 176 | static int foody[MAX_FOOD]; |
167 | 177 | ||
168 | #define MAX_ARGH 100 /* maximal number of argh items */ | 178 | #define MAX_ARGH 100 /* maximal number of argh items */ |
169 | #define ARGHS_PER_FOOD 2 /* number of arghs produced per eaten food */ | 179 | #define ARGHS_PER_FOOD 2 /* number of arghs produced per eaten food */ |
170 | 180 | ||
171 | /* The arrays store the argh coordinates */ | 181 | /* The arrays store the argh coordinates */ |
172 | static char arghx[MAX_ARGH]; | 182 | static int arghx[MAX_ARGH]; |
173 | static char arghy[MAX_ARGH]; | 183 | static int arghy[MAX_ARGH]; |
174 | 184 | ||
175 | /* the number of arghs that are currently in use */ | 185 | /* the number of arghs that are currently in use */ |
176 | static int argh_count; | 186 | static int argh_count; |
177 | 187 | ||
188 | /* the number of arghs per food, settable by user */ | ||
189 | static int arghs_per_food = ARGHS_PER_FOOD; | ||
190 | /* the size of the argh, settable by user */ | ||
191 | static int argh_size = ARGH_SIZE; | ||
192 | /* the size of the food, settable by user */ | ||
193 | static int food_size = FOOD_SIZE; | ||
194 | /* the speed of the worm, settable by user */ | ||
195 | static int speed = SPEED; | ||
196 | /* the amount a worm grows by eating a food, settable by user */ | ||
197 | static int worm_food = WORM_PER_FOOD; | ||
198 | |||
199 | /* End additional variables */ | ||
200 | |||
178 | #ifdef DEBUG_WORMLET | 201 | #ifdef DEBUG_WORMLET |
179 | /* just a buffer used for debug output */ | 202 | /* just a buffer used for debug output */ |
180 | static char debugout[15]; | 203 | static char debugout[15]; |
@@ -217,6 +240,23 @@ static int players = 1; | |||
217 | /* the rockbox plugin api */ | 240 | /* the rockbox plugin api */ |
218 | static struct plugin_api* rb; | 241 | static struct plugin_api* rb; |
219 | 242 | ||
243 | #define SETTINGS_VERSION 1 | ||
244 | #define SETTINGS_MIN_VERSION 1 | ||
245 | #define SETTINGS_FILENAME "wormlet.cfg" | ||
246 | |||
247 | static struct configdata config[] = | ||
248 | { | ||
249 | {TYPE_INT, 0, 1024, &highscore, "highscore", NULL, NULL}, | ||
250 | {TYPE_INT, 0, 15, &arghs_per_food, "arghs per food", NULL, NULL}, | ||
251 | {TYPE_INT, 0, 15, &argh_size, "argh size", NULL, NULL}, | ||
252 | {TYPE_INT, 0, 15, &food_size, "food size", NULL, NULL}, | ||
253 | {TYPE_INT, 0, 3, &players, "players", NULL, NULL}, | ||
254 | {TYPE_INT, 0, 3, &worm_count, "worms", NULL, NULL}, | ||
255 | {TYPE_INT, 0, 20, &speed, "speed", NULL, NULL}, | ||
256 | {TYPE_INT, 0, 15, &worm_food, "Worm Growth Per Food", NULL, NULL}//, | ||
257 | //{TYPE_INT, 0, 3, &use_remote, "use remote", NULL, NULL} | ||
258 | }; | ||
259 | |||
220 | #ifdef DEBUG_WORMLET | 260 | #ifdef DEBUG_WORMLET |
221 | static void set_debug_out(char *str){ | 261 | static void set_debug_out(char *str){ |
222 | strcpy(debugout, str); | 262 | strcpy(debugout, str); |
@@ -432,9 +472,9 @@ static bool worm_in_rect(struct worm *w, int x, int y, int width, int height) { | |||
432 | static bool specific_food_collision(int foodIndex, int x, int y) { | 472 | static bool specific_food_collision(int foodIndex, int x, int y) { |
433 | bool retVal = false; | 473 | bool retVal = false; |
434 | if (x >= foodx[foodIndex] && | 474 | if (x >= foodx[foodIndex] && |
435 | x < foodx[foodIndex] + FOOD_SIZE && | 475 | x < foodx[foodIndex] + food_size && |
436 | y >= foody[foodIndex] && | 476 | y >= foody[foodIndex] && |
437 | y < foody[foodIndex] + FOOD_SIZE) { | 477 | y < foody[foodIndex] + food_size) { |
438 | 478 | ||
439 | retVal = true; | 479 | retVal = true; |
440 | } | 480 | } |
@@ -472,8 +512,8 @@ static bool specific_argh_collision(int arghIndex, int x, int y) { | |||
472 | 512 | ||
473 | if ( x >= arghx[arghIndex] && | 513 | if ( x >= arghx[arghIndex] && |
474 | y >= arghy[arghIndex] && | 514 | y >= arghy[arghIndex] && |
475 | x < arghx[arghIndex] + ARGH_SIZE && | 515 | x < arghx[arghIndex] + argh_size && |
476 | y < arghy[arghIndex] + ARGH_SIZE ) | 516 | y < arghy[arghIndex] + argh_size ) |
477 | { | 517 | { |
478 | return true; | 518 | return true; |
479 | } | 519 | } |
@@ -514,7 +554,7 @@ static bool worm_food_collision(struct worm *w, int foodIndex) | |||
514 | bool retVal = false; | 554 | bool retVal = false; |
515 | 555 | ||
516 | retVal = worm_in_rect(w, foodx[foodIndex], foody[foodIndex], | 556 | retVal = worm_in_rect(w, foodx[foodIndex], foody[foodIndex], |
517 | FOOD_SIZE - 1, FOOD_SIZE - 1); | 557 | food_size - 1, food_size - 1); |
518 | 558 | ||
519 | return retVal; | 559 | return retVal; |
520 | } | 560 | } |
@@ -538,7 +578,7 @@ static bool worm_argh_collision_in_moves(struct worm *w, int argh_idx, int moves | |||
538 | y2 = w->y[w->head] + moves * w->diry; | 578 | y2 = w->y[w->head] + moves * w->diry; |
539 | 579 | ||
540 | retVal = line_in_rect(x1, y1, x2, y2, arghx[argh_idx], arghy[argh_idx], | 580 | retVal = line_in_rect(x1, y1, x2, y2, arghx[argh_idx], arghy[argh_idx], |
541 | ARGH_SIZE, ARGH_SIZE); | 581 | argh_size, argh_size); |
542 | return retVal; | 582 | return retVal; |
543 | } | 583 | } |
544 | 584 | ||
@@ -553,7 +593,7 @@ static bool worm_argh_collision(struct worm *w, int arghIndex) | |||
553 | bool retVal = false; | 593 | bool retVal = false; |
554 | 594 | ||
555 | retVal = worm_in_rect(w, arghx[arghIndex], arghy[arghIndex], | 595 | retVal = worm_in_rect(w, arghx[arghIndex], arghy[arghIndex], |
556 | ARGH_SIZE - 1, ARGH_SIZE - 1); | 596 | argh_size - 1, argh_size - 1); |
557 | 597 | ||
558 | return retVal; | 598 | return retVal; |
559 | } | 599 | } |
@@ -564,20 +604,18 @@ static bool worm_argh_collision(struct worm *w, int arghIndex) | |||
564 | * @param int index | 604 | * @param int index |
565 | * Ensure that 0 <= index < MAX_FOOD. | 605 | * Ensure that 0 <= index < MAX_FOOD. |
566 | */ | 606 | */ |
567 | static int make_food(int index) { | 607 | static void make_food(int index) { |
568 | 608 | ||
569 | int x = 0; | 609 | int x = 0; |
570 | int y = 0; | 610 | int y = 0; |
571 | bool collisionDetected = false; | 611 | bool collisionDetected = false; |
572 | int tries = 0; | ||
573 | int i; | 612 | int i; |
574 | 613 | ||
575 | do { | 614 | do { |
576 | /* make coordinates for a new food so that | 615 | /* make coordinates for a new food so that |
577 | the entire food lies within the FIELD */ | 616 | the entire food lies within the FIELD */ |
578 | x = rb->rand() % (FIELD_RECT_WIDTH - FOOD_SIZE); | 617 | x = rb->rand() % (FIELD_RECT_WIDTH - food_size); |
579 | y = rb->rand() % (FIELD_RECT_HEIGHT - FOOD_SIZE); | 618 | y = rb->rand() % (FIELD_RECT_HEIGHT - food_size); |
580 | tries ++; | ||
581 | 619 | ||
582 | /* Ensure that the new food doesn't collide with any | 620 | /* Ensure that the new food doesn't collide with any |
583 | existing foods or arghs. | 621 | existing foods or arghs. |
@@ -586,13 +624,13 @@ static int make_food(int index) { | |||
586 | */ | 624 | */ |
587 | collisionDetected = | 625 | collisionDetected = |
588 | food_collision(x , y ) >= 0 || | 626 | food_collision(x , y ) >= 0 || |
589 | food_collision(x , y + FOOD_SIZE - 1) >= 0 || | 627 | food_collision(x , y + food_size - 1) >= 0 || |
590 | food_collision(x + FOOD_SIZE - 1, y ) >= 0 || | 628 | food_collision(x + food_size - 1, y ) >= 0 || |
591 | food_collision(x + FOOD_SIZE - 1, y + FOOD_SIZE - 1) >= 0 || | 629 | food_collision(x + food_size - 1, y + food_size - 1) >= 0 || |
592 | argh_collision(x , y ) >= 0 || | 630 | argh_collision(x , y ) >= 0 || |
593 | argh_collision(x , y + FOOD_SIZE - 1) >= 0 || | 631 | argh_collision(x , y + food_size - 1) >= 0 || |
594 | argh_collision(x + FOOD_SIZE - 1, y ) >= 0 || | 632 | argh_collision(x + food_size - 1, y ) >= 0 || |
595 | argh_collision(x + FOOD_SIZE - 1, y + FOOD_SIZE - 1) >= 0; | 633 | argh_collision(x + food_size - 1, y + food_size - 1) >= 0; |
596 | 634 | ||
597 | /* use coordinates for further testing */ | 635 | /* use coordinates for further testing */ |
598 | foodx[index] = x; | 636 | foodx[index] = x; |
@@ -605,7 +643,7 @@ static int make_food(int index) { | |||
605 | } | 643 | } |
606 | } | 644 | } |
607 | while (collisionDetected); | 645 | while (collisionDetected); |
608 | return tries; | 646 | return; |
609 | } | 647 | } |
610 | 648 | ||
611 | /** | 649 | /** |
@@ -620,7 +658,7 @@ static void clear_food(int index) | |||
620 | rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); | 658 | rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); |
621 | rb->lcd_fillrect(foodx[index] + FIELD_RECT_X, | 659 | rb->lcd_fillrect(foodx[index] + FIELD_RECT_X, |
622 | foody[index] + FIELD_RECT_Y, | 660 | foody[index] + FIELD_RECT_Y, |
623 | FOOD_SIZE, FOOD_SIZE); | 661 | food_size, food_size); |
624 | rb->lcd_set_drawmode(DRMODE_SOLID); | 662 | rb->lcd_set_drawmode(DRMODE_SOLID); |
625 | } | 663 | } |
626 | 664 | ||
@@ -634,18 +672,18 @@ static void draw_food(int index) | |||
634 | { | 672 | { |
635 | /* draw the food object */ | 673 | /* draw the food object */ |
636 | #ifdef HAVE_LCD_COLOR | 674 | #ifdef HAVE_LCD_COLOR |
637 | rb->lcd_set_foreground(LCD_RGBPACK(0, 150, 0)); | 675 | rb->lcd_set_foreground(COLOR_FOOD); |
638 | #endif | 676 | #endif |
639 | rb->lcd_fillrect(foodx[index] + FIELD_RECT_X, | 677 | rb->lcd_fillrect(foodx[index] + FIELD_RECT_X, |
640 | foody[index] + FIELD_RECT_Y, | 678 | foody[index] + FIELD_RECT_Y, |
641 | FOOD_SIZE, FOOD_SIZE); | 679 | food_size, food_size); |
642 | rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); | 680 | rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); |
643 | rb->lcd_fillrect(foodx[index] + FIELD_RECT_X + 1, | 681 | rb->lcd_fillrect(foodx[index] + FIELD_RECT_X + 1, |
644 | foody[index] + FIELD_RECT_Y + 1, | 682 | foody[index] + FIELD_RECT_Y + 1, |
645 | FOOD_SIZE - 2, FOOD_SIZE - 2); | 683 | food_size - 2, food_size - 2); |
646 | rb->lcd_set_drawmode(DRMODE_SOLID); | 684 | rb->lcd_set_drawmode(DRMODE_SOLID); |
647 | #ifdef HAVE_LCD_COLOR | 685 | #ifdef HAVE_LCD_COLOR |
648 | rb->lcd_set_foreground(LCD_RGBPACK(0, 0, 0)); | 686 | rb->lcd_set_foreground(COLOR_FG); |
649 | #endif | 687 | #endif |
650 | } | 688 | } |
651 | 689 | ||
@@ -655,20 +693,18 @@ static void draw_food(int index) | |||
655 | * @param int index | 693 | * @param int index |
656 | * Ensure that 0 <= index < argh_count < MAX_ARGH. | 694 | * Ensure that 0 <= index < argh_count < MAX_ARGH. |
657 | */ | 695 | */ |
658 | static int make_argh(int index) | 696 | static void make_argh(int index) |
659 | { | 697 | { |
660 | int x = -1; | 698 | int x = -1; |
661 | int y = -1; | 699 | int y = -1; |
662 | bool collisionDetected = false; | 700 | bool collisionDetected = false; |
663 | int tries = 0; | ||
664 | int i; | 701 | int i; |
665 | 702 | ||
666 | do { | 703 | do { |
667 | /* make coordinates for a new argh so that | 704 | /* make coordinates for a new argh so that |
668 | the entire food lies within the FIELD */ | 705 | the entire food lies within the FIELD */ |
669 | x = rb->rand() % (FIELD_RECT_WIDTH - ARGH_SIZE); | 706 | x = rb->rand() % (FIELD_RECT_WIDTH - argh_size); |
670 | y = rb->rand() % (FIELD_RECT_HEIGHT - ARGH_SIZE); | 707 | y = rb->rand() % (FIELD_RECT_HEIGHT - argh_size); |
671 | tries ++; | ||
672 | 708 | ||
673 | /* Ensure that the new argh doesn't intersect with any | 709 | /* Ensure that the new argh doesn't intersect with any |
674 | existing foods or arghs. | 710 | existing foods or arghs. |
@@ -677,13 +713,13 @@ static int make_argh(int index) | |||
677 | */ | 713 | */ |
678 | collisionDetected = | 714 | collisionDetected = |
679 | food_collision(x , y ) >= 0 || | 715 | food_collision(x , y ) >= 0 || |
680 | food_collision(x , y + ARGH_SIZE - 1) >= 0 || | 716 | food_collision(x , y + argh_size - 1) >= 0 || |
681 | food_collision(x + ARGH_SIZE - 1, y ) >= 0 || | 717 | food_collision(x + argh_size - 1, y ) >= 0 || |
682 | food_collision(x + ARGH_SIZE - 1, y + ARGH_SIZE - 1) >= 0 || | 718 | food_collision(x + argh_size - 1, y + argh_size - 1) >= 0 || |
683 | argh_collision(x , y ) >= 0 || | 719 | argh_collision(x , y ) >= 0 || |
684 | argh_collision(x , y + ARGH_SIZE - 1) >= 0 || | 720 | argh_collision(x , y + argh_size - 1) >= 0 || |
685 | argh_collision(x + ARGH_SIZE - 1, y ) >= 0 || | 721 | argh_collision(x + argh_size - 1, y ) >= 0 || |
686 | argh_collision(x + ARGH_SIZE - 1, y + ARGH_SIZE - 1) >= 0; | 722 | argh_collision(x + argh_size - 1, y + argh_size - 1) >= 0; |
687 | 723 | ||
688 | /* use the candidate coordinates to make a real argh */ | 724 | /* use the candidate coordinates to make a real argh */ |
689 | arghx[index] = x; | 725 | arghx[index] = x; |
@@ -697,7 +733,7 @@ static int make_argh(int index) | |||
697 | } | 733 | } |
698 | } | 734 | } |
699 | while (collisionDetected); | 735 | while (collisionDetected); |
700 | return tries; | 736 | return; |
701 | } | 737 | } |
702 | 738 | ||
703 | /** | 739 | /** |
@@ -710,13 +746,13 @@ static void draw_argh(int index) | |||
710 | { | 746 | { |
711 | /* draw the new argh */ | 747 | /* draw the new argh */ |
712 | #ifdef HAVE_LCD_COLOR | 748 | #ifdef HAVE_LCD_COLOR |
713 | rb->lcd_set_foreground(LCD_RGBPACK(175, 0, 0)); | 749 | rb->lcd_set_foreground(COLOR_ARGH); |
714 | #endif | 750 | #endif |
715 | rb->lcd_fillrect(arghx[index] + FIELD_RECT_X, | 751 | rb->lcd_fillrect(arghx[index] + FIELD_RECT_X, |
716 | arghy[index] + FIELD_RECT_Y, | 752 | arghy[index] + FIELD_RECT_Y, |
717 | ARGH_SIZE, ARGH_SIZE); | 753 | argh_size, argh_size); |
718 | #ifdef HAVE_LCD_COLOR | 754 | #ifdef HAVE_LCD_COLOR |
719 | rb->lcd_set_foreground(LCD_RGBPACK(0, 0, 0)); | 755 | rb->lcd_set_foreground(COLOR_FG); |
720 | #endif | 756 | #endif |
721 | } | 757 | } |
722 | 758 | ||
@@ -935,7 +971,7 @@ static void move_worm(struct worm *w) | |||
935 | static void draw_worm(struct worm *w) | 971 | static void draw_worm(struct worm *w) |
936 | { | 972 | { |
937 | #ifdef HAVE_LCD_COLOR | 973 | #ifdef HAVE_LCD_COLOR |
938 | rb->lcd_set_foreground(LCD_RGBPACK(80, 40, 0)); | 974 | rb->lcd_set_foreground(COLOR_WORM); |
939 | #endif | 975 | #endif |
940 | /* draw the new head */ | 976 | /* draw the new head */ |
941 | int x = w->x[w->head]; | 977 | int x = w->x[w->head]; |
@@ -954,7 +990,7 @@ static void draw_worm(struct worm *w) | |||
954 | } | 990 | } |
955 | rb->lcd_set_drawmode(DRMODE_SOLID); | 991 | rb->lcd_set_drawmode(DRMODE_SOLID); |
956 | #ifdef HAVE_LCD_COLOR | 992 | #ifdef HAVE_LCD_COLOR |
957 | rb->lcd_set_foreground(LCD_RGBPACK(0, 0, 0)); | 993 | rb->lcd_set_foreground(COLOR_FG); |
958 | #endif | 994 | #endif |
959 | } | 995 | } |
960 | 996 | ||
@@ -1351,7 +1387,7 @@ static bool process_collisions(struct worm *w) | |||
1351 | make_food(index); | 1387 | make_food(index); |
1352 | draw_food(index); | 1388 | draw_food(index); |
1353 | 1389 | ||
1354 | for (i = 0; i < ARGHS_PER_FOOD; i++) { | 1390 | for (i = 0; i < arghs_per_food; i++) { |
1355 | argh_count++; | 1391 | argh_count++; |
1356 | if (argh_count > MAX_ARGH) | 1392 | if (argh_count > MAX_ARGH) |
1357 | argh_count = MAX_ARGH; | 1393 | argh_count = MAX_ARGH; |
@@ -1359,7 +1395,7 @@ static bool process_collisions(struct worm *w) | |||
1359 | draw_argh(argh_count - 1); | 1395 | draw_argh(argh_count - 1); |
1360 | } | 1396 | } |
1361 | 1397 | ||
1362 | add_growing(w, WORM_PER_FOOD); | 1398 | add_growing(w, worm_food); |
1363 | 1399 | ||
1364 | draw_worm(w); | 1400 | draw_worm(w); |
1365 | } | 1401 | } |
@@ -1386,10 +1422,11 @@ static bool process_collisions(struct worm *w) | |||
1386 | * with a dead worm. Returns false if the user | 1422 | * with a dead worm. Returns false if the user |
1387 | * aborted the game manually. | 1423 | * aborted the game manually. |
1388 | */ | 1424 | */ |
1389 | static bool run(void) | 1425 | static int run(void) |
1390 | { | 1426 | { |
1391 | int button = 0; | 1427 | int button = 0; |
1392 | int wormDead = false; | 1428 | int wormDead = false; |
1429 | bool paused = false; | ||
1393 | 1430 | ||
1394 | /* ticks are counted to compensate speed variations */ | 1431 | /* ticks are counted to compensate speed variations */ |
1395 | long cycle_start = 0, cycle_end = 0; | 1432 | long cycle_start = 0, cycle_end = 0; |
@@ -1404,116 +1441,130 @@ static bool run(void) | |||
1404 | 1441 | ||
1405 | cycle_start = *rb->current_tick; | 1442 | cycle_start = *rb->current_tick; |
1406 | /* change the direction of the worm */ | 1443 | /* change the direction of the worm */ |
1407 | while (button != BTN_QUIT && ! wormDead) | 1444 | while (!wormDead) |
1408 | { | 1445 | { |
1409 | int i; | 1446 | int i; |
1410 | long cycle_duration ; | 1447 | long cycle_duration=0; |
1448 | |||
1411 | switch (button) { | 1449 | switch (button) { |
1412 | case BTN_DIR_UP: | 1450 | case BTN_STARTPAUSE: |
1413 | if (players == 1 && !use_remote) { | 1451 | paused = !paused; |
1414 | player1_dir = NORTH; | ||
1415 | } | ||
1416 | break; | 1452 | break; |
1417 | 1453 | case BTN_STOPRESET: | |
1418 | case BTN_DIR_DOWN: | 1454 | if (paused) |
1419 | if (players == 1 && !use_remote) { | 1455 | return 1; /* restart game */ |
1420 | player1_dir = SOUTH; | 1456 | else |
1421 | } | 1457 | paused = true; |
1422 | break; | 1458 | break; |
1423 | 1459 | case BTN_QUIT: | |
1424 | case BTN_DIR_LEFT: | 1460 | return 2; /* back to menu */ |
1425 | if (players != 1 || use_remote) { | ||
1426 | player1_dir = (player1_dir + 3) % 4; | ||
1427 | } else { | ||
1428 | player1_dir = WEST; | ||
1429 | } | ||
1430 | break; | 1461 | break; |
1462 | } | ||
1463 | if (!paused) | ||
1464 | { | ||
1465 | switch (button) { | ||
1466 | case BTN_DIR_UP: | ||
1467 | if (players == 1 && !use_remote) { | ||
1468 | player1_dir = NORTH; | ||
1469 | } | ||
1470 | break; | ||
1431 | 1471 | ||
1432 | case BTN_DIR_RIGHT: | 1472 | case BTN_DIR_DOWN: |
1433 | if (players != 1 || use_remote) { | 1473 | if (players == 1 && !use_remote) { |
1434 | player1_dir = (player1_dir + 1) % 4; | 1474 | player1_dir = SOUTH; |
1435 | } else { | 1475 | } |
1436 | player1_dir = EAST; | 1476 | break; |
1437 | } | 1477 | |
1438 | break; | 1478 | case BTN_DIR_LEFT: |
1479 | if (players != 1 || use_remote) { | ||
1480 | player1_dir = (player1_dir + 3) % 4; | ||
1481 | } else { | ||
1482 | player1_dir = WEST; | ||
1483 | } | ||
1484 | break; | ||
1485 | |||
1486 | case BTN_DIR_RIGHT: | ||
1487 | if (players != 1 || use_remote) { | ||
1488 | player1_dir = (player1_dir + 1) % 4; | ||
1489 | } else { | ||
1490 | player1_dir = EAST; | ||
1491 | } | ||
1492 | break; | ||
1439 | 1493 | ||
1440 | #ifdef MULTIPLAYER | 1494 | #ifdef MULTIPLAYER |
1441 | case BTN_PLAYER2_DIR1: | 1495 | case BTN_PLAYER2_DIR1: |
1442 | player2_dir = (player2_dir + 3) % 4; | 1496 | player2_dir = (player2_dir + 3) % 4; |
1443 | break; | 1497 | break; |
1444 | 1498 | ||
1445 | case BTN_PLAYER2_DIR2: | 1499 | case BTN_PLAYER2_DIR2: |
1446 | player2_dir = (player2_dir + 1) % 4; | 1500 | player2_dir = (player2_dir + 1) % 4; |
1447 | break; | 1501 | break; |
1448 | #endif | 1502 | #endif |
1449 | 1503 | ||
1450 | #ifdef REMOTE | 1504 | #ifdef REMOTE |
1451 | case BTN_RC_UP: | 1505 | case BTN_RC_UP: |
1452 | player3_dir = (player3_dir + 1) % 4; | 1506 | player3_dir = (player3_dir + 1) % 4; |
1453 | break; | 1507 | break; |
1454 | 1508 | ||
1455 | case BTN_RC_DOWN: | 1509 | case BTN_RC_DOWN: |
1456 | player3_dir = (player3_dir + 3) % 4; | 1510 | player3_dir = (player3_dir + 3) % 4; |
1457 | break; | 1511 | break; |
1458 | #endif | 1512 | #endif |
1513 | } | ||
1459 | 1514 | ||
1460 | case BTN_STARTPAUSE: | ||
1461 | do { | ||
1462 | button = rb->button_get(true); | ||
1463 | } while (button != BTN_STARTPAUSE && | ||
1464 | button != BTN_QUIT && | ||
1465 | button != BTN_STOPRESET); | ||
1466 | break; | ||
1467 | } | ||
1468 | 1515 | ||
1469 | for (i = 0; i < worm_count; i++) { | 1516 | for (i = 0; i < worm_count; i++) { |
1470 | worms[i].fetch_worm_direction(&worms[i]); | 1517 | worms[i].fetch_worm_direction(&worms[i]); |
1471 | } | 1518 | } |
1472 | 1519 | ||
1473 | wormDead = true; | ||
1474 | for (i = 0; i < worm_count; i++){ | ||
1475 | struct worm *w = &worms[i]; | ||
1476 | move_worm(w); | ||
1477 | wormDead &= process_collisions(w); | ||
1478 | draw_worm(w); | ||
1479 | } | ||
1480 | score_board(); | ||
1481 | rb->lcd_update(); | ||
1482 | if (button == BTN_STOPRESET) { | ||
1483 | wormDead = true; | 1520 | wormDead = true; |
1484 | } | 1521 | for (i = 0; i < worm_count; i++){ |
1522 | struct worm *w = &worms[i]; | ||
1523 | move_worm(w); | ||
1524 | wormDead &= process_collisions(w); | ||
1525 | draw_worm(w); | ||
1526 | } | ||
1527 | score_board(); | ||
1528 | rb->lcd_update(); | ||
1529 | if (button == BTN_STOPRESET) { | ||
1530 | wormDead = true; | ||
1531 | } | ||
1485 | 1532 | ||
1486 | /* here the wormlet game cycle ends | 1533 | /* here the wormlet game cycle ends |
1487 | thus the current tick is stored | 1534 | thus the current tick is stored |
1488 | as end time */ | 1535 | as end time */ |
1489 | cycle_end = *rb->current_tick; | 1536 | cycle_end = *rb->current_tick; |
1490 | 1537 | ||
1491 | /* The duration of the game cycle */ | 1538 | /* The duration of the game cycle */ |
1492 | cycle_duration = cycle_end - cycle_start; | 1539 | cycle_duration = cycle_end - cycle_start; |
1493 | cycle_duration = MAX(0, cycle_duration); | 1540 | cycle_duration = MAX(0, cycle_duration); |
1494 | cycle_duration = MIN(SPEED -1, cycle_duration); | 1541 | cycle_duration = MIN(speed -1, cycle_duration); |
1495 | 1542 | ||
1496 | 1543 | ||
1497 | #ifdef DEBUG_WORMLET | 1544 | #ifdef DEBUG_WORMLET |
1498 | ticks_to_max_cycle_reset--; | 1545 | ticks_to_max_cycle_reset--; |
1499 | if (ticks_to_max_cycle_reset <= 0) { | 1546 | if (ticks_to_max_cycle_reset <= 0) { |
1500 | max_cycle = 0; | 1547 | max_cycle = 0; |
1501 | } | 1548 | } |
1502 | 1549 | ||
1503 | if (max_cycle < cycle_duration) { | 1550 | if (max_cycle < cycle_duration) { |
1504 | max_cycle = cycle_duration; | 1551 | max_cycle = cycle_duration; |
1505 | ticks_to_max_cycle_reset = 20; | 1552 | ticks_to_max_cycle_reset = 20; |
1506 | } | 1553 | } |
1507 | rb->snprintf(buf, sizeof buf, "ticks %d", max_cycle); | 1554 | rb->snprintf(buf, sizeof buf, "ticks %d", max_cycle); |
1508 | set_debug_out(buf); | 1555 | set_debug_out(buf); |
1509 | #endif | 1556 | #endif |
1557 | } | ||
1510 | /* adjust the number of ticks to wait for a button. | 1558 | /* adjust the number of ticks to wait for a button. |
1511 | This ensures that a complete game cycle including | 1559 | This ensures that a complete game cycle including |
1512 | user input runs in constant time */ | 1560 | user input runs in constant time */ |
1513 | button = rb->button_get_w_tmo(SPEED - cycle_duration); | 1561 | button = rb->button_get_w_tmo(speed - cycle_duration); |
1514 | cycle_start = *rb->current_tick; | 1562 | cycle_start = *rb->current_tick; |
1515 | } | 1563 | } |
1516 | return wormDead; | 1564 | |
1565 | rb->splash(HZ*2, true, "Game Over!"); | ||
1566 | |||
1567 | return 2; /* back to menu */ | ||
1517 | } | 1568 | } |
1518 | 1569 | ||
1519 | #ifdef DEBUG_WORMLET | 1570 | #ifdef DEBUG_WORMLET |
@@ -1555,7 +1606,7 @@ static void test_worm_food_collision(void) { | |||
1555 | rb->lcd_putsxy(0, LCD_HEIGHT -8, buf); | 1606 | rb->lcd_putsxy(0, LCD_HEIGHT -8, buf); |
1556 | rb->lcd_update(); | 1607 | rb->lcd_update(); |
1557 | } | 1608 | } |
1558 | if (collision_count != FOOD_SIZE) { | 1609 | if (collision_count != food_size) { |
1559 | rb->button_get(true); | 1610 | rb->button_get(true); |
1560 | } | 1611 | } |
1561 | 1612 | ||
@@ -1574,7 +1625,7 @@ static void test_worm_food_collision(void) { | |||
1574 | rb->lcd_putsxy(0, LCD_HEIGHT -8, buf); | 1625 | rb->lcd_putsxy(0, LCD_HEIGHT -8, buf); |
1575 | rb->lcd_update(); | 1626 | rb->lcd_update(); |
1576 | } | 1627 | } |
1577 | if (collision_count != FOOD_SIZE * 2) { | 1628 | if (collision_count != food_size * 2) { |
1578 | rb->button_get(true); | 1629 | rb->button_get(true); |
1579 | } | 1630 | } |
1580 | 1631 | ||
@@ -1609,7 +1660,7 @@ static void test_worm_argh_collision(void) { | |||
1609 | } | 1660 | } |
1610 | 1661 | ||
1611 | arghx[0] = 12; | 1662 | arghx[0] = 12; |
1612 | for (arghy[0] = 0; arghy[0] < FIELD_RECT_HEIGHT - ARGH_SIZE; arghy[0]++){ | 1663 | for (arghy[0] = 0; arghy[0] < FIELD_RECT_HEIGHT - argh_size; arghy[0]++){ |
1613 | char buf[20]; | 1664 | char buf[20]; |
1614 | bool collision; | 1665 | bool collision; |
1615 | draw_argh(0); | 1666 | draw_argh(0); |
@@ -1621,12 +1672,12 @@ static void test_worm_argh_collision(void) { | |||
1621 | rb->lcd_putsxy(0, LCD_HEIGHT -8, buf); | 1672 | rb->lcd_putsxy(0, LCD_HEIGHT -8, buf); |
1622 | rb->lcd_update(); | 1673 | rb->lcd_update(); |
1623 | } | 1674 | } |
1624 | if (collision_count != ARGH_SIZE * 2) { | 1675 | if (collision_count != argh_size * 2) { |
1625 | rb->button_get(true); | 1676 | rb->button_get(true); |
1626 | } | 1677 | } |
1627 | 1678 | ||
1628 | arghy[0] = 12; | 1679 | arghy[0] = 12; |
1629 | for (arghx[0] = 0; arghx[0] < FIELD_RECT_HEIGHT - ARGH_SIZE; arghx[0]++){ | 1680 | for (arghx[0] = 0; arghx[0] < FIELD_RECT_HEIGHT - argh_size; arghx[0]++){ |
1630 | char buf[20]; | 1681 | char buf[20]; |
1631 | bool collision; | 1682 | bool collision; |
1632 | draw_argh(0); | 1683 | draw_argh(0); |
@@ -1638,7 +1689,7 @@ static void test_worm_argh_collision(void) { | |||
1638 | rb->lcd_putsxy(0, LCD_HEIGHT -8, buf); | 1689 | rb->lcd_putsxy(0, LCD_HEIGHT -8, buf); |
1639 | rb->lcd_update(); | 1690 | rb->lcd_update(); |
1640 | } | 1691 | } |
1641 | if (collision_count != ARGH_SIZE * 4) { | 1692 | if (collision_count != argh_size * 4) { |
1642 | rb->button_get(true); | 1693 | rb->button_get(true); |
1643 | } | 1694 | } |
1644 | } | 1695 | } |
@@ -1807,8 +1858,8 @@ static int testline_in_rect(void) { | |||
1807 | /* test 13 */ | 1858 | /* test 13 */ |
1808 | rx = 9; | 1859 | rx = 9; |
1809 | ry = 15; | 1860 | ry = 15; |
1810 | rw = FOOD_SIZE; | 1861 | rw = food_size; |
1811 | rh = FOOD_SIZE; | 1862 | rh = food_size; |
1812 | 1863 | ||
1813 | x1 = 10; | 1864 | x1 = 10; |
1814 | y1 = 10; | 1865 | y1 = 10; |
@@ -1923,11 +1974,11 @@ static void test_make_argh(void){ | |||
1923 | char buf[20]; | 1974 | char buf[20]; |
1924 | int x, y; | 1975 | int x, y; |
1925 | rb->srand(seed); | 1976 | rb->srand(seed); |
1926 | x = rb->rand() % (FIELD_RECT_WIDTH - ARGH_SIZE); | 1977 | x = rb->rand() % (FIELD_RECT_WIDTH - argh_size); |
1927 | y = rb->rand() % (FIELD_RECT_HEIGHT - ARGH_SIZE); | 1978 | y = rb->rand() % (FIELD_RECT_HEIGHT - argh_size); |
1928 | 1979 | ||
1929 | for (worm_idx = 0; worm_idx < worm_count; worm_idx++){ | 1980 | for (worm_idx = 0; worm_idx < worm_count; worm_idx++){ |
1930 | if (expensive_worm_in_rect(&worms[worm_idx], x, y, ARGH_SIZE, ARGH_SIZE)) { | 1981 | if (expensive_worm_in_rect(&worms[worm_idx], x, y, argh_size, argh_size)) { |
1931 | int tries = 0; | 1982 | int tries = 0; |
1932 | rb->srand(seed); | 1983 | rb->srand(seed); |
1933 | 1984 | ||
@@ -1939,12 +1990,12 @@ static void test_make_argh(void){ | |||
1939 | rb->snprintf(buf, sizeof buf, "(%d;%d) fail%d try%d", x, y, failures, tries); | 1990 | rb->snprintf(buf, sizeof buf, "(%d;%d) fail%d try%d", x, y, failures, tries); |
1940 | rb->lcd_putsxy(0, LCD_HEIGHT - 8, buf); | 1991 | rb->lcd_putsxy(0, LCD_HEIGHT - 8, buf); |
1941 | rb->lcd_update(); | 1992 | rb->lcd_update(); |
1942 | rb->lcd_invertrect(x + FIELD_RECT_X, y+ FIELD_RECT_Y, ARGH_SIZE, ARGH_SIZE); | 1993 | rb->lcd_invertrect(x + FIELD_RECT_X, y+ FIELD_RECT_Y, argh_size, argh_size); |
1943 | rb->lcd_update(); | 1994 | rb->lcd_update(); |
1944 | draw_argh(0); | 1995 | draw_argh(0); |
1945 | rb->lcd_update(); | 1996 | rb->lcd_update(); |
1946 | rb->lcd_invertrect(x + FIELD_RECT_X, y + FIELD_RECT_Y, ARGH_SIZE, ARGH_SIZE); | 1997 | rb->lcd_invertrect(x + FIELD_RECT_X, y + FIELD_RECT_Y, argh_size, argh_size); |
1947 | rb->lcd_clearrect(arghx[0] + FIELD_RECT_X, arghy[0] + FIELD_RECT_Y, ARGH_SIZE, ARGH_SIZE); | 1998 | rb->lcd_clearrect(arghx[0] + FIELD_RECT_X, arghy[0] + FIELD_RECT_Y, argh_size, argh_size); |
1948 | 1999 | ||
1949 | if (failures > last_failures) { | 2000 | if (failures > last_failures) { |
1950 | rb->button_get(true); | 2001 | rb->button_get(true); |
@@ -1978,7 +2029,7 @@ static void test_worm_argh_collision_in_moves(void) { | |||
1978 | rb->lcd_putsxy(0, LCD_HEIGHT - 8, buf); | 2029 | rb->lcd_putsxy(0, LCD_HEIGHT - 8, buf); |
1979 | rb->lcd_update(); | 2030 | rb->lcd_update(); |
1980 | } | 2031 | } |
1981 | if (hit_count != ARGH_SIZE + 5) { | 2032 | if (hit_count != argh_size + 5) { |
1982 | rb->button_get(true); | 2033 | rb->button_get(true); |
1983 | } | 2034 | } |
1984 | } | 2035 | } |
@@ -1987,20 +2038,252 @@ static void test_worm_argh_collision_in_moves(void) { | |||
1987 | extern bool use_old_rect; | 2038 | extern bool use_old_rect; |
1988 | 2039 | ||
1989 | /** | 2040 | /** |
2041 | * These are additional functions required to set various wormlet settings | ||
2042 | * and to enable saving of settings and high score | ||
2043 | */ | ||
2044 | |||
2045 | /* | ||
2046 | Sets the total number of worms, both human and machine | ||
2047 | */ | ||
2048 | bool set_worm_num_worms(void) | ||
2049 | { | ||
2050 | bool ret; | ||
2051 | static const struct opt_items num_worms_option[3] = { | ||
2052 | { "1", NULL }, | ||
2053 | { "2", NULL }, | ||
2054 | { "3", NULL }, | ||
2055 | }; | ||
2056 | |||
2057 | ret = rb->set_option("Number Of Worms", &worm_count,INT, num_worms_option, 3, NULL); | ||
2058 | if (worm_count < players) { | ||
2059 | worm_count=players; | ||
2060 | } | ||
2061 | return ret; | ||
2062 | } | ||
2063 | |||
2064 | /* | ||
2065 | Sets the number of human players | ||
2066 | */ | ||
2067 | bool set_worm_num_players(void) | ||
2068 | { | ||
2069 | bool ret; | ||
2070 | static const struct opt_items num_players_option[4] = { | ||
2071 | { "0", NULL }, | ||
2072 | { "1", NULL }, | ||
2073 | { "2", NULL }, | ||
2074 | { "3", NULL } | ||
2075 | }; | ||
2076 | |||
2077 | ret = rb->set_option("Number of Players", &players, INT,num_players_option , 4, NULL); | ||
2078 | if (players > worm_count) { | ||
2079 | worm_count = players; | ||
2080 | } | ||
2081 | if (players > 2) { | ||
2082 | use_remote = true; | ||
2083 | } | ||
2084 | return ret; | ||
2085 | } | ||
2086 | |||
2087 | /* | ||
2088 | Sets the size of each argh block created | ||
2089 | */ | ||
2090 | bool set_worm_argh_size(void) | ||
2091 | { | ||
2092 | static const struct opt_items argh_size_option[11] = { | ||
2093 | { "0", NULL }, | ||
2094 | { "1", NULL }, | ||
2095 | { "2", NULL }, | ||
2096 | { "3", NULL }, | ||
2097 | { "4", NULL }, | ||
2098 | { "5", NULL }, | ||
2099 | { "6", NULL }, | ||
2100 | { "7", NULL }, | ||
2101 | { "8", NULL }, | ||
2102 | { "9", NULL }, | ||
2103 | { "10", NULL } | ||
2104 | }; | ||
2105 | |||
2106 | return rb->set_option("Argh Size", &argh_size,INT,argh_size_option , 11, NULL); | ||
2107 | } | ||
2108 | |||
2109 | /* | ||
2110 | Sets the amount a worm grows per food | ||
2111 | */ | ||
2112 | bool set_worm_food(void) | ||
2113 | { | ||
2114 | static const struct opt_items worm_food_option[11] = { | ||
2115 | { "0", NULL }, | ||
2116 | { "1", NULL }, | ||
2117 | { "2", NULL }, | ||
2118 | { "3", NULL }, | ||
2119 | { "4", NULL }, | ||
2120 | { "5", NULL }, | ||
2121 | { "6", NULL }, | ||
2122 | { "7", NULL }, | ||
2123 | { "8", NULL }, | ||
2124 | { "9", NULL }, | ||
2125 | { "10", NULL } | ||
2126 | }; | ||
2127 | return rb->set_option("Worm Growth Per Food", &worm_food,INT,worm_food_option , 11, NULL); | ||
2128 | } | ||
2129 | |||
2130 | /* | ||
2131 | Sets the number of arghs created per food | ||
2132 | */ | ||
2133 | bool set_argh_per_food(void) | ||
2134 | { | ||
2135 | static const struct opt_items argh_food_option[5] = { | ||
2136 | { "0", NULL }, | ||
2137 | { "1", NULL }, | ||
2138 | { "2", NULL }, | ||
2139 | { "3", NULL }, | ||
2140 | { "4", NULL }, | ||
2141 | }; | ||
2142 | return rb->set_option("Arghs Per Food", &arghs_per_food,INT,argh_food_option , 5, NULL); | ||
2143 | } | ||
2144 | |||
2145 | /* | ||
2146 | Sets the number of ticks per move | ||
2147 | */ | ||
2148 | bool set_worm_speed(void) | ||
2149 | { | ||
2150 | bool ret; | ||
2151 | static const struct opt_items speed_option[19] = { | ||
2152 | { "0", NULL }, | ||
2153 | { "1", NULL }, | ||
2154 | { "2", NULL }, | ||
2155 | { "3", NULL }, | ||
2156 | { "4", NULL }, | ||
2157 | { "5", NULL }, | ||
2158 | { "6", NULL }, | ||
2159 | { "7", NULL }, | ||
2160 | { "8", NULL }, | ||
2161 | { "9", NULL }, | ||
2162 | { "10", NULL }, | ||
2163 | { "11", NULL }, | ||
2164 | { "12", NULL }, | ||
2165 | { "13", NULL }, | ||
2166 | { "14", NULL }, | ||
2167 | { "15", NULL }, | ||
2168 | { "16", NULL }, | ||
2169 | { "17", NULL }, | ||
2170 | { "18", NULL }, | ||
2171 | }; | ||
2172 | |||
2173 | |||
2174 | speed = 20 - speed; | ||
2175 | ret = rb->set_option("Worm Speed", &speed,INT,speed_option , 19, NULL); | ||
2176 | speed = 20 - speed; | ||
2177 | return ret; | ||
2178 | } | ||
2179 | |||
2180 | /* | ||
2181 | Sets the control style, which depends on the number of players, | ||
2182 | remote control existing, etc | ||
2183 | bool set_bool_options(char* string, bool* variable, | ||
2184 | char* yes_str, char* no_str, void (*function)(bool)) | ||
2185 | */ | ||
2186 | bool set_worm_control_style(void) | ||
2187 | { | ||
2188 | static const struct opt_items key1_option[2] = { | ||
2189 | { "Remote Control", NULL }, | ||
2190 | { "No Rem. Control", NULL }, | ||
2191 | }; | ||
2192 | |||
2193 | static const struct opt_items key2_option[2] = { | ||
2194 | { "2 Key Control", NULL }, | ||
2195 | { "4 Key COntrol", NULL }, | ||
2196 | }; | ||
2197 | |||
2198 | static const struct opt_items key3_option[1] = { | ||
2199 | { "Out of Control", NULL }, | ||
2200 | }; | ||
2201 | |||
2202 | if (players > 1) { | ||
2203 | rb->set_option("Control Style",&use_remote,INT, key1_option, 2, NULL); | ||
2204 | } else { | ||
2205 | if (players > 0) { | ||
2206 | rb->set_option("Control Style",&use_remote,INT, key2_option, 2, NULL); | ||
2207 | } | ||
2208 | else { | ||
2209 | rb->set_option("Control Style",&use_remote,INT, key3_option, 1, NULL); | ||
2210 | } | ||
2211 | } | ||
2212 | return false; | ||
2213 | } | ||
2214 | |||
2215 | void default_settings(void) | ||
2216 | { | ||
2217 | arghs_per_food = ARGHS_PER_FOOD; | ||
2218 | argh_size = ARGH_SIZE; | ||
2219 | food_size = FOOD_SIZE; | ||
2220 | speed = SPEED; | ||
2221 | worm_food = WORM_PER_FOOD; | ||
2222 | players = 1; | ||
2223 | worm_count = MAX_WORMS; | ||
2224 | use_remote = false; | ||
2225 | return; | ||
2226 | } | ||
2227 | |||
2228 | /* | ||
2229 | Launches the wormlet game | ||
2230 | */ | ||
2231 | bool launch_wormlet(void) | ||
2232 | { | ||
2233 | int game_result = 1; | ||
2234 | |||
2235 | rb->lcd_clear_display(); | ||
2236 | |||
2237 | /* Permanently enable the backlight (unless the user has turned it off) */ | ||
2238 | if (rb->global_settings->backlight_timeout > 0) | ||
2239 | rb->backlight_set_timeout(1); | ||
2240 | |||
2241 | /* start the game */ | ||
2242 | while (game_result == 1) | ||
2243 | game_result = run(); | ||
2244 | |||
2245 | switch (game_result) | ||
2246 | { | ||
2247 | case 2: | ||
2248 | /* Restore user's original backlight setting */ | ||
2249 | rb->backlight_set_timeout(rb->global_settings->backlight_timeout); | ||
2250 | return false; | ||
2251 | break; | ||
2252 | } | ||
2253 | return false; | ||
2254 | } | ||
2255 | |||
2256 | /* End of settings/changes etc */ | ||
2257 | |||
2258 | /** | ||
1990 | * Main entry point | 2259 | * Main entry point |
1991 | */ | 2260 | */ |
1992 | enum plugin_status plugin_start(struct plugin_api* api, void* parameter) | 2261 | enum plugin_status plugin_start(struct plugin_api* api, void* parameter) |
1993 | { | 2262 | { |
1994 | bool worm_dead = false; | 2263 | int m; |
1995 | int button; | 2264 | int result; |
2265 | int menu_quit = 0; | ||
2266 | int new_setting; | ||
1996 | 2267 | ||
1997 | (void)(parameter); | 2268 | (void)(parameter); |
1998 | |||
1999 | rb = api; | 2269 | rb = api; |
2000 | rb->lcd_setfont(FONT_SYSFIXED); | 2270 | |
2271 | default_settings(); | ||
2272 | configfile_init(rb); | ||
2273 | if (configfile_load(SETTINGS_FILENAME, config, | ||
2274 | sizeof(config)/sizeof(*config), | ||
2275 | SETTINGS_MIN_VERSION ) < 0) | ||
2276 | { | ||
2277 | /* If the loading failed, save a new config file (as the disk is | ||
2278 | already spinning) */ | ||
2279 | configfile_save(SETTINGS_FILENAME, config, | ||
2280 | sizeof(config)/sizeof(*config), | ||
2281 | SETTINGS_VERSION); | ||
2282 | } | ||
2001 | 2283 | ||
2002 | #ifdef HAVE_LCD_COLOR | 2284 | #ifdef HAVE_LCD_COLOR |
2003 | rb->lcd_set_background(LCD_RGBPACK(200, 210, 230)); | 2285 | rb->lcd_set_foreground(COLOR_FG); |
2286 | rb->lcd_set_background(COLOR_BG); | ||
2004 | #endif | 2287 | #endif |
2005 | 2288 | ||
2006 | #ifdef DEBUG_WORMLET | 2289 | #ifdef DEBUG_WORMLET |
@@ -2013,132 +2296,259 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter) | |||
2013 | #endif | 2296 | #endif |
2014 | 2297 | ||
2015 | /* Setup screen */ | 2298 | /* Setup screen */ |
2016 | do { | ||
2017 | char buf[40]; | ||
2018 | #if defined MULTIPLAYER && defined REMOTE | ||
2019 | char* ptr; | ||
2020 | #endif | ||
2021 | rb->lcd_clear_display(); | ||
2022 | 2299 | ||
2023 | /* first line players */ | 2300 | static const struct opt_items noyes[2] = { |
2301 | { "No", NULL }, | ||
2302 | { "Yes", NULL }, | ||
2303 | }; | ||
2304 | |||
2305 | static const struct opt_items num_worms_option[3] = { | ||
2306 | { "1", NULL }, | ||
2307 | { "2", NULL }, | ||
2308 | { "3", NULL } | ||
2309 | }; | ||
2310 | |||
2024 | #ifdef MULTIPLAYER | 2311 | #ifdef MULTIPLAYER |
2025 | rb->snprintf(buf, sizeof buf, "%d Players (%s)", players, PLAYERS_TEXT); | 2312 | static const struct opt_items num_players_option[4] = { |
2026 | #else | 2313 | #else |
2027 | rb->snprintf(buf, sizeof buf, "1 Player"); | 2314 | static const struct opt_items num_players_option[2] = { |
2028 | #endif | 2315 | #endif |
2029 | rb->lcd_puts(0, 0, buf); | 2316 | { "0", NULL }, |
2030 | 2317 | { "1", NULL } | |
2031 | /* second line worms */ | 2318 | #ifdef MULTIPLAYER |
2032 | rb->snprintf(buf, sizeof buf, "%d Worms (%s)", worm_count, WORMS_TEXT); | 2319 | ,{ "2", NULL }, |
2033 | rb->lcd_puts(0, 1, buf); | 2320 | { "3", NULL } |
2034 | |||
2035 | #if defined MULTIPLAYER && defined REMOTE | ||
2036 | /* third line control */ | ||
2037 | if (players > 1) { | ||
2038 | if (use_remote) { | ||
2039 | rb->snprintf(buf, sizeof(buf), "Remote Control (%s)", KEY_CONTROL_TEXT); | ||
2040 | ptr = buf; | ||
2041 | } else { | ||
2042 | rb->snprintf(buf, sizeof(buf), "No Rem. Control (%s)", KEY_CONTROL_TEXT); | ||
2043 | ptr = buf; | ||
2044 | } | ||
2045 | } else { | ||
2046 | if (players > 0) { | ||
2047 | if (use_remote) { | ||
2048 | rb->snprintf(buf, sizeof(buf), "2 Key Control (%s)", KEY_CONTROL_TEXT); | ||
2049 | ptr = buf; | ||
2050 | } else { | ||
2051 | rb->snprintf(buf, sizeof(buf), "4 Key Control (%s)", KEY_CONTROL_TEXT); | ||
2052 | ptr = buf; | ||
2053 | } | ||
2054 | } else { | ||
2055 | ptr = "Out Of Control"; | ||
2056 | } | ||
2057 | } | ||
2058 | rb->lcd_puts(0, 2, ptr); | ||
2059 | #endif | 2321 | #endif |
2060 | rb->lcd_update(); | 2322 | }; |
2061 | 2323 | ||
2062 | /* user selection */ | 2324 | static const struct opt_items argh_size_option[9] = { |
2063 | button = rb->button_get(true); | 2325 | { "2", NULL }, |
2064 | switch (button) { | 2326 | { "3", NULL }, |
2327 | { "4", NULL }, | ||
2328 | { "5", NULL }, | ||
2329 | { "6", NULL }, | ||
2330 | { "7", NULL }, | ||
2331 | { "8", NULL }, | ||
2332 | { "9", NULL }, | ||
2333 | { "10", NULL } | ||
2334 | }; | ||
2335 | |||
2336 | static const struct opt_items food_size_option[9] = { | ||
2337 | { "2", NULL }, | ||
2338 | { "3", NULL }, | ||
2339 | { "4", NULL }, | ||
2340 | { "5", NULL }, | ||
2341 | { "6", NULL }, | ||
2342 | { "7", NULL }, | ||
2343 | { "8", NULL }, | ||
2344 | { "9", NULL }, | ||
2345 | { "10", NULL } | ||
2346 | }; | ||
2347 | |||
2348 | static const struct opt_items worm_food_option[16] = { | ||
2349 | { "0", NULL }, | ||
2350 | { "1", NULL }, | ||
2351 | { "2", NULL }, | ||
2352 | { "3", NULL }, | ||
2353 | { "4", NULL }, | ||
2354 | { "5", NULL }, | ||
2355 | { "6", NULL }, | ||
2356 | { "7", NULL }, | ||
2357 | { "8", NULL }, | ||
2358 | { "9", NULL }, | ||
2359 | { "10", NULL }, | ||
2360 | { "11", NULL }, | ||
2361 | { "12", NULL }, | ||
2362 | { "13", NULL }, | ||
2363 | { "14", NULL }, | ||
2364 | { "15", NULL } | ||
2365 | }; | ||
2366 | |||
2367 | static const struct opt_items argh_food_option[9] = { | ||
2368 | { "0", NULL }, | ||
2369 | { "1", NULL }, | ||
2370 | { "2", NULL }, | ||
2371 | { "3", NULL }, | ||
2372 | { "4", NULL }, | ||
2373 | { "5", NULL }, | ||
2374 | { "6", NULL }, | ||
2375 | { "7", NULL }, | ||
2376 | { "8", NULL } | ||
2377 | }; | ||
2378 | |||
2379 | static const struct opt_items speed_option[21] = { | ||
2380 | { "0", NULL }, | ||
2381 | { "1", NULL }, | ||
2382 | { "2", NULL }, | ||
2383 | { "3", NULL }, | ||
2384 | { "4", NULL }, | ||
2385 | { "5", NULL }, | ||
2386 | { "6", NULL }, | ||
2387 | { "7", NULL }, | ||
2388 | { "8", NULL }, | ||
2389 | { "9", NULL }, | ||
2390 | { "10", NULL }, | ||
2391 | { "11", NULL }, | ||
2392 | { "12", NULL }, | ||
2393 | { "13", NULL }, | ||
2394 | { "14", NULL }, | ||
2395 | { "15", NULL }, | ||
2396 | { "16", NULL }, | ||
2397 | { "17", NULL }, | ||
2398 | { "18", NULL }, | ||
2399 | { "19", NULL }, | ||
2400 | { "20", NULL } | ||
2401 | }; | ||
2402 | |||
2403 | static const struct opt_items remoteonly_option[1] = { | ||
2404 | { "Remote Control", NULL } | ||
2405 | }; | ||
2406 | |||
2407 | static const struct opt_items key24_option[2] = { | ||
2408 | { "4 Key Control", NULL }, | ||
2409 | { "2 Key Control", NULL } | ||
2410 | }; | ||
2411 | |||
2412 | #ifdef REMOTE | ||
2413 | static const struct opt_items remote_option[2] = { | ||
2414 | { "Remote Control", NULL }, | ||
2415 | { "No Rem. Control", NULL } | ||
2416 | }; | ||
2417 | #else | ||
2418 | static const struct opt_items key2_option[1] = { | ||
2419 | { "2 Key Control", NULL } | ||
2420 | }; | ||
2421 | #endif | ||
2422 | |||
2423 | static const struct opt_items nokey_option[1] = { | ||
2424 | { "Out of Control", NULL } | ||
2425 | }; | ||
2426 | |||
2427 | static const struct menu_item items[] = { | ||
2428 | { "Play Wormlet!", NULL }, | ||
2429 | { "Number of Worms", NULL }, | ||
2430 | { "Number of Players", NULL }, | ||
2431 | { "Control Style", NULL }, | ||
2432 | { "Worm Growth Per Food", NULL }, | ||
2433 | { "Worm Speed", NULL }, | ||
2434 | { "Arghs Per Food", NULL }, | ||
2435 | { "Argh Size", NULL }, | ||
2436 | { "Food Size", NULL }, | ||
2437 | { "Revert to Default Settings", NULL }, | ||
2438 | { "Quit", NULL } | ||
2439 | }; | ||
2440 | |||
2441 | m = rb->menu_init(items, sizeof(items) / sizeof(*items), | ||
2442 | NULL, NULL, NULL, NULL); | ||
2443 | |||
2444 | rb->button_clear_queue(); | ||
2445 | |||
2446 | while (!menu_quit) { | ||
2447 | result = rb->menu_show(m); | ||
2448 | |||
2449 | switch(result) | ||
2450 | { | ||
2451 | case 0: | ||
2452 | rb->lcd_setfont(FONT_SYSFIXED); | ||
2453 | launch_wormlet(); | ||
2454 | break; | ||
2455 | case 1: | ||
2456 | new_setting = worm_count - 1; | ||
2457 | rb->set_option("Number of Worms", &new_setting, INT, num_worms_option, 3, NULL); | ||
2458 | if (new_setting != worm_count) | ||
2459 | worm_count = new_setting + 1; | ||
2460 | if (worm_count < players) { | ||
2461 | worm_count = players; | ||
2462 | } | ||
2463 | break; | ||
2464 | case 2: | ||
2465 | new_setting = players; | ||
2065 | #ifdef MULTIPLAYER | 2466 | #ifdef MULTIPLAYER |
2066 | case BTN_TOGGLE_KEYS: | 2467 | rb->set_option("Number of Players", &new_setting, INT, num_players_option , 4, NULL); |
2067 | use_remote = !use_remote; | 2468 | #else |
2469 | rb->set_option("Number of Players", &new_setting, INT, num_players_option , 2, NULL); | ||
2470 | #endif | ||
2471 | if (new_setting != players) | ||
2472 | players = new_setting; | ||
2473 | if (players > worm_count) { | ||
2474 | worm_count = players; | ||
2475 | } | ||
2068 | if (players > 2) { | 2476 | if (players > 2) { |
2069 | use_remote = true; | 2477 | use_remote = true; |
2070 | } | 2478 | } |
2071 | break; | 2479 | break; |
2072 | 2480 | case 3: | |
2073 | case BTN_DIR_UP: | 2481 | new_setting = use_remote; |
2074 | if (players < 3) { | 2482 | switch(players) { |
2075 | players ++; | 2483 | case 0: |
2076 | if (players > worm_count) { | 2484 | rb->set_option("Control Style",&new_setting,INT, nokey_option, 1, NULL); |
2077 | worm_count = players; | 2485 | break; |
2078 | } | 2486 | case 1: |
2079 | if (players > 2) { | 2487 | rb->set_option("Control Style",&new_setting,INT, key24_option, 2, NULL); |
2080 | use_remote = true; | 2488 | break; |
2081 | } | 2489 | case 2: |
2490 | #ifdef REMOTE | ||
2491 | rb->set_option("Control Style",&new_setting,INT, remote_option, 2, NULL); | ||
2492 | #else | ||
2493 | rb->set_option("Control Style",&new_setting,INT, key2_option, 1, NULL); | ||
2494 | #endif | ||
2495 | break; | ||
2496 | case 3: | ||
2497 | rb->set_option("Control Style",&new_setting,INT, remoteonly_option, 1, NULL); | ||
2498 | break; | ||
2082 | } | 2499 | } |
2500 | if (new_setting != use_remote) | ||
2501 | use_remote = new_setting; | ||
2083 | break; | 2502 | break; |
2084 | 2503 | case 4: | |
2085 | case BTN_DIR_DOWN: | 2504 | new_setting = worm_food; |
2086 | if (players > 0) { | 2505 | rb->set_option("Worm Growth Per Food", &new_setting,INT,worm_food_option , 16, NULL); |
2087 | players --; | 2506 | if (new_setting != worm_food) |
2088 | } | 2507 | worm_food = new_setting; |
2089 | break; | 2508 | break; |
2090 | #endif | 2509 | case 5: |
2091 | case BTN_DIR_LEFT: | 2510 | new_setting = speed; |
2092 | if (worm_count > 1) { | 2511 | new_setting = 20 - new_setting; |
2093 | worm_count--; | 2512 | rb->set_option("Worm Speed", &new_setting,INT,speed_option , 21, NULL); |
2094 | if (worm_count < players) { | 2513 | new_setting = 20 - new_setting; |
2095 | players = worm_count; | 2514 | if (new_setting != speed) |
2096 | } | 2515 | speed = new_setting; |
2097 | } | ||
2098 | break; | 2516 | break; |
2099 | 2517 | case 6: | |
2100 | case BTN_DIR_RIGHT: | 2518 | new_setting = arghs_per_food; |
2101 | if (worm_count < MAX_WORMS) { | 2519 | rb->set_option("Arghs Per Food", &new_setting,INT,argh_food_option , 9, NULL); |
2102 | worm_count ++; | 2520 | if (new_setting != arghs_per_food) |
2103 | } | 2521 | arghs_per_food = new_setting; |
2522 | break; | ||
2523 | case 7: | ||
2524 | new_setting = argh_size-2; | ||
2525 | rb->set_option("Argh Size", &new_setting,INT,argh_size_option , 9, NULL); | ||
2526 | if (new_setting != argh_size) | ||
2527 | argh_size = new_setting+2; | ||
2528 | break; | ||
2529 | case 8: | ||
2530 | new_setting = food_size-2; | ||
2531 | rb->set_option("Food Size", &new_setting,INT,food_size_option, 9, NULL); | ||
2532 | if (new_setting != food_size) | ||
2533 | food_size = new_setting+2; | ||
2534 | break; | ||
2535 | case 9: | ||
2536 | new_setting = 0; | ||
2537 | rb->set_option("Reset Settings?", &new_setting,INT, noyes , 2, NULL); | ||
2538 | if (new_setting == 1) | ||
2539 | default_settings(); | ||
2104 | break; | 2540 | break; |
2105 | |||
2106 | default: | 2541 | default: |
2107 | if (rb->default_event_handler(button) == SYS_USB_CONNECTED) | 2542 | menu_quit=1; |
2108 | return PLUGIN_USB_CONNECTED; | ||
2109 | break; | 2543 | break; |
2110 | } | 2544 | } |
2111 | } while (button != BTN_STARTPAUSE && | 2545 | } |
2112 | button != BTN_QUIT && button != BTN_STOPRESET); | ||
2113 | |||
2114 | rb->lcd_clear_display(); | ||
2115 | /* end of setup */ | ||
2116 | |||
2117 | do { | ||
2118 | |||
2119 | /* button state will be overridden if | ||
2120 | the game quits with the death of the worm. | ||
2121 | Initializing button to BTN_QUIT ensures | ||
2122 | that the user can hit BTN_QUIT during the | ||
2123 | game to return to the menu. | ||
2124 | */ | ||
2125 | button = BTN_QUIT; | ||
2126 | 2546 | ||
2127 | /* start the game */ | 2547 | rb->menu_exit(m); |
2128 | worm_dead = run(); | ||
2129 | 2548 | ||
2130 | /* if worm isn't dead the game was quit | 2549 | configfile_save(SETTINGS_FILENAME, config, |
2131 | via BTN_QUIT -> no need to wait for buttons. */ | 2550 | sizeof(config)/sizeof(*config), |
2132 | if (worm_dead) { | 2551 | SETTINGS_VERSION); |
2133 | do { | ||
2134 | button = rb->button_get(true); | ||
2135 | } | ||
2136 | /* BTN_STOPRESET -> start new game */ | ||
2137 | /* BTN_QUIT -> back to game menu */ | ||
2138 | while (button != BTN_QUIT && button != BTN_STOPRESET); | ||
2139 | } | ||
2140 | } | ||
2141 | while (button != BTN_QUIT); | ||
2142 | 2552 | ||
2143 | return PLUGIN_OK; | 2553 | return PLUGIN_OK; |
2144 | } | 2554 | } |