Index: apps/plugin.c =================================================================== RCS file: /cvsroot/rockbox/apps/plugin.c,v retrieving revision 1.3 diff -u -b -r1.3 plugin.c --- apps/plugin.c 29 Jun 2003 23:38:03 -0000 1.3 +++ apps/plugin.c 9 Jul 2003 00:40:14 -0000 @@ -30,6 +30,8 @@ #include "mas.h" #include "plugin.h" #include "lang.h" +#include "menu.h" +#include "settings.h" #ifdef SIMULATOR #include @@ -59,6 +61,7 @@ #ifdef HAVE_LCD_CHARCELLS lcd_define_pattern, #else + lcd_setmargins, lcd_putsxy, lcd_bitmap, lcd_drawline, @@ -125,6 +128,13 @@ rand, splash, qsort, + + /* menu */ + menu_init, + menu_exit, + menu_run, + set_int, + set_bool_options, }; int plugin_load(char* plugin, void* parameter) Index: apps/plugin.h =================================================================== RCS file: /cvsroot/rockbox/apps/plugin.h,v retrieving revision 1.2 diff -u -b -r1.2 plugin.h --- apps/plugin.h 29 Jun 2003 21:42:15 -0000 1.2 +++ apps/plugin.h 9 Jul 2003 00:40:14 -0000 @@ -35,6 +35,8 @@ #include "font.h" #include "system.h" #include "lcd.h" +#include "menu.h" +#include "settings.h" /* increase this every time the api struct changes */ #define PLUGIN_API_VERSION 2 @@ -83,6 +85,7 @@ #ifdef HAVE_LCD_CHARCELLS void (*lcd_define_pattern)(int which,char *pattern); #else + void (*lcd_setmargins)(int xmargin, int ymargin); void (*lcd_putsxy)(int x, int y, unsigned char *string); void (*lcd_bitmap)(unsigned char *src, int x, int y, int nx, int ny, bool clear); @@ -151,6 +154,15 @@ void (*splash)(int ticks, int keymask, bool center, char *fmt, ...); void (*qsort)(void *base, size_t nmemb, size_t size, int(*compar)(const void *, const void *)); + + /* menu */ + int (*menu_init)(struct menu_items* mitems, int count); + void (*menu_exit)(int menu); + bool (*menu_run)(int menu); + bool (*set_int)(char* string, char* unit, int* variable, + void (*function)(int), int step, int min, int max ); + bool (*set_bool_options)(char* string, bool* variable, + char* yes_str, char* no_str, void (*function)(bool)); }; /* defined by the plugin loader (plugin.c) */ Index: apps/plugins/wormlet.c =================================================================== RCS file: /cvsroot/rockbox/apps/plugins/wormlet.c,v retrieving revision 1.1 diff -u -b -r1.1 wormlet.c --- apps/plugins/wormlet.c 29 Jun 2003 16:33:04 -0000 1.1 +++ apps/plugins/wormlet.c 9 Jul 2003 00:40:27 -0000 @@ -142,6 +142,24 @@ #endif /** + * These are additional variables used in the game + */ + +/* the number of arghs per food, settable by user */ +static int argh_per_food = ARGHS_PER_FOOD; + +/* the size of the argh, settable by user */ +static int argh_size = ARGH_SIZE; + +/* the speed of the worm, settable by user */ +static int speed = SPEED; + +/* the amount a worm grows by eating a food, settable by user */ +static int worm_food = WORM_PER_FOOD; + +/* End additional variables */ + +/** * Returns the direction id in which the worm * currently is creeping. * @param struct worm *w The worm that is to be investigated. @@ -390,8 +408,8 @@ if ( x >= arghx[arghIndex] && y >= arghy[arghIndex] && - x < arghx[arghIndex] + ARGH_SIZE && - y < arghy[arghIndex] + ARGH_SIZE ) + x < arghx[arghIndex] + argh_size && + y < arghy[arghIndex] + argh_size ) { return true; } @@ -456,7 +474,7 @@ y2 = w->y[w->head] + moves * w->diry; retVal = line_in_rect(x1, y1, x2, y2, arghx[argh_idx], arghy[argh_idx], - ARGH_SIZE, ARGH_SIZE); + argh_size, argh_size); return retVal; } @@ -471,7 +489,7 @@ bool retVal = false; retVal = worm_in_rect(w, arghx[arghIndex], arghy[arghIndex], - ARGH_SIZE - 1, ARGH_SIZE - 1); + argh_size - 1, argh_size - 1); return retVal; } @@ -574,8 +592,8 @@ do { /* make coordinates for a new argh so that the entire food lies within the FIELD */ - x = rb->rand() % (FIELD_RECT_WIDTH - ARGH_SIZE); - y = rb->rand() % (FIELD_RECT_HEIGHT - ARGH_SIZE); + x = rb->rand() % (FIELD_RECT_WIDTH - argh_size); + y = rb->rand() % (FIELD_RECT_HEIGHT - argh_size); tries ++; /* Ensure that the new argh doesn't intersect with any @@ -585,13 +603,13 @@ */ collisionDetected = food_collision(x , y ) >= 0 || - food_collision(x , y + ARGH_SIZE - 1) >= 0 || - food_collision(x + ARGH_SIZE - 1, y ) >= 0 || - food_collision(x + ARGH_SIZE - 1, y + ARGH_SIZE - 1) >= 0 || + food_collision(x , y + argh_size - 1) >= 0 || + food_collision(x + argh_size - 1, y ) >= 0 || + food_collision(x + argh_size - 1, y + argh_size - 1) >= 0 || argh_collision(x , y ) >= 0 || - argh_collision(x , y + ARGH_SIZE - 1) >= 0 || - argh_collision(x + ARGH_SIZE - 1, y ) >= 0 || - argh_collision(x + ARGH_SIZE - 1, y + ARGH_SIZE - 1) >= 0; + argh_collision(x , y + argh_size - 1) >= 0 || + argh_collision(x + argh_size - 1, y ) >= 0 || + argh_collision(x + argh_size - 1, y + argh_size - 1) >= 0; /* use the candidate coordinates to make a real argh */ arghx[index] = x; @@ -619,7 +637,7 @@ /* draw the new argh */ rb->lcd_fillrect(arghx[index] + FIELD_RECT_X, arghy[index] + FIELD_RECT_Y, - ARGH_SIZE, ARGH_SIZE); + argh_size, argh_size); } static void virtual_player(struct worm *w); @@ -1238,7 +1256,7 @@ make_food(index); draw_food(index); - for (i = 0; i < ARGHS_PER_FOOD; i++) { + for (i = 0; i < argh_per_food; i++) { argh_count++; if (argh_count > MAX_ARGH) argh_count = MAX_ARGH; @@ -1246,7 +1264,7 @@ draw_argh(argh_count - 1); } - add_growing(w, WORM_PER_FOOD); + add_growing(w, worm_food); draw_worm(w); } @@ -1374,7 +1392,7 @@ /* The duration of the game cycle */ cycle_duration = cycle_end - cycle_start; cycle_duration = MAX(0, cycle_duration); - cycle_duration = MIN(SPEED -1, cycle_duration); + cycle_duration = MIN(speed -1, cycle_duration); #ifdef DEBUG_WORMLET @@ -1393,7 +1411,7 @@ /* adjust the number of ticks to wait for a button. This ensures that a complete game cycle including user input runs in constant time */ - button = rb->button_get_w_tmo(SPEED - cycle_duration); + button = rb->button_get_w_tmo(speed - cycle_duration); cycle_start = *rb->current_tick; } return wormDead; @@ -1493,7 +1511,7 @@ } arghx[0] = 12; - for (arghy[0] = 0; arghy[0] < FIELD_RECT_HEIGHT - ARGH_SIZE; arghy[0]++){ + for (arghy[0] = 0; arghy[0] < FIELD_RECT_HEIGHT - argh_size; arghy[0]++){ char buf[20]; bool collision; draw_argh(0); @@ -1505,12 +1523,12 @@ rb->lcd_putsxy(0, LCD_HEIGHT -8, buf); rb->lcd_update(); } - if (collision_count != ARGH_SIZE * 2) { + if (collision_count != argh_size * 2) { rb->button_get(true); } arghy[0] = 12; - for (arghx[0] = 0; arghx[0] < FIELD_RECT_HEIGHT - ARGH_SIZE; arghx[0]++){ + for (arghx[0] = 0; arghx[0] < FIELD_RECT_HEIGHT - argh_size; arghx[0]++){ char buf[20]; bool collision; draw_argh(0); @@ -1522,7 +1540,7 @@ rb->lcd_putsxy(0, LCD_HEIGHT -8, buf); rb->lcd_update(); } - if (collision_count != ARGH_SIZE * 4) { + if (collision_count != argh_size * 4) { rb->button_get(true); } } @@ -1807,11 +1825,11 @@ char buf[20]; int x, y; rb->srand(seed); - x = rb->rand() % (FIELD_RECT_WIDTH - ARGH_SIZE); - y = rb->rand() % (FIELD_RECT_HEIGHT - ARGH_SIZE); + x = rb->rand() % (FIELD_RECT_WIDTH - argh_size); + y = rb->rand() % (FIELD_RECT_HEIGHT - argh_size); for (worm_idx = 0; worm_idx < worm_count; worm_idx++){ - if (expensive_worm_in_rect(&worms[worm_idx], x, y, ARGH_SIZE, ARGH_SIZE)) { + if (expensive_worm_in_rect(&worms[worm_idx], x, y, argh_size, argh_size)) { int tries = 0; rb->srand(seed); @@ -1823,12 +1841,12 @@ rb->snprintf(buf, sizeof buf, "(%d;%d) fail%d try%d", x, y, failures, tries); rb->lcd_putsxy(0, LCD_HEIGHT - 8, buf); rb->lcd_update(); - rb->lcd_invertrect(x + FIELD_RECT_X, y+ FIELD_RECT_Y, ARGH_SIZE, ARGH_SIZE); + rb->lcd_invertrect(x + FIELD_RECT_X, y+ FIELD_RECT_Y, argh_size, argh_size); rb->lcd_update(); draw_argh(0); rb->lcd_update(); - rb->lcd_invertrect(x + FIELD_RECT_X, y + FIELD_RECT_Y, ARGH_SIZE, ARGH_SIZE); - rb->lcd_clearrect(arghx[0] + FIELD_RECT_X, arghy[0] + FIELD_RECT_Y, ARGH_SIZE, ARGH_SIZE); + rb->lcd_invertrect(x + FIELD_RECT_X, y + FIELD_RECT_Y, argh_size, argh_size); + rb->lcd_clearrect(arghx[0] + FIELD_RECT_X, arghy[0] + FIELD_RECT_Y, argh_size, argh_size); if (failures > last_failures) { rb->button_get(true); @@ -1862,120 +1880,172 @@ rb->lcd_putsxy(0, LCD_HEIGHT - 8, buf); rb->lcd_update(); } - if (hit_count != ARGH_SIZE + 5) { + if (hit_count != argh_size + 5) { rb->button_get(true); } } #endif /* DEBUG_WORMLET */ extern bool use_old_rect; - /** - * Main entry point + * These are additional functions required to set various wormlet settings + * and to enable saving of settings and high score */ -enum plugin_status plugin_start(struct plugin_api* api, void* parameter) -{ - bool worm_dead = false; - int button; - TEST_PLUGIN_API(api); - (void)(parameter); - - rb = api; - rb->lcd_setfont(FONT_SYSFIXED); - -#ifdef DEBUG_WORMLET - testline_in_rect(); - test_worm_argh_collision_in_moves(); - test_make_argh(); - test_worm_food_collision(); - test_worm_argh_collision(); - test_specific_worm_collision(); -#endif - - /* Setup screen */ - do { - char buf[20]; - char* ptr; - rb->lcd_clear_display(); - - /* first line players */ - rb->snprintf(buf, sizeof buf, "%d Players UP/DN", players); - rb->lcd_puts(0, 0, buf); - - /* second line worms */ - rb->snprintf(buf, sizeof buf, "%d Worms L/R", worm_count); - rb->lcd_puts(0, 1, buf); +/* +Sets the total number of worms, both human and machine +*/ +bool set_worm_num_worms(void) +{ + bool ret; - /* third line control */ - if (players > 1) { - if (use_remote) { - ptr = "Remote Control F1"; - } else { - ptr = "No Rem. Control F1"; - } - } else { - if (players > 0) { - if (use_remote) { - ptr = "2 Key Control F1"; - } else { - ptr = "4 Key Control F1"; - } - } else { - ptr = "Out Of Control"; - } + ret = rb->set_int("Number Of Worms","",&worm_count,NULL,1,1,3); + if (worm_count < players) { + worm_count=players; } - rb->lcd_puts(0, 2, ptr); - rb->lcd_update(); + return ret; +} - /* user selection */ - button = rb->button_get(true); - switch (button) { - case BUTTON_UP: - if (players < 3) { - players ++; +/* +Sets the number of human players +*/ +bool set_worm_num_players(void) +{ + bool ret; + + ret = rb->set_int("Number Of Players","",&players,NULL,1,0,3); if (players > worm_count) { worm_count = players; } if (players > 2) { use_remote = true; } - } - break; - case BUTTON_DOWN: + return ret; +} + +/* +Sets the size of each argh block created +*/ +bool set_worm_argh_size(void) +{ + return rb->set_int("Size Of ARGHs","",&argh_size,NULL,1,0,7); +} + +/* +Sets the amount a worm grows per food +*/ +bool set_worm_food(void) +{ + return rb->set_int("Score Per Food","",&worm_food,NULL,1,0,50); +} + +/* +Sets the number of arghs created per food +*/ +bool set_argh_per_food(void) +{ + return rb->set_int("ARGHs Per Food","",&argh_per_food,NULL,1,0,5); +} + +/* +Sets the number of ticks per move +*/ +bool set_worm_speed(void) +{ + bool ret; + + speed = 20 - speed; + ret = rb->set_int("Speed Of Worm","",&speed,NULL,1,1,10); + speed = 20 - speed; + return ret; +} + +/* +Sets the control style, which depends on the number of players, +remote control existing, etc +bool set_bool_options(char* string, bool* variable, + char* yes_str, char* no_str, void (*function)(bool)) +*/ +bool set_worm_control_style(void) +{ + if (players > 1) { + rb->set_bool_options("Control Styles", &use_remote, "Remote Control", + "No Rem. Control", NULL); + } else { if (players > 0) { - players --; - } - break; - case BUTTON_LEFT: - if (worm_count > 1) { - worm_count--; - if (worm_count < players) { - players = worm_count; + rb->set_bool_options("Control Styles", &use_remote, "2 Key Control", + "4 Key Control", NULL); } + else { + rb->set_bool_options("Control Styles", &use_remote, "Out Of Control!", + "Out Of Control!", NULL); } - break; - case BUTTON_RIGHT: - if (worm_count < MAX_WORMS) { - worm_count ++; } - break; - case BUTTON_F1: - use_remote = !use_remote; - if (players > 2) { - use_remote = true; + return false; +} + +/* +Loads the settings (speed, argh per food, argh size, worm food, highscore) +from the file /.rockbox/worm_settings +*/ +bool load_settings(void) +{ + int fd; + int len; + + len = sizeof(int); + fd = rb->open("/.rockbox/worm_settings",O_RDONLY); + if (fd < 0) { + return false; } - break; + /* read in the variables */ + rb->read(fd,&speed,len); + rb->read(fd,&argh_per_food,len); + rb->read(fd,&argh_size,len); + rb->read(fd,&worm_food,len); + rb->read(fd,&highscore,len); + + rb->close(fd); + return false; +} + +/* +Saves the settings (speed, argh per food, argh size, worm food, highscore) +to the file /.rockbox/worm_settings +*/ +bool save_settings(void) +{ + int fd; + int len; - case SYS_USB_CONNECTED: - rb->usb_screen(); - return PLUGIN_USB_CONNECTED; + len = sizeof(int); + fd = rb->open("/.rockbox/worm_settings",O_WRONLY|O_CREAT); + if (fd < 0) { + return false; } - } while (button != BUTTON_PLAY && - button != BUTTON_OFF && button != BUTTON_ON); + /* Always start with a clean file */ + rb->ftruncate(fd,0); + + /* write out the variables */ + rb->write(fd,&speed,len); + rb->write(fd,&argh_per_food,len); + rb->write(fd,&argh_size,len); + rb->write(fd,&worm_food,len); + rb->write(fd,&highscore,len); + + rb->close(fd); + return false; +} + +/* +Launches the wormlet game +*/ +bool launch_wormlet(void) +{ + bool worm_dead = false; + int button; rb->lcd_clear_display(); - /* end of setup */ do { @@ -2002,6 +2072,56 @@ } } while (button != BUTTON_OFF); + + /* save the settings */ + save_settings(); + + rb->lcd_setfont(FONT_UI); + + return false; +} + +/* End of settings/changes etc */ + +/** + * Main entry point + */ +enum plugin_status plugin_start(struct plugin_api* api, void* parameter) +{ + int m; + bool result; + + TEST_PLUGIN_API(api); + (void)(parameter); + + rb = api; + rb->lcd_setfont(FONT_SYSFIXED); + +#ifdef DEBUG_WORMLET + testline_in_rect(); + test_worm_argh_collision_in_moves(); + test_make_argh(); + test_worm_food_collision(); + test_worm_argh_collision(); + test_specific_worm_collision(); +#endif + + /* Setup screen */ + + struct menu_items items[] = { + { "Number Of Worms", set_worm_num_worms }, + { "Number Of Players", set_worm_num_players }, + { "Score Per Food", set_worm_food }, + { "Speed Of Worm", set_worm_speed }, + { "ARGHs Per Food", set_argh_per_food }, + { "Size Of ARGHs", set_worm_argh_size }, + { "Control Styles", set_worm_control_style }, + { "Play Wormlet!", launch_wormlet }, + }; + + m=rb->menu_init( items, sizeof items / sizeof(struct menu_items) ); + result = rb->menu_run(m); + rb->menu_exit(m); return PLUGIN_OK; }