summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZakk Roberts <midk@rockbox.org>2006-05-22 06:56:39 +0000
committerZakk Roberts <midk@rockbox.org>2006-05-22 06:56:39 +0000
commit02e97d58b1ca3424b661322a69fea96eb3fa14bf (patch)
treeacd1ade9ac39212242a11802494ff8a6525f5249
parentd072ca6b177eae8e5086425d765612f06df10e2e (diff)
downloadrockbox-02e97d58b1ca3424b661322a69fea96eb3fa14bf.tar.gz
rockbox-02e97d58b1ca3424b661322a69fea96eb3fa14bf.zip
Patch attached to bug report #5077 by Ewan Davies which fixes argh/food generation on larger LCDs. His patch also brings up-to-date and includes Tom Evans' patch #1510 to start Wormlet with a menu for adjusting almost everything about the game (argh size, number, food size, number, growth rate, worm speed...). Some changes by me. Probably not bugfree, but Works For Me (tm).
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@9972 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/plugins/wormlet.c924
-rw-r--r--docs/CREDITS2
2 files changed, 669 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
21PLUGIN_HEADER 22PLUGIN_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 */
165static char foodx[MAX_FOOD]; 175static int foodx[MAX_FOOD];
166static char foody[MAX_FOOD]; 176static 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 */
172static char arghx[MAX_ARGH]; 182static int arghx[MAX_ARGH];
173static char arghy[MAX_ARGH]; 183static 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 */
176static int argh_count; 186static int argh_count;
177 187
188/* the number of arghs per food, settable by user */
189static int arghs_per_food = ARGHS_PER_FOOD;
190/* the size of the argh, settable by user */
191static int argh_size = ARGH_SIZE;
192/* the size of the food, settable by user */
193static int food_size = FOOD_SIZE;
194/* the speed of the worm, settable by user */
195static int speed = SPEED;
196/* the amount a worm grows by eating a food, settable by user */
197static 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 */
180static char debugout[15]; 203static char debugout[15];
@@ -217,6 +240,23 @@ static int players = 1;
217/* the rockbox plugin api */ 240/* the rockbox plugin api */
218static struct plugin_api* rb; 241static struct plugin_api* rb;
219 242
243#define SETTINGS_VERSION 1
244#define SETTINGS_MIN_VERSION 1
245#define SETTINGS_FILENAME "wormlet.cfg"
246
247static 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
221static void set_debug_out(char *str){ 261static 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) {
432static bool specific_food_collision(int foodIndex, int x, int y) { 472static 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 */
567static int make_food(int index) { 607static 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 */
658static int make_argh(int index) 696static 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)
935static void draw_worm(struct worm *w) 971static 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 */
1389static bool run(void) 1425static 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) {
1987extern bool use_old_rect; 2038extern 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/*
2046Sets the total number of worms, both human and machine
2047*/
2048bool 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/*
2065Sets the number of human players
2066*/
2067bool 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/*
2088Sets the size of each argh block created
2089*/
2090bool 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/*
2110Sets the amount a worm grows per food
2111*/
2112bool 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/*
2131Sets the number of arghs created per food
2132*/
2133bool 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/*
2146Sets the number of ticks per move
2147*/
2148bool 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/*
2181Sets the control style, which depends on the number of players,
2182remote control existing, etc
2183bool set_bool_options(char* string, bool* variable,
2184 char* yes_str, char* no_str, void (*function)(bool))
2185*/
2186bool 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
2215void 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/*
2229Launches the wormlet game
2230*/
2231bool 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 */
1992enum plugin_status plugin_start(struct plugin_api* api, void* parameter) 2261enum 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}
diff --git a/docs/CREDITS b/docs/CREDITS
index d7d112c1ec..9c89a6a3e9 100644
--- a/docs/CREDITS
+++ b/docs/CREDITS
@@ -202,3 +202,5 @@ Marianne Arnold
202Gaetano Vocca 202Gaetano Vocca
203Frederik Vestre 203Frederik Vestre
204Wenbin Leo 204Wenbin Leo
205Tom Evans
206Ewan Davies