/*************************************************************************** * __________ __ ___. * Open \______ \ ____ ____ | | _\_ |__ _______ ___ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ * \/ \/ \/ \/ \/ * $Id$ * * Copyright (C) 2006 Will Robertson * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * ****************************************************************************/ #include "plugin.h" #include "lib/playback_control.h" PLUGIN_HEADER extern const fb_data superdom_boarditems[]; char buf[255]; #define COLOUR_DARK 0 #define COLOUR_LIGHT 1 #define MARGIN 5 #if LCD_WIDTH > LCD_HEIGHT #define BOX_WIDTH ((LCD_WIDTH-(MARGIN*2))/10) #define BOX_HEIGHT ((BOX_WIDTH*2)/3) #else #define BOX_HEIGHT ((LCD_HEIGHT-(MARGIN*2)-15)/10) #define BOX_WIDTH ((BOX_HEIGHT*2)/3) #endif #if LCD_WIDTH == 220 && LCD_HEIGHT == 176 #define NUM_BOX_HEIGHT 25 #define NUM_BOX_WIDTH 30 #define STRIDE 14 #define ICON_HEIGHT 7 #define ICON_WIDTH 7 #elif (LCD_WIDTH == 160 && LCD_HEIGHT == 128) || \ (LCD_WIDTH == 176 && LCD_HEIGHT == 132) || \ (LCD_WIDTH == 176 && LCD_HEIGHT == 220) #define NUM_BOX_HEIGHT 20 #define NUM_BOX_WIDTH 24 #define STRIDE 8 #define ICON_HEIGHT 4 #define ICON_WIDTH 4 #elif (LCD_WIDTH == 320 && LCD_HEIGHT == 240) #define NUM_BOX_HEIGHT 25 #define NUM_BOX_WIDTH 30 #define STRIDE 20 #define ICON_HEIGHT 10 #define ICON_WIDTH 10 #elif (LCD_WIDTH == 240 && LCD_HEIGHT == 320) #define NUM_BOX_HEIGHT 25 #define NUM_BOX_WIDTH 30 #define STRIDE 18 #define ICON_HEIGHT 9 #define ICON_WIDTH 9 #endif #define NUM_MARGIN_X (LCD_WIDTH-3*NUM_BOX_WIDTH)/2 #define NUM_MARGIN_Y (LCD_HEIGHT-4*NUM_BOX_HEIGHT)/2 #if (CONFIG_KEYPAD == IPOD_4G_PAD) || (CONFIG_KEYPAD == IPOD_3G_PAD) || \ (CONFIG_KEYPAD == IPOD_1G2G_PAD) #define SUPERDOM_OK BUTTON_SELECT #define SUPERDOM_CANCEL BUTTON_MENU #define SUPERDOM_LEFT BUTTON_LEFT #define SUPERDOM_RIGHT BUTTON_RIGHT #define IPOD_STYLE #elif CONFIG_KEYPAD == IRIVER_H300_PAD || CONFIG_KEYPAD == IRIVER_H100_PAD #define SUPERDOM_OK BUTTON_SELECT #define SUPERDOM_LEFT BUTTON_LEFT #define SUPERDOM_RIGHT BUTTON_RIGHT #define SUPERDOM_UP BUTTON_UP #define SUPERDOM_DOWN BUTTON_DOWN #define SUPERDOM_CANCEL BUTTON_OFF #elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD #define SUPERDOM_OK BUTTON_SELECT #define SUPERDOM_LEFT BUTTON_LEFT #define SUPERDOM_RIGHT BUTTON_RIGHT #define SUPERDOM_UP BUTTON_UP #define SUPERDOM_DOWN BUTTON_DOWN #define SUPERDOM_CANCEL BUTTON_REC #elif CONFIG_KEYPAD == IRIVER_H10_PAD #define SUPERDOM_OK BUTTON_RIGHT #define SUPERDOM_UP BUTTON_SCROLL_UP #define SUPERDOM_DOWN BUTTON_SCROLL_DOWN #define SUPERDOM_CANCEL BUTTON_LEFT #elif CONFIG_KEYPAD == GIGABEAT_PAD #define SUPERDOM_OK BUTTON_SELECT #define SUPERDOM_UP BUTTON_UP #define SUPERDOM_DOWN BUTTON_DOWN #define SUPERDOM_LEFT BUTTON_LEFT #define SUPERDOM_RIGHT BUTTON_RIGHT #define SUPERDOM_CANCEL BUTTON_POWER #elif CONFIG_KEYPAD == SANSA_E200_PAD || \ CONFIG_KEYPAD == SANSA_FUZE_PAD #define SUPERDOM_OK BUTTON_SELECT #define SUPERDOM_UP BUTTON_SCROLL_BACK #define SUPERDOM_DOWN BUTTON_SCROLL_FWD #define SUPERDOM_LEFT BUTTON_LEFT #define SUPERDOM_RIGHT BUTTON_RIGHT #define SUPERDOM_CANCEL BUTTON_POWER #elif CONFIG_KEYPAD == GIGABEAT_S_PAD #define SUPERDOM_OK BUTTON_SELECT #define SUPERDOM_UP BUTTON_UP #define SUPERDOM_DOWN BUTTON_DOWN #define SUPERDOM_LEFT BUTTON_LEFT #define SUPERDOM_RIGHT BUTTON_RIGHT #define SUPERDOM_CANCEL BUTTON_BACK #elif CONFIG_KEYPAD == COWOND2_PAD #define SUPERDOM_CANCEL BUTTON_POWER #elif CONFIG_KEYPAD == CREATIVEZVM_PAD #define SUPERDOM_OK BUTTON_SELECT #define SUPERDOM_UP BUTTON_UP #define SUPERDOM_DOWN BUTTON_DOWN #define SUPERDOM_LEFT BUTTON_LEFT #define SUPERDOM_RIGHT BUTTON_RIGHT #define SUPERDOM_CANCEL BUTTON_BACK #endif #ifdef HAVE_TOUCHSCREEN #ifndef SUPERDOM_OK #define SUPERDOM_OK BUTTON_CENTER #endif #ifndef SUPERDOM_UP #define SUPERDOM_UP BUTTON_TOPMIDDLE #endif #ifndef SUPERDOM_LEFT #define SUPERDOM_LEFT BUTTON_MIDLEFT #endif #ifndef SUPERDOM_RIGHT #define SUPERDOM_RIGHT BUTTON_MIDRIGHT #endif #ifndef SUPERDOM_DOWN #define SUPERDOM_DOWN BUTTON_BOTTOMMIDDLE #endif #ifndef SUPERDOM_CANCEL #define SUPERDOM_CANCEL BUTTON_TOPLEFT #endif #endif #define SUPERDOM_QUIT 23 void gen_interest(void); int production_menu(void); void init_resources(void); int select_square(void); void update_score(void); void gen_resources(void); void draw_cursor(void); int calc_strength(bool colour, int x, int y); void draw_board(void); struct tile{ signed int colour; /* -1 = Unset */ bool tank; bool plane; bool nuke; bool ind; bool farm; int men; }; struct resources { int cash; int food; int farms; int inds; int men; int tanks; int planes; int nukes; int bank; int moves; }; struct settings { int compstartfarms; int compstartinds; int humanstartfarms; int humanstartinds; int startcash; int startfood; int movesperturn; } superdom_settings; struct resources humanres; struct resources compres; struct cursor{ int x; int y; } cursor; struct tile board[12][12]; void init_board(void) { rb->srand(*rb->current_tick); int i,j; for(i=0;i<12;i++) { /* Hopefully about 50% each colour */ for(j=0;j<12;j++) { if((i<1)||(j<1)||(i>10)||(j>10)) board[i][j].colour = -1; /* Unset */ else board[i][j].colour = rb->rand()%2; board[i][j].tank = false; board[i][j].plane = false; board[i][j].nuke = false; board[i][j].ind = false; board[i][j].farm = false; board[i][j].men = 0; } } while(compres.farms < superdom_settings.compstartfarms) { i = rb->rand()%10 + 1; j = rb->rand()%10 + 1; if((board[i][j].colour == COLOUR_DARK) && (board[i][j].farm == false)) { board[i][j].farm = true; compres.farms++; break; } } while(compres.inds < superdom_settings.compstartinds) { i = rb->rand()%10 + 1; j = rb->rand()%10 + 1; if((board[i][j].colour == COLOUR_DARK) && (board[i][j].ind == false)) { board[i][j].ind = true; compres.inds++; break; } } while(humanres.farmsrand()%10 + 1; j = rb->rand()%10 + 1; if((board[i][j].colour == COLOUR_LIGHT)&&(board[i][j].farm == false)) { board[i][j].farm = true; humanres.farms++; } } while(humanres.indsrand()%10 + 1; j = rb->rand()%10 + 1; if((board[i][j].colour == COLOUR_LIGHT) && (board[i][j].ind == false)) { board[i][j].ind = true; humanres.inds++; } } } void draw_board(void) { rb->lcd_clear_display(); int i,j; for(i=1;i<11;i++) { for(j=1;j<11;j++) { if(board[i][j].colour == COLOUR_DARK) { rb->lcd_set_foreground(LCD_DARKGRAY); } else { rb->lcd_set_foreground(LCD_LIGHTGRAY); } rb->lcd_fillrect(MARGIN+(BOX_WIDTH*(i-1)), MARGIN+(BOX_HEIGHT*(j-1)), BOX_WIDTH, BOX_HEIGHT); #if LCD_DEPTH != 16 rb->lcd_set_drawmode(DRMODE_BG | DRMODE_INVERSEVID); #endif if(board[i][j].ind) { #if (LCD_DEPTH == 16) rb->lcd_bitmap_transparent_part(superdom_boarditems, #else rb->lcd_mono_bitmap_part(superdom_boarditems, #endif board[i][j].colour?ICON_WIDTH:0, 0, STRIDE, #if LCD_WIDTH > LCD_HEIGHT MARGIN+(BOX_WIDTH*(i-1))+1, MARGIN+(BOX_HEIGHT*(j-1))+ICON_HEIGHT+1, #else MARGIN+(BOX_WIDTH*(i-1))+1+ICON_WIDTH, MARGIN+(BOX_HEIGHT*(j-1))+1, #endif ICON_WIDTH, ICON_HEIGHT); } if(board[i][j].farm) { #if (LCD_DEPTH == 16) rb->lcd_bitmap_transparent_part(superdom_boarditems, #else rb->lcd_mono_bitmap_part(superdom_boarditems, #endif board[i][j].colour?ICON_WIDTH:0, ICON_HEIGHT, STRIDE, MARGIN+(BOX_WIDTH*(i-1))+1, MARGIN+(BOX_HEIGHT*(j-1))+1, ICON_WIDTH, ICON_HEIGHT); } if(board[i][j].tank) { #if (LCD_DEPTH == 16) rb->lcd_bitmap_transparent_part(superdom_boarditems, #else rb->lcd_mono_bitmap_part(superdom_boarditems, #endif board[i][j].colour?ICON_WIDTH:0, ICON_HEIGHT*2, STRIDE, MARGIN+(BOX_WIDTH*(i-1))+ICON_WIDTH+1, MARGIN+(BOX_HEIGHT*(j-1))+ICON_HEIGHT+1, ICON_WIDTH, ICON_HEIGHT); } if(board[i][j].men) { #if (LCD_DEPTH == 16) rb->lcd_bitmap_transparent_part(superdom_boarditems, #else rb->lcd_mono_bitmap_part(superdom_boarditems, #endif board[i][j].colour?ICON_WIDTH:0, ICON_HEIGHT*3, #if LCD_WIDTH > LCD_HEIGHT STRIDE, MARGIN+(BOX_WIDTH*(i-1))+ICON_WIDTH+1, MARGIN+(BOX_HEIGHT*(j-1))+1, #else STRIDE, MARGIN+(BOX_WIDTH*(i-1))+1, MARGIN+(BOX_HEIGHT*(j-1))+1+ICON_HEIGHT, #endif ICON_WIDTH, ICON_HEIGHT); } if(board[i][j].plane) { #if (LCD_DEPTH == 16) rb->lcd_bitmap_transparent_part(superdom_boarditems, #else rb->lcd_mono_bitmap_part(superdom_boarditems, #endif board[i][j].colour?ICON_WIDTH:0, ICON_HEIGHT*4, #if LCD_WIDTH > LCD_HEIGHT STRIDE,MARGIN+(BOX_WIDTH*(i-1))+ICON_WIDTH*2+1, MARGIN+(BOX_HEIGHT*(j-1))+ICON_HEIGHT+1, #else STRIDE,MARGIN+(BOX_WIDTH*(i-1))+ICON_WIDTH+1, MARGIN+(BOX_HEIGHT*(j-1))+ICON_HEIGHT*2+1, #endif ICON_WIDTH, ICON_HEIGHT); } if(board[i][j].nuke) { #if (LCD_DEPTH == 16) rb->lcd_bitmap_transparent_part(superdom_boarditems, #else rb->lcd_mono_bitmap_part(superdom_boarditems, #endif board[i][j].colour?ICON_WIDTH:0, ICON_HEIGHT*5, #if LCD_WIDTH > LCD_HEIGHT STRIDE,MARGIN+(BOX_WIDTH*(i-1))+ICON_WIDTH*2+1, MARGIN+(BOX_HEIGHT*(j-1))+1, #else STRIDE,MARGIN+(BOX_WIDTH*(i-1))+1, MARGIN+(BOX_HEIGHT*(j-1))+ICON_HEIGHT*2+1, #endif ICON_WIDTH, ICON_HEIGHT); } #if LCD_DEPTH != 16 rb->lcd_set_drawmode(DRMODE_SOLID); #endif } } rb->lcd_set_foreground(LCD_BLACK); for(i=0;i<=10;i++) { /* Draw Horizontal lines */ rb->lcd_hline(MARGIN, MARGIN+(BOX_WIDTH*10), MARGIN+(BOX_HEIGHT*i)); } for(i=0;i<=10;i++) { /* Draw Vertical lines */ rb->lcd_vline(MARGIN+(BOX_WIDTH*i), MARGIN, MARGIN+(BOX_HEIGHT*10)); } rb->lcd_update(); } int calc_strength(bool colour, int x, int y) { int a, b, score=0; for (a = -1; a < 2; a++){ for (b = -1; b < 2; b++){ if (b == 0){ if(board[x + a][y].colour == colour) score+=10; if(((board[x + a][y].colour == colour) && board[x + a][y].tank) || ((board[x + a][y].colour == colour) && board[x + a][y].farm)) score+=30; if(((board[x + a][y].colour == colour) && board[x + a][y].plane) || ((board[x + a][y].colour == colour) && board[x + a][y].ind)) score+=40; if((board[x + a][y].colour == colour) && board[x + a][y].nuke) score+=20; if((board[x + a][y].colour == colour) && board[x + a][y].men) score+=(board[x + a][y].men*133/1000); } else if (a == 0){ if(board[x][y + b].colour == colour) score+=10; if(((board[x][y + b].colour == colour) && board[x][y + b].tank) || ((board[x][y + b].colour == colour) && board[x][y + b].farm)) score+=30; if(((board[x][y + b].colour == colour) && board[x][y + b].plane) || ((board[x][y + b].colour == colour) && board[x][y + b].ind)) score+=40; if((board[x][y + b].colour == colour) && board[x][y + b].nuke) score+=20; if((board[x][y + b].colour == colour) && board[x][y + b].men) score+=(board[x][y + b].men*133/1000); } } } return score; } void gen_interest(void) { /* Interest should be around 10% */ rb->srand(*rb->current_tick); int interest = 7+rb->rand()%6; humanres.bank = humanres.bank+(interest*humanres.bank/100); } void draw_cursor(void) { rb->lcd_set_drawmode(DRMODE_COMPLEMENT); rb->lcd_fillrect(MARGIN+((cursor.x-1)*BOX_WIDTH), MARGIN+((cursor.y-1)*BOX_HEIGHT), BOX_WIDTH+1, BOX_HEIGHT+1); rb->lcd_set_drawmode(DRMODE_SOLID); rb->lcd_update(); } void gen_resources(void) { gen_interest(); int inccash = 0; int incfood = 0; int i; rb->srand(*rb->current_tick); /* Generate Human's resources */ for(i=0;irand()%200); } for(i=0;irand()%200); } if(inccash/humanres.inds > 450) { if(incfood/humanres.farms > 350) { rb->splash(HZ*2, "Patriotism sweeps the land, all production" " is up this year!"); } else { rb->splash(HZ*2, "Factories working at maximum efficiency," " cash production up this year!"); } } else if((inccash/humanres.inds>350)&&(inccash/humanres.inds<=450)) { if(incfood/humanres.farms > 350) { rb->splash(HZ*2, "Record crop harvest this year!"); } else if((incfood/humanres.farms > 250) && (incfood/humanres.farms <= 350)) { rb->splash(HZ*2, "Production continues as normal"); } else { rb->splash(HZ*2, "Spoilage of crops leads to reduced farm" " output this year"); } } else { if(incfood/humanres.farms > 350) { rb->splash(HZ*2, "Record crop harvest this year!"); } else if((incfood/humanres.farms > 250) && (incfood/humanres.farms <= 350)) { rb->splash(HZ*2, "Factory unions introduced. Industrial" " production is down this year."); } else { rb->splash(HZ*2, "Internet created. All production is down" " due to time wasted."); } } humanres.cash += inccash; humanres.food += incfood; /* Generate Computer's resources */ inccash = 0; incfood = 0; for(i=0;irand()%200); } for(i=0;irand()%200); } compres.cash += inccash; compres.food += incfood; } void update_score(void) { rb->lcd_set_drawmode(DRMODE_BG|DRMODE_INVERSEVID); rb->lcd_fillrect(5,LCD_HEIGHT-20,105,20); rb->lcd_set_drawmode(DRMODE_SOLID); rb->snprintf(buf, sizeof(buf), "Your power: %d.%d", calc_strength(COLOUR_LIGHT, cursor.x, cursor.y)/10, calc_strength(COLOUR_LIGHT, cursor.x, cursor.y)%10); rb->lcd_putsxy(5,LCD_HEIGHT-20, buf); rb->snprintf(buf, sizeof(buf), "Comp power: %d.%d", calc_strength(COLOUR_DARK, cursor.x, cursor.y)/10, calc_strength(COLOUR_DARK, cursor.x, cursor.y)%10); rb->lcd_putsxy(5,LCD_HEIGHT-10, buf); } int settings_menu_function(void) { int selection = 0; MENUITEM_STRINGLIST(settings_menu,"Super Domination Settings",NULL, "Computer starting farms","Computer starting factories", "Human starting farms","Human starting factories", "Starting cash","Starting food","Moves per turn"); settings_menu: selection=rb->do_menu(&settings_menu,&selection, NULL, false); switch(selection) { case 0: rb->set_int("Computer starting farms", "", UNIT_INT, &superdom_settings.compstartfarms, NULL, 1, 0, 5, NULL); goto settings_menu; break; case 1: rb->set_int("Computer starting factories", "", UNIT_INT, &superdom_settings.compstartinds, NULL, 1, 0, 5, NULL); goto settings_menu; break; case 2: rb->set_int("Human starting farms", "", UNIT_INT, &superdom_settings.humanstartfarms, NULL, 1, 0, 5, NULL); goto settings_menu; break; case 3: superdom_settings.humanstartinds = rb->set_int("Human starting factories", "", UNIT_INT, &superdom_settings.humanstartinds, NULL, 1, 0, 5, NULL); goto settings_menu; break; case 4: rb->set_int("Starting cash", "", UNIT_INT, &superdom_settings.startcash, NULL, 250, 0, 5000, NULL); goto settings_menu; break; case 5: rb->set_int("Starting food", "", UNIT_INT, &superdom_settings.startfood, NULL, 250, 0, 5000, NULL); goto settings_menu; break; case 6: rb->set_int("Moves per turn", "", UNIT_INT, &superdom_settings.movesperturn, NULL, 1, 1, 5, NULL); goto settings_menu; break; case MENU_ATTACHED_USB: return PLUGIN_USB_CONNECTED; break; } return 0; } static int do_help(void) { int button; int y = MARGIN, space_w, width, height; unsigned short x = MARGIN, i = 0; #define WORDS (sizeof instructions / sizeof (char*)) static char* instructions[] = { "Super", "domination", "is", "a", "turn", "based", "strategy", "game,", "where", "the", "aim", "is", "to", "overpower", "the", "computer", "player", "by", "taking", "their", "territory.", "", "Each", "year", "you", "are", "allocated", "an", "amount", "of", "cash", "and", "food,", "depending", "on", "how", "many", "farms", "and", "factories", "you", "control.", "", "Use", "this", "cash", "and", "food", "to", "buy", "and", "feed", "your", "army.", "Each", "tile", "has", "a", "strength,", "calculated", "by", "the", "ownership", "of", "adjacent", "tiles,", "and", "the", "type", "and", "number", "of", "troops", "on", "them.", }; rb->lcd_clear_display(); rb->lcd_getstringsize(" ", &space_w, &height); for (i = 0; i < WORDS; i++) { rb->lcd_getstringsize(instructions[i], &width, NULL); /* Skip to next line if the current one can't fit the word */ if (x + width > LCD_WIDTH - MARGIN) { x = MARGIN; y += height; } /* .. or if the word is the empty string */ if (rb->strcmp(instructions[i], "") == 0) { x = MARGIN; y += height; continue; } /* We filled the screen */ if (y + height > LCD_HEIGHT - MARGIN) { y = MARGIN; rb->lcd_update(); do { button = rb->button_get(true); if (button == SYS_USB_CONNECTED) { return PLUGIN_USB_CONNECTED; } } while( ( button == BUTTON_NONE ) || ( button & (BUTTON_REL|BUTTON_REPEAT) ) ); rb->lcd_clear_display(); } rb->lcd_putsxy(x, y, instructions[i]); x += width + space_w; } rb->lcd_update(); do { button = rb->button_get(true); if (button == SYS_USB_CONNECTED) { return PLUGIN_USB_CONNECTED; } } while( ( button == BUTTON_NONE ) || ( button & (BUTTON_REL|BUTTON_REPEAT) ) ); return 0; } int menu(void) { int selection = 0; MENUITEM_STRINGLIST(main_menu,"Super Domination Menu",NULL, "Play Super Domination","Settings","Help","Quit"); while(1) { selection=rb->do_menu(&main_menu,&selection, NULL, false); switch(selection) { case 0: return 0; /* start playing */ break; case 1: if(settings_menu_function()==PLUGIN_USB_CONNECTED) return PLUGIN_USB_CONNECTED; break; case 2: if(do_help()==PLUGIN_USB_CONNECTED) return PLUGIN_USB_CONNECTED; break; default: return 2; /* quit program */ break; } } return 3; } int save_game(void) { int fd; char savepath[MAX_PATH]; rb->snprintf(savepath, sizeof(savepath), "/Savegame.ssg"); if(rb->kbd_input(savepath, MAX_PATH)) { DEBUGF("Keyboard input failed\n"); return -1; } fd = rb->open(savepath, O_WRONLY|O_CREAT); DEBUGF("savepath: %s\n", savepath); if(fd < 0) { DEBUGF("Couldn't create/open file\n"); return -1; } rb->write(fd, "SSGv2", 5); rb->write(fd, &humanres.cash, sizeof(humanres.cash)); rb->write(fd, &humanres.food, sizeof(humanres.food)); rb->write(fd, &humanres.bank, sizeof(humanres.bank)); rb->write(fd, &humanres.planes, sizeof(humanres.planes)); rb->write(fd, &humanres.tanks, sizeof(humanres.tanks)); rb->write(fd, &humanres.men, sizeof(humanres.men)); rb->write(fd, &humanres.nukes, sizeof(humanres.nukes)); rb->write(fd, &humanres.inds, sizeof(humanres.inds)); rb->write(fd, &humanres.farms, sizeof(humanres.farms)); rb->write(fd, &humanres.moves, sizeof(humanres.moves)); rb->write(fd, &compres.cash, sizeof(compres.cash)); rb->write(fd, &compres.food, sizeof(compres.food)); rb->write(fd, &compres.bank, sizeof(compres.bank)); rb->write(fd, &compres.planes, sizeof(compres.planes)); rb->write(fd, &compres.tanks, sizeof(compres.tanks)); rb->write(fd, &compres.men, sizeof(compres.men)); rb->write(fd, &compres.nukes, sizeof(compres.nukes)); rb->write(fd, &compres.inds, sizeof(compres.inds)); rb->write(fd, &compres.farms, sizeof(compres.farms)); rb->write(fd, &compres.moves, sizeof(compres.moves)); rb->write(fd, board, sizeof(board)); rb->write(fd, &superdom_settings.compstartfarms, sizeof(int)); rb->write(fd, &superdom_settings.compstartinds, sizeof(int)); rb->write(fd, &superdom_settings.humanstartfarms, sizeof(int)); rb->write(fd, &superdom_settings.humanstartfarms, sizeof(int)); rb->write(fd, &superdom_settings.startcash, sizeof(int)); rb->write(fd, &superdom_settings.startfood, sizeof(int)); rb->write(fd, &superdom_settings.movesperturn, sizeof(int)); rb->close(fd); return 0; } int ingame_menu(void) { int selection = 0; MENUITEM_STRINGLIST(ingame_menu,"Super Domination Menu",NULL, "Return to game","Save Game","Playback Control", "Quit"); selection=rb->do_menu(&ingame_menu,&selection, NULL, false); switch(selection) { case 0: return 0; break; case 1: if(!save_game()) rb->splash(HZ, "Game saved"); else rb->splash(HZ, "Error in save"); break; case 2: playback_control(NULL); break; case 3: return SUPERDOM_QUIT; break; case MENU_ATTACHED_USB: return PLUGIN_USB_CONNECTED; break; } return 0; } int get_number(char* param, int* value) { //int numbers[3][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}; int numbers[3][3]; numbers[0][0] = 1; numbers[0][1] = 2; numbers[0][2] = 3; numbers[1][0] = 4; numbers[1][1] = 5; numbers[1][2] = 6; numbers[2][0] = 7; numbers[2][1] = 8; numbers[2][2] = 9; rb->lcd_clear_display(); /* Draw a 3x4 grid */ int i,j,x=0,y=0; for(i=0;i<=3;i++) { /* Vertical lines */ rb->lcd_vline(NUM_MARGIN_X+(NUM_BOX_WIDTH*i), NUM_MARGIN_Y, NUM_MARGIN_Y+(4*NUM_BOX_HEIGHT)); } for(i=0;i<=4;i++) { /* Horizontal lines */ rb->lcd_hline(NUM_MARGIN_X, NUM_MARGIN_X+(3*NUM_BOX_WIDTH), NUM_MARGIN_Y+(NUM_BOX_HEIGHT*i)); } int temp = 1; for(i=0;i<3;i++) { for(j=0;j<3;j++) { rb->snprintf(buf, sizeof(buf), "%d", temp); rb->lcd_putsxy(NUM_MARGIN_X+(j*NUM_BOX_WIDTH)+10, NUM_MARGIN_Y+(i*NUM_BOX_HEIGHT)+8, buf); temp++; } } rb->lcd_putsxy(NUM_MARGIN_X+5, NUM_MARGIN_Y+(3*NUM_BOX_HEIGHT)+8, "CLR"); rb->lcd_putsxy(NUM_MARGIN_X+NUM_BOX_WIDTH+10, NUM_MARGIN_Y+(3*NUM_BOX_HEIGHT)+8, "0"); rb->lcd_putsxy(NUM_MARGIN_X+2*NUM_BOX_WIDTH+8, NUM_MARGIN_Y+(3*NUM_BOX_HEIGHT)+8, "OK"); rb->snprintf(buf,sizeof(buf), "%d", *value); rb->lcd_putsxy(NUM_MARGIN_X+10, NUM_MARGIN_Y+4*NUM_BOX_HEIGHT+10, buf); int height, width; rb->lcd_getstringsize(param, &width, &height); rb->lcd_putsxy((LCD_WIDTH-width)/2, (NUM_MARGIN_Y-height)/2, param); rb->lcd_set_drawmode(DRMODE_COMPLEMENT); rb->lcd_fillrect(NUM_MARGIN_X+(NUM_BOX_WIDTH*x), NUM_MARGIN_Y+(NUM_BOX_HEIGHT*y), NUM_BOX_WIDTH+1, NUM_BOX_HEIGHT+1); rb->lcd_set_drawmode(DRMODE_SOLID); int button = 0; rb->lcd_update(); while(1) { button = rb->button_get(true); switch(button) { case SUPERDOM_OK: *value *= 10; if(y!=3) { *value += numbers[y][x]; } else if(y==3 && x==0) { *value /= 100; } else if(y==3 && x==2) { *value /= 10; return 0; } rb->lcd_set_drawmode(DRMODE_BG|DRMODE_INVERSEVID); rb->lcd_fillrect(0, NUM_MARGIN_Y+4*NUM_BOX_HEIGHT+10, LCD_WIDTH, 30); rb->lcd_set_drawmode(DRMODE_SOLID); rb->snprintf(buf,sizeof(buf), "%d", *value); rb->lcd_putsxy(NUM_MARGIN_X+10, NUM_MARGIN_Y+4*NUM_BOX_HEIGHT+10, buf); break; case SUPERDOM_CANCEL: return 0; break; #if CONFIG_KEYPAD != IRIVER_H10_PAD case SUPERDOM_LEFT: rb->lcd_set_drawmode(DRMODE_COMPLEMENT); rb->lcd_fillrect(NUM_MARGIN_X+(NUM_BOX_WIDTH*x), NUM_MARGIN_Y+(NUM_BOX_HEIGHT*y), NUM_BOX_WIDTH+1, NUM_BOX_HEIGHT+1); rb->lcd_set_drawmode(DRMODE_SOLID); if(x==0) { #ifdef IPOD_STYLE if(y>0) y--; else y=3; #endif x=2; } else { x--; } rb->lcd_set_drawmode(DRMODE_COMPLEMENT); rb->lcd_fillrect(NUM_MARGIN_X+(NUM_BOX_WIDTH*x), NUM_MARGIN_Y+(NUM_BOX_HEIGHT*y), NUM_BOX_WIDTH+1, NUM_BOX_HEIGHT+1); rb->lcd_set_drawmode(DRMODE_SOLID); break; case SUPERDOM_RIGHT: rb->lcd_set_drawmode(DRMODE_COMPLEMENT); rb->lcd_fillrect(NUM_MARGIN_X+(NUM_BOX_WIDTH*x), NUM_MARGIN_Y+(NUM_BOX_HEIGHT*y), NUM_BOX_WIDTH+1, NUM_BOX_HEIGHT+1); rb->lcd_set_drawmode(DRMODE_SOLID); if(x==2) { #ifdef IPOD_STYLE if(y==3) y=0; else y++; #endif x=0; } else { x++; } rb->lcd_set_drawmode(DRMODE_COMPLEMENT); rb->lcd_fillrect(NUM_MARGIN_X+(NUM_BOX_WIDTH*x), NUM_MARGIN_Y+(NUM_BOX_HEIGHT*y), NUM_BOX_WIDTH+1, NUM_BOX_HEIGHT+1); rb->lcd_set_drawmode(DRMODE_SOLID); break; #endif #ifndef IPOD_STYLE case SUPERDOM_UP: rb->lcd_set_drawmode(DRMODE_COMPLEMENT); rb->lcd_fillrect(NUM_MARGIN_X+(NUM_BOX_WIDTH*x), NUM_MARGIN_Y+(NUM_BOX_HEIGHT*y), NUM_BOX_WIDTH+1, NUM_BOX_HEIGHT+1); rb->lcd_set_drawmode(DRMODE_SOLID); if(y==0) { #if CONFIG_KEYPAD == IRIVER_H10_PAD if(x > 0) x--; else x=2; #endif y=3; } else { y--; } rb->lcd_set_drawmode(DRMODE_COMPLEMENT); rb->lcd_fillrect(NUM_MARGIN_X+(NUM_BOX_WIDTH*x), NUM_MARGIN_Y+(NUM_BOX_HEIGHT*y), NUM_BOX_WIDTH+1, NUM_BOX_HEIGHT+1); rb->lcd_set_drawmode(DRMODE_SOLID); break; case SUPERDOM_DOWN: rb->lcd_set_drawmode(DRMODE_COMPLEMENT); rb->lcd_fillrect(NUM_MARGIN_X+(NUM_BOX_WIDTH*x), NUM_MARGIN_Y+(NUM_BOX_HEIGHT*y), NUM_BOX_WIDTH+1, NUM_BOX_HEIGHT+1); rb->lcd_set_drawmode(DRMODE_SOLID); if(y==3) { #if CONFIG_KEYPAD == IRIVER_H10_PAD if(x < 2) x++; else x=0; #endif y=0; } else { y++; } rb->lcd_set_drawmode(DRMODE_COMPLEMENT); rb->lcd_fillrect(NUM_MARGIN_X+(NUM_BOX_WIDTH*x), NUM_MARGIN_Y+(NUM_BOX_HEIGHT*y), NUM_BOX_WIDTH+1, NUM_BOX_HEIGHT+1); rb->lcd_set_drawmode(DRMODE_SOLID); break; #endif default: if (rb->default_event_handler(button) == SYS_USB_CONNECTED) { return PLUGIN_USB_CONNECTED; } break; } rb->lcd_update(); } return 0; } int buy_resources_menu(void) { int selection,tempmenu,nummen; MENUITEM_STRINGLIST(res_menu, "Buy Resources", NULL, "Buy men ($1)", "Buy tank ($300)", "Buy plane ($600)", "Buy Farm ($1150)", "Buy Factory ($1300)", "Buy Nuke ($2000)", "Finish buying", "Game menu"); resources_menu: selection=rb->do_menu(&res_menu,&selection, NULL, false); switch(selection) { case 0: nummen = 0; if(get_number("How many men would you like?", &nummen) == PLUGIN_USB_CONNECTED) return PLUGIN_USB_CONNECTED; if(humanres.cash>=nummen) { rb->splash(HZ, "Where do you want to place them?"); tempmenu = select_square(); switch(tempmenu) { case 0: rb->splash(HZ, "Cancelled"); break; case 2: if(board[cursor.x][cursor.y].colour == COLOUR_LIGHT) { humanres.men += nummen; board[cursor.x][cursor.y].men += nummen; humanres.cash -= nummen; } else { rb->splash(HZ,"Can't place men on enemy territory"); } break; case PLUGIN_USB_CONNECTED: return PLUGIN_USB_CONNECTED; break; } } else { rb->splash(HZ, "Not enough money!"); } goto resources_menu; break; case 1: if(humanres.cash>=300) { rb->splash(HZ, "Where do you want to place the tank?"); tempmenu = select_square(); switch(tempmenu) { case 0: rb->splash(HZ, "Cancelled"); goto resources_menu; break; case PLUGIN_USB_CONNECTED: return PLUGIN_USB_CONNECTED; break; } if(board[cursor.x][cursor.y].colour == COLOUR_LIGHT) { if(board[cursor.x][cursor.y].tank) { rb->splash(HZ, "There is already a tank there"); } else { board[cursor.x][cursor.y].tank = true; humanres.cash -= 300; humanres.tanks++; } } else { rb->splash(HZ, "Can't place men on enemy territory"); } } else { rb->splash(HZ, "Not enough money!"); } goto resources_menu; break; case 2: if(humanres.cash>=600) { rb->splash(HZ, "Where do you want to place the plane?"); tempmenu = select_square(); switch(tempmenu) { case 0: rb->splash(HZ, "Cancelled"); goto resources_menu; break; case PLUGIN_USB_CONNECTED: return PLUGIN_USB_CONNECTED; break; } if(board[cursor.x][cursor.y].colour == COLOUR_LIGHT) { if(board[cursor.x][cursor.y].plane) { rb->splash(HZ, "There is already a plane there"); } else { board[cursor.x][cursor.y].plane = true; humanres.cash -= 600; humanres.planes++; } } else { rb->splash(HZ, "Can't place men on enemy territory"); } } else { rb->splash(HZ, "Not enough money!"); } goto resources_menu; break; case 3: if(humanres.cash>=1150) { rb->splash(HZ, "Where do you want to place the farm?"); tempmenu = select_square(); switch(tempmenu) { case 0: rb->splash(HZ, "Cancelled"); goto resources_menu; break; case PLUGIN_USB_CONNECTED: return PLUGIN_USB_CONNECTED; break; } if(board[cursor.x][cursor.y].colour == COLOUR_LIGHT) { if(board[cursor.x][cursor.y].farm) { rb->splash(HZ, "There is already a farm there"); } else { board[cursor.x][cursor.y].farm = true; humanres.cash -= 1150; humanres.farms++; } } else { rb->splash(HZ, "Can't build on enemy territory"); } } else { rb->splash(HZ, "Not enough money!"); } goto resources_menu; break; case 4: if(humanres.cash>=1300) { rb->splash(HZ, "Where do you want to place the industrial" " plant?"); tempmenu = select_square(); switch(tempmenu) { case 0: rb->splash(HZ, "Cancelled"); goto resources_menu; break; case PLUGIN_USB_CONNECTED: return PLUGIN_USB_CONNECTED; break; } if(board[cursor.x][cursor.y].colour == COLOUR_LIGHT) { if(board[cursor.x][cursor.y].ind) { rb->splash(HZ, "There is already an industrial" " plant there"); } else { board[cursor.x][cursor.y].ind = true; humanres.cash -= 1300; humanres.inds++; } } else { rb->splash(HZ, "Can't build on enemy territory"); } } else { rb->splash(HZ, "Not enough money!"); } goto resources_menu; break; case 5: if(humanres.cash>=2000) { rb->splash(HZ, "Where do you want to place the nuke?"); tempmenu = select_square(); switch(tempmenu) { case 0: rb->splash(HZ, "Cancelled"); goto resources_menu; break; case PLUGIN_USB_CONNECTED: return PLUGIN_USB_CONNECTED; break; } if(board[cursor.x][cursor.y].colour == COLOUR_LIGHT) { if(board[cursor.x][cursor.y].nuke) { rb->splash(HZ, "There is already a nuke there"); } else { board[cursor.x][cursor.y].nuke = true; humanres.cash -= 2000; humanres.nukes++; } } else { rb->splash(HZ, "Can't place a nuke on enemy territory"); } } else { rb->splash(HZ, "Not enough money!"); } goto resources_menu; break; case 6: return 0; break; case MENU_ATTACHED_USB: return PLUGIN_USB_CONNECTED; break; } return 0; } int move_unit(void) { int selection, nummen; struct cursor from; MENUITEM_STRINGLIST(move_unit_menu, "Move unit", NULL, "Move men", "Move tank", "Move plane"); selection=rb->do_menu(&move_unit_menu,&selection, NULL, false); switch(selection) { case 0: rb->splash(HZ, "Select where to move troops from"); if(select_square() == PLUGIN_USB_CONNECTED) return PLUGIN_USB_CONNECTED; if(board[cursor.x][cursor.y].colour == COLOUR_LIGHT) { if(board[cursor.x][cursor.y].men) { from.x = cursor.x; from.y = cursor.y; nummen = board[from.x][from.y].men; if(get_number("How many men do you want to move?", &nummen) == PLUGIN_USB_CONNECTED) return PLUGIN_USB_CONNECTED; if(nummen > board[from.x][from.y].men) { rb->splash(HZ, "You don't have that many troops."); } else { rb->splash(HZ,"Select where to move the troops to"); if(select_square() == PLUGIN_USB_CONNECTED) return PLUGIN_USB_CONNECTED; if((board[cursor.x][cursor.y].colour == COLOUR_LIGHT) && (abs(cursor.x - from.x) <= 1) && abs(cursor.y - from.y) <= 1) { board[from.x][from.y].men -= nummen; board[cursor.x][cursor.y].men += nummen; humanres.moves--; return 0; } } } else { rb->splash(HZ, "You don't have any troops there"); } } else { rb->splash(HZ, "Can't move enemy troops"); } break; case 1: rb->splash(HZ, "Select where you want to move the tank from"); if(select_square() == PLUGIN_USB_CONNECTED) return PLUGIN_USB_CONNECTED; if(board[cursor.x][cursor.y].colour == COLOUR_LIGHT) { if(board[cursor.x][cursor.y].tank) { from.x = cursor.x; from.y = cursor.y; rb->splash(HZ, "Select where you want" " to move the tank to"); if(select_square() == PLUGIN_USB_CONNECTED) return PLUGIN_USB_CONNECTED; if((board[cursor.x][cursor.y].colour == COLOUR_LIGHT)&& (abs(cursor.x-from.x) <= 1) && (abs(cursor.y-from.y) <= 1)) { if(board[cursor.x][cursor.y].tank) { rb->splash(HZ, "There is already a tank there"); } else { board[from.x][from.y].tank = false; board[cursor.x][cursor.y].tank = true; humanres.moves--; return 0; } } else { rb->splash(HZ, "Invalid move"); } } else { rb->splash(HZ, "You don't have a tank there"); } } else { rb->splash(HZ, "That isn't your territory"); } break; case 2: rb->splash(HZ, "Select where you want" " to move the plane from"); if(select_square() == PLUGIN_USB_CONNECTED) return PLUGIN_USB_CONNECTED; if(board[cursor.x][cursor.y].colour == COLOUR_LIGHT) { if(board[cursor.x][cursor.y].plane) { from.x = cursor.x; from.y = cursor.y; rb->splash(HZ, "Select where you want" " to move the plane to"); if(select_square() == PLUGIN_USB_CONNECTED) return PLUGIN_USB_CONNECTED; if(board[cursor.x][cursor.y].colour == COLOUR_LIGHT) { if(board[cursor.x][cursor.y].plane) { rb->splash(HZ,"There is already a plane there"); } else { board[from.x][from.y].plane = false; board[cursor.x][cursor.y].plane = true; humanres.moves--; return 0; } } else { rb->splash(HZ, "Invalid move"); } } else { rb->splash(HZ, "You don't have a plane there"); } } else { rb->splash(HZ, "That isn't your territory"); } break; } return 0; } int movement_menu(void) { int selection, tempmenu; bool menu_quit = false; MENUITEM_STRINGLIST(move_menu, "Movement", NULL, "Move unit", "Buy additional moves ($100)", "Launch nuclear missile", "Check map", "Finish moving", "Game menu"); while(!menu_quit) { selection=rb->do_menu(&move_menu,&selection, NULL, false); switch(selection) { case 0: if(humanres.moves) { if(move_unit()==PLUGIN_USB_CONNECTED) return PLUGIN_USB_CONNECTED; } else { rb->splash(HZ, "You have no more moves left." " You can buy more for $100 each."); } break; case 1: if(humanres.cash > 100) { humanres.moves++; humanres.cash -= 100; rb->snprintf(buf, sizeof(buf), "You now have %d moves", humanres.moves); rb->splash(HZ, buf); } break; case 2: if(humanres.nukes==0) { rb->splash(HZ, "You do not have any nukes to launch"); } else { rb->splash(HZ, "Select place to launch nuke from"); if(select_square() == PLUGIN_USB_CONNECTED) { return PLUGIN_USB_CONNECTED; } if(board[cursor.x][cursor.y].nuke) { rb->splash(HZ, "Select place to target with nuke"); if(select_square() == PLUGIN_USB_CONNECTED) { return PLUGIN_USB_CONNECTED; } board[cursor.x][cursor.y].men = 0; board[cursor.x][cursor.y].tank = 0; board[cursor.x][cursor.y].plane = 0; board[cursor.x][cursor.y].ind = 0; board[cursor.x][cursor.y].nuke = 0; board[cursor.x][cursor.y].farm = 0; /* TODO: Fallout carried by wind */ } } break; case 3: if(select_square() == PLUGIN_USB_CONNECTED) return PLUGIN_USB_CONNECTED; break; case 4: return 0; break; case 5: tempmenu = ingame_menu(); switch(tempmenu) { case PLUGIN_USB_CONNECTED: return PLUGIN_USB_CONNECTED; break; case SUPERDOM_QUIT: return SUPERDOM_QUIT; break; } break; case MENU_ATTACHED_USB: return PLUGIN_USB_CONNECTED; break; } } return 0; } int show_inventory(void) { rb->lcd_clear_display(); rb->lcd_puts(1, 0, "Inventory"); char men[20], tanks[20], planes[20], inds[20], farms[20], nukes[20], cash[20], food[20], bank[20]; rb->snprintf(men, sizeof(men), "Men: %d", humanres.men); rb->snprintf(tanks, sizeof(tanks), "Tanks: %d", humanres.tanks); rb->snprintf(planes, sizeof(planes), "Planes: %d", humanres.planes); rb->snprintf(inds, sizeof(inds), "Factories: %d", humanres.inds); rb->snprintf(farms, sizeof(farms), "Farms: %d", humanres.farms); rb->snprintf(nukes, sizeof(nukes), "Nukes: %d", humanres.nukes); rb->snprintf(cash, sizeof(cash), "Cash: %d", humanres.cash); rb->snprintf(food, sizeof(food), "Food: %d", humanres.food); rb->snprintf(bank, sizeof(bank), "Bank: %d", humanres.bank); rb->lcd_puts(2, 1, men); rb->lcd_puts(2, 2, tanks); rb->lcd_puts(2, 3, planes); rb->lcd_puts(2, 4, inds); rb->lcd_puts(2, 5, farms); rb->lcd_puts(2, 6, nukes); rb->lcd_puts(2, 7, cash); rb->lcd_puts(2, 8, food); rb->lcd_puts(2, 9, bank); rb->lcd_update(); if(rb->default_event_handler(rb->button_get(true)) == SYS_USB_CONNECTED) { return PLUGIN_USB_CONNECTED; } else { return 0; } } int production_menu(void) { int selection, tempbank, tempmenu; MENUITEM_STRINGLIST(prod_menu, "Production", NULL, "Buy resources", "Show inventory", "Check map", "Invest money", "Withdraw money", "Finish turn", "Game menu"); while(1) { selection=rb->do_menu(&prod_menu,&selection, NULL, false); switch(selection) { case 0: tempmenu = buy_resources_menu(); switch(tempmenu) { case PLUGIN_USB_CONNECTED: return PLUGIN_USB_CONNECTED; break; case SUPERDOM_QUIT: return SUPERDOM_QUIT; break; } break; case 1: tempmenu = show_inventory(); switch(tempmenu) { case 0: break; case PLUGIN_USB_CONNECTED: return PLUGIN_USB_CONNECTED; break; } break; case 2: tempmenu = select_square(); switch(tempmenu) { case PLUGIN_USB_CONNECTED: return PLUGIN_USB_CONNECTED; break; case SUPERDOM_QUIT: return SUPERDOM_QUIT; break; case 0: break; } break; case 3: tempbank = humanres.cash; if(get_number("How much do you want to invest?", &tempbank) == PLUGIN_USB_CONNECTED) return PLUGIN_USB_CONNECTED; if(tempbank>humanres.cash) { rb->splash(HZ, "You don't have that much cash to invest"); } else { humanres.cash -= tempbank; humanres.bank += tempbank; } break; case 4: tempbank = 0; if(get_number("How much do you want to withdraw?", &tempbank) == PLUGIN_USB_CONNECTED) return PLUGIN_USB_CONNECTED; if(tempbank>humanres.bank) { rb->splash(HZ, "You don't have that much cash to withdraw"); } else { humanres.cash += tempbank; humanres.bank -= tempbank; } break; case 5: return 0; break; case 6: tempmenu = ingame_menu(); switch(tempmenu) { case PLUGIN_USB_CONNECTED: return PLUGIN_USB_CONNECTED; break; case SUPERDOM_QUIT: return SUPERDOM_QUIT; break; } break; case MENU_ATTACHED_USB: return PLUGIN_USB_CONNECTED; break; } } return 0; } void init_resources(void) { humanres.cash = superdom_settings.startcash; humanres.food = superdom_settings.startfood; humanres.tanks = 0; humanres.planes = 0; humanres.nukes = 0; humanres.inds = 0; humanres.farms = 0; humanres.men = 0; humanres.bank = 0; humanres.moves = 0; compres.cash = superdom_settings.startcash; compres.food = superdom_settings.startfood; compres.tanks = 0; compres.planes = 0; compres.nukes = 0; compres.inds = 0; compres.farms = 0; compres.men = 0; compres.bank = 0; compres.moves = 0; } int select_square(void) { draw_board(); draw_cursor(); update_score(); #if LCD_WIDTH >= 220 rb->snprintf(buf, sizeof(buf), "Cash: %d", humanres.cash); rb->lcd_putsxy(125, LCD_HEIGHT-20, buf); rb->snprintf(buf, sizeof(buf), "Food: %d", humanres.food); rb->lcd_putsxy(125, LCD_HEIGHT-10, buf); #endif rb->lcd_update(); int button = 0; while(1) { button = rb->button_get(true); switch(button) { case SUPERDOM_CANCEL: return 0; break; case SUPERDOM_OK: return 2; break; #if CONFIG_KEYPAD != IRIVER_H10_PAD case SUPERDOM_LEFT: case (SUPERDOM_LEFT|BUTTON_REPEAT): draw_cursor(); /* Deselect the current tile */ if(cursor.x>1) { cursor.x--; } else { #ifdef IPOD_STYLE if(cursor.y>1) cursor.y--; else cursor.y = 10; #endif cursor.x = 10; } update_score(); draw_cursor(); break; case SUPERDOM_RIGHT: case (SUPERDOM_RIGHT|BUTTON_REPEAT): draw_cursor(); /* Deselect the current tile */ if(cursor.x<10) { cursor.x++; } else { #ifdef IPOD_STYLE if(cursor.y<10) cursor.y++; else cursor.y = 1; #endif cursor.x = 1; } update_score(); draw_cursor(); break; #endif #ifndef IPOD_STYLE case SUPERDOM_UP: case (SUPERDOM_UP|BUTTON_REPEAT): draw_cursor(); /* Deselect the current tile */ if(cursor.y>1) { cursor.y--; } else { #if CONFIG_KEYPAD == IRIVER_H10_PAD if(cursor.x > 1) cursor.x--; else cursor.x = 10; #endif cursor.y = 10; } update_score(); draw_cursor(); break; case SUPERDOM_DOWN: case (SUPERDOM_DOWN|BUTTON_REPEAT): draw_cursor(); /* Deselect the current tile */ if(cursor.y<10) { cursor.y++; } else { #if CONFIG_KEYPAD == IRIVER_H10_PAD if(cursor.x < 10) cursor.x++; else cursor.x = 1; #endif cursor.y = 1; } update_score(); draw_cursor(); break; #endif default: if (rb->default_event_handler(button) == SYS_USB_CONNECTED) { return PLUGIN_USB_CONNECTED; } } } } int killmen(bool human) { int menkilled,i,j; int percent; if(human) { percent = (humanres.food*1000)/humanres.men; humanres.food = 0; } else { percent = (compres.food*1000)/compres.men; compres.food = 0; } menkilled = 0; for(i=1;i<12;i++) { for(j=1;j<12;j++) { if(board[i][j].colour == human) { menkilled += ((board[i][j].men * percent)/1000); board[i][j].men = (board[i][j].men * percent)/1000; } } } if(human) humanres.men -= menkilled; else compres.men -= menkilled; return menkilled; } int war_menu(void) { int selection, tempmenu; MENUITEM_STRINGLIST(wartime_menu, "War!", NULL, "Select territory to attack", "Finish turn", "Game menu"); humanres.moves = superdom_settings.movesperturn; while(humanres.moves) { selection=rb->do_menu(&wartime_menu,&selection, NULL, false); switch(selection) { case 0: if(select_square() == PLUGIN_USB_CONNECTED) return PLUGIN_USB_CONNECTED; if(board[cursor.x][cursor.y].colour == COLOUR_DARK) { if(calc_strength(COLOUR_LIGHT, cursor.x, cursor.y) > calc_strength(COLOUR_DARK, cursor.x, cursor.y)) { board[cursor.x][cursor.y].colour = COLOUR_LIGHT; board[cursor.x][cursor.y].tank = 0; board[cursor.x][cursor.y].men = 0; board[cursor.x][cursor.y].plane = 0; board[cursor.x][cursor.y].nuke = 0; draw_board(); rb->sleep(HZ*2); humanres.moves--; } else if(calc_strength(COLOUR_LIGHT, cursor.x, cursor.y)== calc_strength(COLOUR_DARK, cursor.x, cursor.y)) { if(rb->rand()%2) { board[cursor.x][cursor.y].colour = COLOUR_LIGHT; board[cursor.x][cursor.y].tank = 0; board[cursor.x][cursor.y].men = 0; board[cursor.x][cursor.y].plane = 0; board[cursor.x][cursor.y].nuke = 0; draw_board(); rb->sleep(HZ*2); humanres.moves--; } else { rb->splash(HZ, "Your troops were unable to" " overcome the enemy troops"); humanres.moves--; } } else { rb->splash(HZ, "Your troops were unable to overcome" " the enemy troops"); humanres.moves--; } } else { rb->splash(HZ, "You can't attack your own territory"); } break; case 1: return 0; break; case 2: tempmenu = ingame_menu(); switch(tempmenu) { case PLUGIN_USB_CONNECTED: return PLUGIN_USB_CONNECTED; break; case SUPERDOM_QUIT: return SUPERDOM_QUIT; break; } break; } } return 0; } struct threat { int x; int y; int str_diff; }; bool place_adjacent(bool tank, int x, int y) { if(tank) { if(!board[x-1][y].tank && (board[x][y].colour==board[x-1][y].colour)) { compres.cash -= 300; board[x-1][y].tank = true; compres.tanks++; return 0; } if(!board[x+1][y].tank && (board[x][y].colour==board[x+1][y].colour)) { compres.cash -= 300; board[x+1][y].tank = true; compres.tanks++; return 0; } if(!board[x][y-1].tank && (board[x][y].colour==board[x][y-1].colour)) { compres.cash -= 300; board[x][y-1].tank = true; compres.tanks++; return 0; } if(!board[x][y+1].tank && (board[x][y].colour==board[x][y+1].colour)) { compres.cash -= 300; board[x][y+1].tank = true; compres.tanks++; return 0; } } else { if(!board[x-1][y].plane && (board[x][y].colour==board[x-1][y].colour)) { compres.cash -= 600; board[x-1][y].plane = true; compres.planes++; return 0; } if(!board[x+1][y].plane && (board[x][y].colour==board[x+1][y].colour)) { compres.cash -= 600; board[x+1][y].plane = true; compres.planes++; return 0; } if(!board[x][y-1].plane && (board[x][y].colour==board[x][y-1].colour)) { compres.cash -= 600; board[x][y-1].plane = true; compres.planes++; return 0; } if(!board[x][y+1].plane && (board[x][y].colour==board[x][y+1].colour)) { compres.cash -= 600; board[x][y+1].plane = true; compres.planes++; return 0; } } return 1; } bool has_adjacent(int x, int y) { if((board[x][y].colour == COLOUR_LIGHT) && ((board[x-1][y].colour == COLOUR_DARK) || (board[x+1][y].colour == COLOUR_DARK) || (board[x][y+1].colour == COLOUR_DARK) || (board[x][y-1].colour == COLOUR_DARK))) return 1; else return 0; } void find_adjacent(int x, int y, int* adj_x, int* adj_y, bool* full) { /* Finds adjacent squares, returning squares without tanks on them * in preference to those with them */ if(((board[x-1][y].tank && (board[x-1][y].colour == COLOUR_DARK)) || board[x-1][y].colour != COLOUR_DARK) && ((board[x+1][y].tank && (board[x+1][y].colour == COLOUR_DARK)) || board[x+1][y].colour != COLOUR_DARK) && ((board[x][y-1].tank && (board[x][y-1].colour == COLOUR_DARK)) || board[x][y-1].colour != COLOUR_DARK) && ((board[x][y+1].tank && (board[x][y+1].colour == COLOUR_DARK)) || board[x][y+1].colour != COLOUR_DARK)) { *full = true; } else { *full = false; } if(board[x-1][y].colour == COLOUR_DARK) { *adj_x = x-1; *adj_y = y; if(board[x-1][y].tank) { if(*full) return; } else { return; } } if(board[x+1][y].colour == COLOUR_DARK) { *adj_x = x+1; *adj_y = y; if(board[x+1][y].tank) { if(*full) return; } else { return; } } if(board[x][y-1].colour == COLOUR_DARK) { *adj_x = x; *adj_y = y-1; if(board[x][y-1].tank) { if(*full) return; } else { return; } } if(board[x][y+1].colour == COLOUR_DARK) { *adj_x = x; *adj_y = y+1; if(board[x][y+1].tank) { if(*full) return; } else { return; } } } void computer_allocate(void) { /* Firstly, decide whether to go offensive or defensive. * This is primarily decided by the human player posing a threat to either * the computer's farms or factories */ int i, j, k; bool offensive = true; struct threat threats[4]; int numthreats = 0; int total_str_diff = 0; int men_needed; struct threat targets[2]; int numtargets; struct cursor adj; bool full = false; for(i=1;i<12;i++) { for(j=1;j<12;j++) { if((board[i][j].colour == COLOUR_DARK) && (calc_strength(COLOUR_DARK,i,j) < calc_strength(COLOUR_LIGHT,i,j))) { if(board[i][j].ind || board[i][j].farm) { if(numthreats < 3) { offensive = false; threats[numthreats].x = i; threats[numthreats].y = j; threats[numthreats].str_diff = calc_strength(COLOUR_LIGHT,i,j) - calc_strength(COLOUR_DARK,i,j); numthreats++; } } } rb->yield(); } } if(offensive) { /* The AI is going to go straight for the throat here and attack * the player's farms and factories. The amount of cash * the AI has to spend will determine how many targets there are */ if(compres.cash > 1200) { /* 1200 is a figure I pulled out of nowhere. Adjust as needed */ numtargets = 2; } else { numtargets = 1; } /* Work out which target(s) to attack. They must have adjacent squares * owned by the computer. If none are found just place troops in * random places around the map until we run out of money */ k = 0; while(kyield(); } } } if(k == 0) { /* No targets found! Randomly pick squares and if they're owned * by the computer then stick a tank on it. */ rb->srand(*rb->current_tick); while(compres.cash >= 300) { i = rb->rand()%11 + 1; j = rb->rand()%11 + 1; if(board[i][j].colour == COLOUR_DARK) { if(compres.cash >= 300) { if(!board[i][j].tank) { board[i][j].tank = true; compres.tanks++; compres.cash -= 300; draw_board(); rb->sleep(HZ); } } } } compres.bank += compres.cash; compres.cash = 0; } else { for(i=0;i calc_strength(COLOUR_DARK, targets[i].x, targets[i].y)) && compres.cash > 0) { /* While we still need them keep placing men */ if(compres.cash >= 300 && !full) { if(board[adj.x][adj.y].tank) { find_adjacent(targets[i].x, targets[i].y, &adj.x, &adj.y, &full); } else { board[adj.x][adj.y].tank = true; compres.tanks++; compres.cash -= 300; draw_board(); rb->sleep(HZ); } } else { men_needed = (calc_strength(COLOUR_LIGHT, targets[i].x, targets[i].y) + 20 - calc_strength(COLOUR_DARK, targets[i].x, targets[i].y))*1000/133; if(compres.cash >= men_needed) { board[adj.x][adj.y].men += men_needed; compres.men += men_needed; compres.cash -= men_needed; compres.bank += compres.cash; compres.cash = 0; } else { board[adj.x][adj.y].men += compres.cash; compres.men += compres.cash; compres.cash = 0; } draw_board(); rb->sleep(HZ); } } } compres.bank += compres.cash; compres.cash = 0; rb->yield(); } } else { /* Work out what to place on each square to defend it. * Tanks are preferential because they do not require food, * but if the budget is tight then we fall back onto troops. * Conversely if cash is not an issue and there are already tanks in * place planes will be deployed. We would like a margin of at least * 20 points to be safe. */ for(i=0;i compres.cash) { /* Not enough cash to accomodate all threats using tanks alone - * use men as a backup */ for(i=0;i= men_needed) { board[threats[i].x][threats[i].y].men += men_needed; compres.cash -= men_needed; compres.men += men_needed; draw_board(); rb->sleep(HZ); } else { board[threats[i].x][threats[i].y].men += compres.cash; compres.men += compres.cash; compres.cash = 0; draw_board(); rb->sleep(HZ); } rb->yield(); } } else if((total_str_diff+20)*15 < compres.cash) { /* Enough money to pay their way by planes */ for(i=0;i= men_needed) { compres.cash -= men_needed; compres.men += men_needed; board[threats[i].x][threats[i].y].men += men_needed; draw_board(); rb->sleep(HZ); } } } else { if(compres.cash >= 600) { board[threats[i].x][threats[i].y].plane = true; compres.cash -= 600; compres.planes++; draw_board(); rb->sleep(HZ); } } } rb->yield(); } } else { /* Tanks it is */ for(i=0;i 0) { if(board[threats[i].x][threats[i].y].tank) { if(place_adjacent(1, threats[i].x, threats[i].y)) { /* No room for any more tanks, revert to men */ men_needed = (calc_strength(COLOUR_LIGHT, threats[i].x, threats[i].y) + 20 - calc_strength(COLOUR_DARK, threats[i].x, threats[i].y)*1000/133); if(compres.cash >= men_needed) { compres.cash -= men_needed; compres.men += men_needed; board[threats[i].x][threats[i].y].men += men_needed; draw_board(); rb->sleep(HZ); } } } else { if(compres.cash >= 300) { board[threats[i].x][threats[i].y].tank = true; compres.tanks++; compres.cash -= 300; draw_board(); rb->sleep(HZ); } } } rb->yield(); } } compres.bank += compres.cash; compres.cash = 0; } } int find_adj_target(int x, int y, struct cursor* adj) { /* Find a square next to a computer's farm or factory owned by the player * that is vulnerable. Return 1 on success, 0 otherwise */ if(board[x+1][y].colour == COLOUR_LIGHT && calc_strength(COLOUR_LIGHT,x+1,y)<=calc_strength(COLOUR_DARK,x+1,y)) { adj->x = x+1; adj->y = y; return 1; } if(board[x-1][y].colour == COLOUR_LIGHT && calc_strength(COLOUR_LIGHT,x-1,y)<=calc_strength(COLOUR_DARK,x-1,y)) { adj->x = x-1; adj->y = y; return 1; } if(board[x][y+1].colour == COLOUR_LIGHT && calc_strength(COLOUR_LIGHT,x,y+1)<=calc_strength(COLOUR_DARK,x,y+1)) { adj->x = x; adj->y = y+1; return 1; } if(board[x][y-1].colour == COLOUR_LIGHT && calc_strength(COLOUR_LIGHT,x,y-1)<=calc_strength(COLOUR_DARK,x,y-1)) { adj->x = x; adj->y = y-1; return 1; } return 0; } void computer_war(void) { /* Work out where to attack - prioritise the defence of buildings */ int i, j; struct cursor adj; while(compres.moves) { for(i=1;i<12;i++) { for(j=1;j<12;j++) { if((board[i][j].colour == COLOUR_DARK) && (board[i][j].farm || board[i][j].ind)) { if(find_adj_target(i, j, &adj) && compres.moves) { if(calc_strength(COLOUR_LIGHT, adj.x, adj.y) == calc_strength(COLOUR_DARK, adj.x, adj.y)) { rb->srand(*rb->current_tick); if(rb->rand()%2) { board[adj.x][adj.y].colour = COLOUR_DARK; board[adj.x][adj.y].tank = false; board[adj.x][adj.y].plane = false; board[adj.x][adj.y].nuke = false; humanres.men -= board[adj.x][adj.y].men; board[adj.x][adj.y].men = 0; draw_board(); rb->sleep(HZ); compres.moves--; } else { rb->splash(HZ*2, "The computer attempted" " to attack, but the" " invasion was pushed" " back"); compres.moves--; } } else { if(compres.moves) { board[adj.x][adj.y].colour = COLOUR_DARK; board[adj.x][adj.y].tank = false; board[adj.x][adj.y].plane = false; board[adj.x][adj.y].nuke = false; humanres.men -= board[adj.x][adj.y].men; board[adj.x][adj.y].men = 0; draw_board(); rb->sleep(HZ); compres.moves--; } } } } rb->yield(); } } if(compres.moves) { /* Defence stage done, move on to OFFENCE */ for(i=1;i<12;i++) { for(j=1;j<12;j++) { if(board[i][j].colour == COLOUR_LIGHT && compres.moves && (board[i][j].ind || board[i][j].farm) && (calc_strength(COLOUR_DARK, i, j) >= calc_strength(COLOUR_LIGHT, i, j))) { if(calc_strength(COLOUR_DARK, i, j) == calc_strength(COLOUR_LIGHT, i, j)) { if(rb->rand()%2) { board[i][j].colour = COLOUR_DARK; board[i][j].tank = false; board[i][j].plane = false; board[i][j].nuke = false; board[i][j].men = 0; draw_board(); rb->sleep(HZ); compres.moves--; } else { rb->splash(HZ*2, "The computer attempted to " "attack, but the invasion was" " pushed back"); compres.moves--; } } else { board[i][j].colour = COLOUR_DARK; board[i][j].tank = false; board[i][j].plane = false; board[i][j].nuke = false; board[i][j].men = 0; draw_board(); rb->sleep(HZ); compres.moves--; } } rb->yield(); } } while(compres.moves > 0) { /* Spend leftover moves wherever attacking randomly */ rb->srand(*rb->current_tick); i = (rb->rand()%10)+1; j = (rb->rand()%10)+1; if(board[i][j].colour == COLOUR_LIGHT && (calc_strength(COLOUR_DARK, i, j) >= calc_strength(COLOUR_LIGHT, i, j))) { if(calc_strength(COLOUR_DARK, i, j) == calc_strength(COLOUR_LIGHT, i, j)) { if(rb->rand()%2) { board[i][j].colour = COLOUR_DARK; board[i][j].tank = false; board[i][j].plane = false; board[i][j].nuke = false; board[i][j].men = 0; draw_board(); rb->sleep(HZ); compres.moves--; } else { rb->splash(HZ*2, "The computer attempted to" " attack, but the invasion was" " pushed back"); compres.moves--; } } else { board[i][j].colour = COLOUR_DARK; board[i][j].tank = false; board[i][j].plane = false; board[i][j].nuke = false; board[i][j].men = 0; draw_board(); rb->sleep(HZ); compres.moves--; } } } } } } static int load_game(const char* file) { int fd; fd = rb->open(file, O_RDONLY); if(fd == 0) { DEBUGF("Couldn't open savegame\n"); return -1; } rb->read(fd, buf, 5); if(rb->strcmp(buf, "SSGv2")) { rb->splash(HZ, "Invalid/incompatible savegame\n"); return -1; } rb->read(fd, &humanres.cash, sizeof(humanres.cash)); rb->read(fd, &humanres.food, sizeof(humanres.food)); rb->read(fd, &humanres.bank, sizeof(humanres.bank)); rb->read(fd, &humanres.planes, sizeof(humanres.planes)); rb->read(fd, &humanres.tanks, sizeof(humanres.tanks)); rb->read(fd, &humanres.men, sizeof(humanres.men)); rb->read(fd, &humanres.nukes, sizeof(humanres.nukes)); rb->read(fd, &humanres.inds, sizeof(humanres.inds)); rb->read(fd, &humanres.farms, sizeof(humanres.farms)); rb->read(fd, &humanres.moves, sizeof(humanres.moves)); rb->read(fd, &compres.cash, sizeof(humanres.cash)); rb->read(fd, &compres.food, sizeof(humanres.food)); rb->read(fd, &compres.bank, sizeof(humanres.bank)); rb->read(fd, &compres.planes, sizeof(humanres.planes)); rb->read(fd, &compres.tanks, sizeof(humanres.tanks)); rb->read(fd, &compres.men, sizeof(humanres.men)); rb->read(fd, &compres.nukes, sizeof(humanres.nukes)); rb->read(fd, &compres.inds, sizeof(humanres.inds)); rb->read(fd, &compres.farms, sizeof(humanres.farms)); rb->read(fd, &compres.moves, sizeof(humanres.moves)); rb->read(fd, board, sizeof(board)); rb->read(fd, &superdom_settings.compstartfarms, sizeof(int)); rb->read(fd, &superdom_settings.compstartinds, sizeof(int)); rb->read(fd, &superdom_settings.humanstartfarms, sizeof(int)); rb->read(fd, &superdom_settings.humanstartfarms, sizeof(int)); rb->read(fd, &superdom_settings.startcash, sizeof(int)); rb->read(fd, &superdom_settings.startfood, sizeof(int)); rb->read(fd, &superdom_settings.movesperturn, sizeof(int)); return 0; } void default_settings(void) { superdom_settings.compstartfarms = 1; superdom_settings.compstartinds = 1; superdom_settings.humanstartfarms = 2; superdom_settings.humanstartinds = 2; superdom_settings.startcash = 0; superdom_settings.startfood = 0; superdom_settings.movesperturn = 2; } int average_strength(bool colour) { /* This function calculates the average strength of the given player, * used to determine when the computer wins or loses. */ int i,j; int totalpower = 0; for(i=0;i<12;i++) { for(j=0;j<12;j++) { if(board[i][j].colour != -1) { totalpower += calc_strength(colour, i, j); } } } return totalpower/100; } enum plugin_status plugin_start(const void* parameter) { int tempmenu; bool statusbar_setting; #if LCD_DEPTH > 1 rb->lcd_set_backdrop(NULL); rb->lcd_set_foreground(LCD_BLACK); rb->lcd_set_background(LCD_WHITE); #endif statusbar_setting = rb->global_settings->statusbar; rb->global_settings->statusbar = false; cursor.x = 1; cursor.y = 1; default_settings(); if(parameter) { if(load_game(parameter) != 0) { DEBUGF("Loading failed, generating new game\n"); init_resources(); init_board(); } else { goto startyear; } } else { init_resources(); init_board(); } bool play = false; while(!play) { switch(menu()) { case 0: play = true; break; case 2: rb->global_settings->statusbar = statusbar_setting; return PLUGIN_OK; break; } } gen_resources(); startyear: if((average_strength(COLOUR_LIGHT) - average_strength(COLOUR_DARK)) > 15) { rb->splash(HZ*4, "The computer has surrendered. You win."); rb->global_settings->statusbar = statusbar_setting; return PLUGIN_OK; } if((average_strength(COLOUR_DARK) - average_strength(COLOUR_LIGHT)) > 15) { rb->splash(HZ*4, "Your army have suffered terrible morale from the bleak prospects of winning. You lose"); rb->global_settings->statusbar = statusbar_setting; return PLUGIN_OK; } tempmenu = production_menu(); switch(tempmenu) { case PLUGIN_USB_CONNECTED: rb->global_settings->statusbar = statusbar_setting; return PLUGIN_USB_CONNECTED; break; case SUPERDOM_QUIT: rb->global_settings->statusbar = statusbar_setting; return PLUGIN_OK; break; } computer_allocate(); humanres.moves += superdom_settings.movesperturn; tempmenu = movement_menu(); switch(tempmenu) { case PLUGIN_USB_CONNECTED: rb->global_settings->statusbar = statusbar_setting; return PLUGIN_USB_CONNECTED; break; case SUPERDOM_QUIT: rb->global_settings->statusbar = statusbar_setting; return PLUGIN_OK; break; } if(humanres.men) { if(humanres.food > humanres.men) { rb->snprintf(buf, sizeof(buf), "Your men ate %d units of food", humanres.men); humanres.food -= humanres.men; } else { rb->snprintf(buf, sizeof(buf), "There was not enough food to feed" " all your men, %d men have died of starvation", killmen(COLOUR_LIGHT)); } rb->splash(HZ*2, buf); } if(compres.men) { if(compres.food < compres.men) { rb->snprintf(buf, sizeof(buf), "The computer does not have enough" " food to feed its men. %d have ided of starvation", killmen(COLOUR_DARK)); rb->splash(HZ, buf); } } tempmenu = war_menu(); switch(tempmenu) { case PLUGIN_USB_CONNECTED: rb->global_settings->statusbar = statusbar_setting; return PLUGIN_USB_CONNECTED; break; case SUPERDOM_QUIT: rb->global_settings->statusbar = statusbar_setting; return PLUGIN_OK; break; } compres.moves += superdom_settings.movesperturn; computer_war(); gen_resources(); goto startyear; rb->global_settings->statusbar = statusbar_setting; return PLUGIN_OK; }