fix some problems with the menu code:
[kugel-rb.git] / apps / plugins / superdom.c
blob088cdaea3314573ec9b88ce46902cbfc25130d1e
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2006 Will Robertson
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
21 #include "plugin.h"
22 PLUGIN_HEADER
23 static const struct plugin_api* rb;
25 extern const fb_data superdom_boarditems[];
26 char buf[255];
28 #define COLOUR_DARK 0
29 #define COLOUR_LIGHT 1
31 #define MARGIN 5
33 #if LCD_WIDTH > LCD_HEIGHT
34 #define BOX_WIDTH ((LCD_WIDTH-(MARGIN*2))/10)
35 #define BOX_HEIGHT ((BOX_WIDTH*2)/3)
37 #else
38 #define BOX_HEIGHT ((LCD_HEIGHT-(MARGIN*2)-15)/10)
39 #define BOX_WIDTH ((BOX_HEIGHT*2)/3)
41 #endif
43 #if LCD_WIDTH == 220 && LCD_HEIGHT == 176
44 #define NUM_BOX_HEIGHT 25
45 #define NUM_BOX_WIDTH 30
46 #define STRIDE 14
47 #define ICON_HEIGHT 7
48 #define ICON_WIDTH 7
50 #elif (LCD_WIDTH == 160 && LCD_HEIGHT == 128) || \
51 (LCD_WIDTH == 176 && LCD_HEIGHT == 132) || \
52 (LCD_WIDTH == 176 && LCD_HEIGHT == 220)
53 #define NUM_BOX_HEIGHT 20
54 #define NUM_BOX_WIDTH 24
55 #define STRIDE 8
56 #define ICON_HEIGHT 4
57 #define ICON_WIDTH 4
59 #elif (LCD_WIDTH == 320 && LCD_HEIGHT == 240)
60 #define NUM_BOX_HEIGHT 25
61 #define NUM_BOX_WIDTH 30
62 #define STRIDE 20
63 #define ICON_HEIGHT 10
64 #define ICON_WIDTH 10
66 #elif (LCD_WIDTH == 240 && LCD_HEIGHT == 320)
67 #define NUM_BOX_HEIGHT 25
68 #define NUM_BOX_WIDTH 30
69 #define STRIDE 18
70 #define ICON_HEIGHT 9
71 #define ICON_WIDTH 9
73 #endif
75 #define NUM_MARGIN_X (LCD_WIDTH-3*NUM_BOX_WIDTH)/2
76 #define NUM_MARGIN_Y (LCD_HEIGHT-4*NUM_BOX_HEIGHT)/2
78 #if (CONFIG_KEYPAD == IPOD_4G_PAD) || (CONFIG_KEYPAD == IPOD_3G_PAD) || \
79 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
80 #define SUPERDOM_OK BUTTON_SELECT
81 #define SUPERDOM_CANCEL BUTTON_MENU
82 #define SUPERDOM_LEFT BUTTON_LEFT
83 #define SUPERDOM_RIGHT BUTTON_RIGHT
84 #define IPOD_STYLE
86 #elif CONFIG_KEYPAD == IRIVER_H300_PAD || CONFIG_KEYPAD == IRIVER_H100_PAD
87 #define SUPERDOM_OK BUTTON_SELECT
88 #define SUPERDOM_LEFT BUTTON_LEFT
89 #define SUPERDOM_RIGHT BUTTON_RIGHT
90 #define SUPERDOM_UP BUTTON_UP
91 #define SUPERDOM_DOWN BUTTON_DOWN
92 #define SUPERDOM_CANCEL BUTTON_OFF
94 #elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
95 #define SUPERDOM_OK BUTTON_SELECT
96 #define SUPERDOM_LEFT BUTTON_LEFT
97 #define SUPERDOM_RIGHT BUTTON_RIGHT
98 #define SUPERDOM_UP BUTTON_UP
99 #define SUPERDOM_DOWN BUTTON_DOWN
100 #define SUPERDOM_CANCEL BUTTON_REC
102 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
103 #define SUPERDOM_OK BUTTON_RIGHT
104 #define SUPERDOM_UP BUTTON_SCROLL_UP
105 #define SUPERDOM_DOWN BUTTON_SCROLL_DOWN
106 #define SUPERDOM_CANCEL BUTTON_LEFT
108 #elif CONFIG_KEYPAD == GIGABEAT_PAD
109 #define SUPERDOM_OK BUTTON_SELECT
110 #define SUPERDOM_UP BUTTON_UP
111 #define SUPERDOM_DOWN BUTTON_DOWN
112 #define SUPERDOM_LEFT BUTTON_LEFT
113 #define SUPERDOM_RIGHT BUTTON_RIGHT
114 #define SUPERDOM_CANCEL BUTTON_POWER
116 #elif CONFIG_KEYPAD == SANSA_E200_PAD
117 #define SUPERDOM_OK BUTTON_SELECT
118 #define SUPERDOM_UP BUTTON_SCROLL_BACK
119 #define SUPERDOM_DOWN BUTTON_SCROLL_FWD
120 #define SUPERDOM_LEFT BUTTON_LEFT
121 #define SUPERDOM_RIGHT BUTTON_RIGHT
122 #define SUPERDOM_CANCEL BUTTON_POWER
124 #elif CONFIG_KEYPAD == GIGABEAT_S_PAD
125 #define SUPERDOM_OK BUTTON_SELECT
126 #define SUPERDOM_UP BUTTON_UP
127 #define SUPERDOM_DOWN BUTTON_DOWN
128 #define SUPERDOM_LEFT BUTTON_LEFT
129 #define SUPERDOM_RIGHT BUTTON_RIGHT
130 #define SUPERDOM_CANCEL BUTTON_BACK
132 #elif CONFIG_KEYPAD == COWOND2_PAD
133 #define SUPERDOM_CANCEL BUTTON_POWER
135 #endif
137 #ifdef HAVE_TOUCHSCREEN
138 #ifndef SUPERDOM_OK
139 #define SUPERDOM_OK BUTTON_CENTER
140 #endif
141 #ifndef SUPERDOM_UP
142 #define SUPERDOM_UP BUTTON_TOPMIDDLE
143 #endif
144 #ifndef SUPERDOM_LEFT
145 #define SUPERDOM_LEFT BUTTON_MIDLEFT
146 #endif
147 #ifndef SUPERDOM_RIGHT
148 #define SUPERDOM_RIGHT BUTTON_MIDRIGHT
149 #endif
150 #ifndef SUPERDOM_DOWN
151 #define SUPERDOM_DOWN BUTTON_BOTTOMMIDDLE
152 #endif
153 #ifndef SUPERDOM_CANCEL
154 #define SUPERDOM_CANCEL BUTTON_TOPLEFT
155 #endif
156 #endif
158 #define SUPERDOM_QUIT 23
160 void gen_interest(void);
161 int production_menu(void);
162 void init_resources(void);
163 int select_square(void);
164 void update_score(void);
165 void gen_resources(void);
166 void draw_cursor(void);
167 int calc_strength(bool colour, int x, int y);
168 void draw_board(void);
170 struct tile{
171 signed int colour; /* -1 = Unset */
172 bool tank;
173 bool plane;
174 bool nuke;
175 bool ind;
176 bool farm;
177 int men;
180 struct resources {
181 int cash;
182 int food;
183 int farms;
184 int inds;
185 int men;
186 int tanks;
187 int planes;
188 int nukes;
189 int bank;
190 int moves;
193 struct settings {
194 int compstartfarms;
195 int compstartinds;
196 int humanstartfarms;
197 int humanstartinds;
198 int startcash;
199 int startfood;
200 int movesperturn;
201 } superdom_settings;
203 struct resources humanres;
204 struct resources compres;
206 struct cursor{
207 int x;
208 int y;
209 } cursor;
211 struct tile board[12][12];
213 void init_board(void) {
214 rb->srand(*rb->current_tick);
215 int i,j;
216 for(i=0;i<12;i++) { /* Hopefully about 50% each colour */
217 for(j=0;j<12;j++) {
218 if((i<1)||(j<1)||(i>10)||(j>10))
219 board[i][j].colour = -1; /* Unset */
220 else
221 board[i][j].colour = rb->rand()%2;
222 board[i][j].tank = false;
223 board[i][j].plane = false;
224 board[i][j].nuke = false;
225 board[i][j].ind = false;
226 board[i][j].farm = false;
227 board[i][j].men = 0;
231 while(compres.farms < superdom_settings.compstartfarms) {
232 i = rb->rand()%10 + 1;
233 j = rb->rand()%10 + 1;
234 if((board[i][j].colour == COLOUR_DARK) && (board[i][j].farm == false)) {
235 board[i][j].farm = true;
236 compres.farms++;
237 break;
240 while(compres.inds < superdom_settings.compstartinds) {
241 i = rb->rand()%10 + 1;
242 j = rb->rand()%10 + 1;
243 if((board[i][j].colour == COLOUR_DARK) && (board[i][j].ind == false)) {
244 board[i][j].ind = true;
245 compres.inds++;
246 break;
249 while(humanres.farms<superdom_settings.humanstartfarms) {
250 i = rb->rand()%10 + 1;
251 j = rb->rand()%10 + 1;
252 if((board[i][j].colour == COLOUR_LIGHT)&&(board[i][j].farm == false)) {
253 board[i][j].farm = true;
254 humanres.farms++;
257 while(humanres.inds<superdom_settings.humanstartfarms) {
258 i = rb->rand()%10 + 1;
259 j = rb->rand()%10 + 1;
260 if((board[i][j].colour == COLOUR_LIGHT) && (board[i][j].ind == false)) {
261 board[i][j].ind = true;
262 humanres.inds++;
267 void draw_board(void) {
268 rb->lcd_clear_display();
269 int i,j;
270 for(i=1;i<11;i++) {
271 for(j=1;j<11;j++) {
272 if(board[i][j].colour == COLOUR_DARK) {
273 rb->lcd_set_foreground(LCD_DARKGRAY);
274 } else {
275 rb->lcd_set_foreground(LCD_LIGHTGRAY);
277 rb->lcd_fillrect(MARGIN+(BOX_WIDTH*(i-1)),
278 MARGIN+(BOX_HEIGHT*(j-1)), BOX_WIDTH,
279 BOX_HEIGHT);
280 #if LCD_DEPTH != 16
281 rb->lcd_set_drawmode(DRMODE_BG | DRMODE_INVERSEVID);
282 #endif
283 if(board[i][j].ind) {
284 #if (LCD_DEPTH == 16)
285 rb->lcd_bitmap_transparent_part(superdom_boarditems,
286 #else
287 rb->lcd_mono_bitmap_part(superdom_boarditems,
288 #endif
289 board[i][j].colour?ICON_WIDTH:0, 0, STRIDE,
290 #if LCD_WIDTH > LCD_HEIGHT
291 MARGIN+(BOX_WIDTH*(i-1))+1,
292 MARGIN+(BOX_HEIGHT*(j-1))+ICON_HEIGHT+1,
293 #else
294 MARGIN+(BOX_WIDTH*(i-1))+1+ICON_WIDTH,
295 MARGIN+(BOX_HEIGHT*(j-1))+1,
296 #endif
297 ICON_WIDTH, ICON_HEIGHT);
299 if(board[i][j].farm) {
300 #if (LCD_DEPTH == 16)
301 rb->lcd_bitmap_transparent_part(superdom_boarditems,
302 #else
303 rb->lcd_mono_bitmap_part(superdom_boarditems,
304 #endif
305 board[i][j].colour?ICON_WIDTH:0, ICON_HEIGHT,
306 STRIDE, MARGIN+(BOX_WIDTH*(i-1))+1,
307 MARGIN+(BOX_HEIGHT*(j-1))+1,
308 ICON_WIDTH, ICON_HEIGHT);
310 if(board[i][j].tank) {
311 #if (LCD_DEPTH == 16)
312 rb->lcd_bitmap_transparent_part(superdom_boarditems,
313 #else
314 rb->lcd_mono_bitmap_part(superdom_boarditems,
315 #endif
316 board[i][j].colour?ICON_WIDTH:0, ICON_HEIGHT*2,
317 STRIDE, MARGIN+(BOX_WIDTH*(i-1))+ICON_WIDTH+1,
318 MARGIN+(BOX_HEIGHT*(j-1))+ICON_HEIGHT+1,
319 ICON_WIDTH, ICON_HEIGHT);
321 if(board[i][j].men) {
322 #if (LCD_DEPTH == 16)
323 rb->lcd_bitmap_transparent_part(superdom_boarditems,
324 #else
325 rb->lcd_mono_bitmap_part(superdom_boarditems,
326 #endif
327 board[i][j].colour?ICON_WIDTH:0, ICON_HEIGHT*3,
328 #if LCD_WIDTH > LCD_HEIGHT
329 STRIDE, MARGIN+(BOX_WIDTH*(i-1))+ICON_WIDTH+1,
330 MARGIN+(BOX_HEIGHT*(j-1))+1,
331 #else
332 STRIDE, MARGIN+(BOX_WIDTH*(i-1))+1,
333 MARGIN+(BOX_HEIGHT*(j-1))+1+ICON_HEIGHT,
334 #endif
335 ICON_WIDTH, ICON_HEIGHT);
337 if(board[i][j].plane) {
338 #if (LCD_DEPTH == 16)
339 rb->lcd_bitmap_transparent_part(superdom_boarditems,
340 #else
341 rb->lcd_mono_bitmap_part(superdom_boarditems,
342 #endif
343 board[i][j].colour?ICON_WIDTH:0, ICON_HEIGHT*4,
344 #if LCD_WIDTH > LCD_HEIGHT
345 STRIDE,MARGIN+(BOX_WIDTH*(i-1))+ICON_WIDTH*2+1,
346 MARGIN+(BOX_HEIGHT*(j-1))+ICON_HEIGHT+1,
347 #else
348 STRIDE,MARGIN+(BOX_WIDTH*(i-1))+ICON_WIDTH+1,
349 MARGIN+(BOX_HEIGHT*(j-1))+ICON_HEIGHT*2+1,
350 #endif
351 ICON_WIDTH, ICON_HEIGHT);
353 if(board[i][j].nuke) {
354 #if (LCD_DEPTH == 16)
355 rb->lcd_bitmap_transparent_part(superdom_boarditems,
356 #else
357 rb->lcd_mono_bitmap_part(superdom_boarditems,
358 #endif
359 board[i][j].colour?ICON_WIDTH:0, ICON_HEIGHT*5,
360 #if LCD_WIDTH > LCD_HEIGHT
361 STRIDE,MARGIN+(BOX_WIDTH*(i-1))+ICON_WIDTH*2+1,
362 MARGIN+(BOX_HEIGHT*(j-1))+1,
363 #else
364 STRIDE,MARGIN+(BOX_WIDTH*(i-1))+1,
365 MARGIN+(BOX_HEIGHT*(j-1))+ICON_HEIGHT*2+1,
366 #endif
367 ICON_WIDTH, ICON_HEIGHT);
369 #if LCD_DEPTH != 16
370 rb->lcd_set_drawmode(DRMODE_SOLID);
371 #endif
374 rb->lcd_set_foreground(LCD_BLACK);
375 for(i=0;i<=10;i++) { /* Draw Horizontal lines */
376 rb->lcd_hline(MARGIN, MARGIN+(BOX_WIDTH*10), MARGIN+(BOX_HEIGHT*i));
378 for(i=0;i<=10;i++) { /* Draw Vertical lines */
379 rb->lcd_vline(MARGIN+(BOX_WIDTH*i), MARGIN, MARGIN+(BOX_HEIGHT*10));
381 rb->lcd_update();
384 int calc_strength(bool colour, int x, int y) {
385 int a, b, score=0;
386 for (a = -1; a < 2; a++){
387 for (b = -1; b < 2; b++){
388 if (b == 0){
389 if(board[x + a][y].colour == colour)
390 score+=10;
391 if(((board[x + a][y].colour == colour) && board[x + a][y].tank) || ((board[x + a][y].colour == colour) && board[x + a][y].farm))
392 score+=30;
393 if(((board[x + a][y].colour == colour) && board[x + a][y].plane) || ((board[x + a][y].colour == colour) && board[x + a][y].ind))
394 score+=40;
395 if((board[x + a][y].colour == colour) && board[x + a][y].nuke)
396 score+=20;
397 if((board[x + a][y].colour == colour) && board[x + a][y].men)
398 score+=(board[x + a][y].men*133/1000);
399 } else if (a == 0){
400 if(board[x][y + b].colour == colour)
401 score+=10;
402 if(((board[x][y + b].colour == colour) && board[x][y + b].tank) || ((board[x][y + b].colour == colour) && board[x][y + b].farm))
403 score+=30;
404 if(((board[x][y + b].colour == colour) && board[x][y + b].plane) || ((board[x][y + b].colour == colour) && board[x][y + b].ind))
405 score+=40;
406 if((board[x][y + b].colour == colour) && board[x][y + b].nuke)
407 score+=20;
408 if((board[x][y + b].colour == colour) && board[x][y + b].men)
409 score+=(board[x][y + b].men*133/1000);
413 return score;
416 void gen_interest(void) {
417 /* Interest should be around 10% */
418 rb->srand(*rb->current_tick);
419 int interest = 7+rb->rand()%6;
420 humanres.bank = humanres.bank+(interest*humanres.bank/100);
423 void draw_cursor(void) {
424 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
425 rb->lcd_fillrect(MARGIN+((cursor.x-1)*BOX_WIDTH),
426 MARGIN+((cursor.y-1)*BOX_HEIGHT), BOX_WIDTH+1, BOX_HEIGHT+1);
427 rb->lcd_set_drawmode(DRMODE_SOLID);
428 rb->lcd_update();
431 void gen_resources(void) {
432 gen_interest();
433 int inccash = 0;
434 int incfood = 0;
435 int i;
436 rb->srand(*rb->current_tick);
437 /* Generate Human's resources */
438 for(i=0;i<humanres.inds;i++) {
439 inccash += (300+rb->rand()%200);
441 for(i=0;i<humanres.farms;i++) {
442 incfood += (200+rb->rand()%200);
444 if(inccash/humanres.inds > 450) {
445 if(incfood/humanres.farms > 350) {
446 rb->splash(HZ*2, "Patriotism sweeps the land, all production"
447 " is up this year!");
448 } else {
449 rb->splash(HZ*2, "Factories working at maximum efficiency,"
450 " cash production up this year!");
452 } else if((inccash/humanres.inds>350)&&(inccash/humanres.inds<=450)) {
453 if(incfood/humanres.farms > 350) {
454 rb->splash(HZ*2, "Record crop harvest this year!");
455 } else if((incfood/humanres.farms > 250) &&
456 (incfood/humanres.farms <= 350)) {
457 rb->splash(HZ*2, "Production continues as normal");
458 } else {
459 rb->splash(HZ*2, "Spoilage of crops leads to reduced farm"
460 " output this year");
462 } else {
463 if(incfood/humanres.farms > 350) {
464 rb->splash(HZ*2, "Record crop harvest this year!");
465 } else if((incfood/humanres.farms > 250) &&
466 (incfood/humanres.farms <= 350)) {
467 rb->splash(HZ*2, "Factory unions introduced. Industrial"
468 " production is down this year.");
469 } else {
470 rb->splash(HZ*2, "Internet created. All production is down"
471 " due to time wasted.");
474 humanres.cash += inccash;
475 humanres.food += incfood;
477 /* Generate Computer's resources */
478 inccash = 0;
479 incfood = 0;
480 for(i=0;i<compres.inds;i++) {
481 inccash += (300+rb->rand()%200);
483 for(i=0;i<compres.farms;i++) {
484 incfood += (200+rb->rand()%200);
486 compres.cash += inccash;
487 compres.food += incfood;
490 void update_score(void) {
491 rb->lcd_set_drawmode(DRMODE_BG|DRMODE_INVERSEVID);
492 rb->lcd_fillrect(5,LCD_HEIGHT-20,105,20);
493 rb->lcd_set_drawmode(DRMODE_SOLID);
494 rb->snprintf(buf, sizeof(buf), "Your power: %d.%d",
495 calc_strength(COLOUR_LIGHT, cursor.x, cursor.y)/10,
496 calc_strength(COLOUR_LIGHT, cursor.x, cursor.y)%10);
497 rb->lcd_putsxy(5,LCD_HEIGHT-20, buf);
498 rb->snprintf(buf, sizeof(buf), "Comp power: %d.%d",
499 calc_strength(COLOUR_DARK, cursor.x, cursor.y)/10,
500 calc_strength(COLOUR_DARK, cursor.x, cursor.y)%10);
501 rb->lcd_putsxy(5,LCD_HEIGHT-10, buf);
504 int settings_menu_function(void) {
505 int selection = 0;
507 MENUITEM_STRINGLIST(settings_menu,"Super Domination Settings",NULL,
508 "Computer starting farms","Computer starting factories",
509 "Human starting farms","Human starting factories",
510 "Starting cash","Starting food","Moves per turn");
511 settings_menu:
512 selection=rb->do_menu(&settings_menu,&selection, NULL, false);
513 switch(selection) {
514 case 0:
515 rb->set_int("Computer starting farms", "", UNIT_INT,
516 &superdom_settings.compstartfarms, NULL,
517 1, 0, 5, NULL);
518 goto settings_menu;
519 break;
520 case 1:
521 rb->set_int("Computer starting factories", "", UNIT_INT,
522 &superdom_settings.compstartinds, NULL,
523 1, 0, 5, NULL);
524 goto settings_menu;
525 break;
526 case 2:
527 rb->set_int("Human starting farms", "", UNIT_INT,
528 &superdom_settings.humanstartfarms, NULL,
529 1, 0, 5, NULL);
530 goto settings_menu;
531 break;
532 case 3:
533 superdom_settings.humanstartinds =
534 rb->set_int("Human starting factories", "", UNIT_INT,
535 &superdom_settings.humanstartinds, NULL,
536 1, 0, 5, NULL);
537 goto settings_menu;
538 break;
539 case 4:
540 rb->set_int("Starting cash", "", UNIT_INT,
541 &superdom_settings.startcash, NULL,
542 250, 0, 5000, NULL);
543 goto settings_menu;
544 break;
545 case 5:
546 rb->set_int("Starting food", "", UNIT_INT,
547 &superdom_settings.startfood, NULL,
548 250, 0, 5000, NULL);
549 goto settings_menu;
550 break;
551 case 6:
552 rb->set_int("Moves per turn", "", UNIT_INT,
553 &superdom_settings.movesperturn, NULL,
554 1, 1, 5, NULL);
555 goto settings_menu;
556 break;
557 case MENU_ATTACHED_USB:
558 return PLUGIN_USB_CONNECTED;
559 break;
561 return 0;
564 static int do_help(void) {
565 int button;
566 int y = MARGIN, space_w, width, height;
567 unsigned short x = MARGIN, i = 0;
568 #define WORDS (sizeof instructions / sizeof (char*))
569 static char* instructions[] = {
570 "Super", "domination", "is", "a", "turn", "based", "strategy", "game,",
571 "where", "the", "aim", "is", "to", "overpower", "the", "computer",
572 "player", "by", "taking", "their", "territory.", "",
573 "Each", "year", "you", "are", "allocated", "an", "amount", "of", "cash",
574 "and", "food,", "depending", "on", "how", "many", "farms", "and",
575 "factories", "you", "control.", "",
576 "Use", "this", "cash", "and", "food", "to", "buy", "and", "feed", "your",
577 "army.", "Each", "tile", "has", "a", "strength,", "calculated", "by",
578 "the", "ownership", "of", "adjacent", "tiles,", "and", "the", "type",
579 "and", "number", "of", "troops", "on", "them.",
581 rb->lcd_clear_display();
582 rb->lcd_getstringsize(" ", &space_w, &height);
583 for (i = 0; i < WORDS; i++) {
584 rb->lcd_getstringsize(instructions[i], &width, NULL);
585 /* Skip to next line if the current one can't fit the word */
586 if (x + width > LCD_WIDTH - MARGIN) {
587 x = MARGIN;
588 y += height;
590 /* .. or if the word is the empty string */
591 if (rb->strcmp(instructions[i], "") == 0) {
592 x = MARGIN;
593 y += height;
594 continue;
596 /* We filled the screen */
597 if (y + height > LCD_HEIGHT - MARGIN) {
598 y = MARGIN;
599 rb->lcd_update();
600 do {
601 button = rb->button_get(true);
602 if (button == SYS_USB_CONNECTED) {
603 return PLUGIN_USB_CONNECTED;
605 } while( ( button == BUTTON_NONE )
606 || ( button & (BUTTON_REL|BUTTON_REPEAT) ) );
609 rb->lcd_clear_display();
611 rb->lcd_putsxy(x, y, instructions[i]);
612 x += width + space_w;
614 rb->lcd_update();
615 do {
616 button = rb->button_get(true);
617 if (button == SYS_USB_CONNECTED) {
618 return PLUGIN_USB_CONNECTED;
620 } while( ( button == BUTTON_NONE )
621 || ( button & (BUTTON_REL|BUTTON_REPEAT) ) );
623 return 0;
626 int menu(void) {
627 int selection = 0;
629 MENUITEM_STRINGLIST(main_menu,"Super Domination Menu",NULL,
630 "Play Super Domination","Settings","Help","Quit");
632 while(1) {
633 selection=rb->do_menu(&main_menu,&selection, NULL, false);
634 switch(selection) {
635 case 0:
636 return 0; /* start playing */
637 break;
638 case 1:
639 if(settings_menu_function()==PLUGIN_USB_CONNECTED)
640 return PLUGIN_USB_CONNECTED;
641 break;
642 case 2:
643 if(do_help()==PLUGIN_USB_CONNECTED)
644 return PLUGIN_USB_CONNECTED;
645 break;
646 default:
647 return 2; /* quit program */
648 break;
652 return 3;
655 int save_game(void) {
656 int fd;
657 char savepath[MAX_PATH];
659 rb->snprintf(savepath, sizeof(savepath), "/Savegame.ssg");
660 if(rb->kbd_input(savepath, MAX_PATH)) {
661 DEBUGF("Keyboard input failed\n");
662 return -1;
665 fd = rb->open(savepath, O_WRONLY|O_CREAT);
666 DEBUGF("savepath: %s\n", savepath);
667 if(fd < 0) {
668 DEBUGF("Couldn't create/open file\n");
669 return -1;
672 rb->write(fd, "SSGv2", 5);
673 rb->write(fd, &humanres.cash, sizeof(humanres.cash));
674 rb->write(fd, &humanres.food, sizeof(humanres.food));
675 rb->write(fd, &humanres.bank, sizeof(humanres.bank));
676 rb->write(fd, &humanres.planes, sizeof(humanres.planes));
677 rb->write(fd, &humanres.tanks, sizeof(humanres.tanks));
678 rb->write(fd, &humanres.men, sizeof(humanres.men));
679 rb->write(fd, &humanres.nukes, sizeof(humanres.nukes));
680 rb->write(fd, &humanres.inds, sizeof(humanres.inds));
681 rb->write(fd, &humanres.farms, sizeof(humanres.farms));
682 rb->write(fd, &humanres.moves, sizeof(humanres.moves));
683 rb->write(fd, &compres.cash, sizeof(compres.cash));
684 rb->write(fd, &compres.food, sizeof(compres.food));
685 rb->write(fd, &compres.bank, sizeof(compres.bank));
686 rb->write(fd, &compres.planes, sizeof(compres.planes));
687 rb->write(fd, &compres.tanks, sizeof(compres.tanks));
688 rb->write(fd, &compres.men, sizeof(compres.men));
689 rb->write(fd, &compres.nukes, sizeof(compres.nukes));
690 rb->write(fd, &compres.inds, sizeof(compres.inds));
691 rb->write(fd, &compres.farms, sizeof(compres.farms));
692 rb->write(fd, &compres.moves, sizeof(compres.moves));
693 rb->write(fd, board, sizeof(board));
694 rb->write(fd, &superdom_settings.compstartfarms, sizeof(int));
695 rb->write(fd, &superdom_settings.compstartinds, sizeof(int));
696 rb->write(fd, &superdom_settings.humanstartfarms, sizeof(int));
697 rb->write(fd, &superdom_settings.humanstartfarms, sizeof(int));
698 rb->write(fd, &superdom_settings.startcash, sizeof(int));
699 rb->write(fd, &superdom_settings.startfood, sizeof(int));
700 rb->write(fd, &superdom_settings.movesperturn, sizeof(int));
701 rb->close(fd);
702 return 0;
705 int ingame_menu(void) {
706 int selection = 0;
708 MENUITEM_STRINGLIST(ingame_menu,"Super Domination Menu",NULL,
709 "Return to game","Save Game", "Quit");
711 selection=rb->do_menu(&ingame_menu,&selection, NULL, false);
712 switch(selection) {
713 case 0:
714 return 0;
715 break;
716 case 1:
717 if(!save_game())
718 rb->splash(HZ, "Game saved");
719 else
720 rb->splash(HZ, "Error in save");
721 break;
722 case 2:
723 return SUPERDOM_QUIT;
724 break;
725 case MENU_ATTACHED_USB:
726 return PLUGIN_USB_CONNECTED;
727 break;
729 return 0;
732 int get_number(char* param, int* value) {
733 //int numbers[3][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
734 int numbers[3][3];
735 numbers[0][0] = 1;
736 numbers[0][1] = 2;
737 numbers[0][2] = 3;
738 numbers[1][0] = 4;
739 numbers[1][1] = 5;
740 numbers[1][2] = 6;
741 numbers[2][0] = 7;
742 numbers[2][1] = 8;
743 numbers[2][2] = 9;
744 rb->lcd_clear_display();
745 /* Draw a 3x4 grid */
746 int i,j,x=0,y=0;
747 for(i=0;i<=3;i++) { /* Vertical lines */
748 rb->lcd_vline(NUM_MARGIN_X+(NUM_BOX_WIDTH*i), NUM_MARGIN_Y,
749 NUM_MARGIN_Y+(4*NUM_BOX_HEIGHT));
751 for(i=0;i<=4;i++) { /* Horizontal lines */
752 rb->lcd_hline(NUM_MARGIN_X, NUM_MARGIN_X+(3*NUM_BOX_WIDTH),
753 NUM_MARGIN_Y+(NUM_BOX_HEIGHT*i));
755 int temp = 1;
756 for(i=0;i<3;i++) {
757 for(j=0;j<3;j++) {
758 rb->snprintf(buf, sizeof(buf), "%d", temp);
759 rb->lcd_putsxy(NUM_MARGIN_X+(j*NUM_BOX_WIDTH)+10,
760 NUM_MARGIN_Y+(i*NUM_BOX_HEIGHT)+8, buf);
761 temp++;
764 rb->lcd_putsxy(NUM_MARGIN_X+5, NUM_MARGIN_Y+(3*NUM_BOX_HEIGHT)+8, "CLR");
765 rb->lcd_putsxy(NUM_MARGIN_X+NUM_BOX_WIDTH+10,
766 NUM_MARGIN_Y+(3*NUM_BOX_HEIGHT)+8, "0");
767 rb->lcd_putsxy(NUM_MARGIN_X+2*NUM_BOX_WIDTH+8,
768 NUM_MARGIN_Y+(3*NUM_BOX_HEIGHT)+8, "OK");
769 rb->snprintf(buf,sizeof(buf), "%d", *value);
770 rb->lcd_putsxy(NUM_MARGIN_X+10, NUM_MARGIN_Y+4*NUM_BOX_HEIGHT+10, buf);
771 int height, width;
772 rb->lcd_getstringsize(param, &width, &height);
773 rb->lcd_putsxy((LCD_WIDTH-width)/2, (NUM_MARGIN_Y-height)/2, param);
774 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
775 rb->lcd_fillrect(NUM_MARGIN_X+(NUM_BOX_WIDTH*x),
776 NUM_MARGIN_Y+(NUM_BOX_HEIGHT*y), NUM_BOX_WIDTH+1,
777 NUM_BOX_HEIGHT+1);
778 rb->lcd_set_drawmode(DRMODE_SOLID);
779 int button = 0;
780 rb->lcd_update();
781 while(1) {
782 button = rb->button_get(true);
783 switch(button) {
784 case SUPERDOM_OK:
785 *value *= 10;
786 if(y!=3) {
787 *value += numbers[y][x];
788 } else if(y==3 && x==0) {
789 *value /= 100;
790 } else if(y==3 && x==2) {
791 *value /= 10;
792 return 0;
794 rb->lcd_set_drawmode(DRMODE_BG|DRMODE_INVERSEVID);
795 rb->lcd_fillrect(0, NUM_MARGIN_Y+4*NUM_BOX_HEIGHT+10,
796 LCD_WIDTH, 30);
797 rb->lcd_set_drawmode(DRMODE_SOLID);
798 rb->snprintf(buf,sizeof(buf), "%d", *value);
799 rb->lcd_putsxy(NUM_MARGIN_X+10,
800 NUM_MARGIN_Y+4*NUM_BOX_HEIGHT+10, buf);
801 break;
802 case SUPERDOM_CANCEL:
803 return 0;
804 break;
805 #if CONFIG_KEYPAD != IRIVER_H10_PAD
806 case SUPERDOM_LEFT:
807 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
808 rb->lcd_fillrect(NUM_MARGIN_X+(NUM_BOX_WIDTH*x),
809 NUM_MARGIN_Y+(NUM_BOX_HEIGHT*y),
810 NUM_BOX_WIDTH+1, NUM_BOX_HEIGHT+1);
811 rb->lcd_set_drawmode(DRMODE_SOLID);
812 if(x==0) {
813 #ifdef IPOD_STYLE
814 if(y>0)
815 y--;
816 else
817 y=3;
818 #endif
819 x=2;
820 } else {
821 x--;
823 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
824 rb->lcd_fillrect(NUM_MARGIN_X+(NUM_BOX_WIDTH*x),
825 NUM_MARGIN_Y+(NUM_BOX_HEIGHT*y),
826 NUM_BOX_WIDTH+1, NUM_BOX_HEIGHT+1);
827 rb->lcd_set_drawmode(DRMODE_SOLID);
828 break;
829 case SUPERDOM_RIGHT:
830 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
831 rb->lcd_fillrect(NUM_MARGIN_X+(NUM_BOX_WIDTH*x),
832 NUM_MARGIN_Y+(NUM_BOX_HEIGHT*y),
833 NUM_BOX_WIDTH+1, NUM_BOX_HEIGHT+1);
834 rb->lcd_set_drawmode(DRMODE_SOLID);
835 if(x==2) {
836 #ifdef IPOD_STYLE
837 if(y==3)
838 y=0;
839 else
840 y++;
841 #endif
842 x=0;
843 } else {
844 x++;
846 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
847 rb->lcd_fillrect(NUM_MARGIN_X+(NUM_BOX_WIDTH*x),
848 NUM_MARGIN_Y+(NUM_BOX_HEIGHT*y),
849 NUM_BOX_WIDTH+1, NUM_BOX_HEIGHT+1);
850 rb->lcd_set_drawmode(DRMODE_SOLID);
851 break;
852 #endif
853 #ifndef IPOD_STYLE
854 case SUPERDOM_UP:
855 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
856 rb->lcd_fillrect(NUM_MARGIN_X+(NUM_BOX_WIDTH*x),
857 NUM_MARGIN_Y+(NUM_BOX_HEIGHT*y),
858 NUM_BOX_WIDTH+1, NUM_BOX_HEIGHT+1);
859 rb->lcd_set_drawmode(DRMODE_SOLID);
860 if(y==0) {
861 #if CONFIG_KEYPAD == IRIVER_H10_PAD
862 if(x > 0)
863 x--;
864 else
865 x=2;
866 #endif
867 y=3;
868 } else {
869 y--;
871 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
872 rb->lcd_fillrect(NUM_MARGIN_X+(NUM_BOX_WIDTH*x),
873 NUM_MARGIN_Y+(NUM_BOX_HEIGHT*y),
874 NUM_BOX_WIDTH+1, NUM_BOX_HEIGHT+1);
875 rb->lcd_set_drawmode(DRMODE_SOLID);
876 break;
877 case SUPERDOM_DOWN:
878 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
879 rb->lcd_fillrect(NUM_MARGIN_X+(NUM_BOX_WIDTH*x),
880 NUM_MARGIN_Y+(NUM_BOX_HEIGHT*y),
881 NUM_BOX_WIDTH+1, NUM_BOX_HEIGHT+1);
882 rb->lcd_set_drawmode(DRMODE_SOLID);
883 if(y==3) {
884 #if CONFIG_KEYPAD == IRIVER_H10_PAD
885 if(x < 2)
886 x++;
887 else
888 x=0;
889 #endif
890 y=0;
891 } else {
892 y++;
894 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
895 rb->lcd_fillrect(NUM_MARGIN_X+(NUM_BOX_WIDTH*x),
896 NUM_MARGIN_Y+(NUM_BOX_HEIGHT*y),
897 NUM_BOX_WIDTH+1, NUM_BOX_HEIGHT+1);
898 rb->lcd_set_drawmode(DRMODE_SOLID);
899 break;
900 #endif
901 default:
902 if (rb->default_event_handler(button) == SYS_USB_CONNECTED)
904 return PLUGIN_USB_CONNECTED;
906 break;
908 rb->lcd_update();
910 return 0;
913 int buy_resources_menu(void) {
914 int selection,tempmenu,nummen;
916 MENUITEM_STRINGLIST(res_menu, "Buy Resources", NULL, "Buy men ($1)",
917 "Buy tank ($300)", "Buy plane ($600)", "Buy Farm ($1150)",
918 "Buy Factory ($1300)", "Buy Nuke ($2000)",
919 "Finish buying", "Game menu");
921 resources_menu:
922 selection=rb->do_menu(&res_menu,&selection, NULL, false);
923 switch(selection) {
924 case 0:
925 nummen = 0;
926 if(get_number("How many men would you like?", &nummen)
927 == PLUGIN_USB_CONNECTED)
928 return PLUGIN_USB_CONNECTED;
929 if(humanres.cash>=nummen) {
930 rb->splash(HZ, "Where do you want to place them?");
931 tempmenu = select_square();
932 switch(tempmenu) {
933 case 0:
934 rb->splash(HZ, "Cancelled");
935 break;
936 case 2:
937 if(board[cursor.x][cursor.y].colour == COLOUR_LIGHT) {
938 humanres.men += nummen;
939 board[cursor.x][cursor.y].men += nummen;
940 humanres.cash -= nummen;
941 } else {
942 rb->splash(HZ,"Can't place men on enemy territory");
944 break;
945 case PLUGIN_USB_CONNECTED:
946 return PLUGIN_USB_CONNECTED;
947 break;
949 } else {
950 rb->splash(HZ, "Not enough money!");
952 goto resources_menu;
953 break;
954 case 1:
955 if(humanres.cash>=300) {
956 rb->splash(HZ, "Where do you want to place the tank?");
957 tempmenu = select_square();
958 switch(tempmenu) {
959 case 0:
960 rb->splash(HZ, "Cancelled");
961 goto resources_menu;
962 break;
963 case PLUGIN_USB_CONNECTED:
964 return PLUGIN_USB_CONNECTED;
965 break;
967 if(board[cursor.x][cursor.y].colour == COLOUR_LIGHT) {
968 if(board[cursor.x][cursor.y].tank) {
969 rb->splash(HZ, "There is already a tank there");
970 } else {
971 board[cursor.x][cursor.y].tank = true;
972 humanres.cash -= 300;
973 humanres.tanks++;
975 } else {
976 rb->splash(HZ, "Can't place men on enemy territory");
978 } else {
979 rb->splash(HZ, "Not enough money!");
981 goto resources_menu;
982 break;
983 case 2:
984 if(humanres.cash>=600) {
985 rb->splash(HZ, "Where do you want to place the plane?");
986 tempmenu = select_square();
987 switch(tempmenu) {
988 case 0:
989 rb->splash(HZ, "Cancelled");
990 goto resources_menu;
991 break;
992 case PLUGIN_USB_CONNECTED:
993 return PLUGIN_USB_CONNECTED;
994 break;
996 if(board[cursor.x][cursor.y].colour == COLOUR_LIGHT) {
997 if(board[cursor.x][cursor.y].plane) {
998 rb->splash(HZ, "There is already a plane there");
999 } else {
1000 board[cursor.x][cursor.y].plane = true;
1001 humanres.cash -= 600;
1002 humanres.planes++;
1004 } else {
1005 rb->splash(HZ, "Can't place men on enemy territory");
1007 } else {
1008 rb->splash(HZ, "Not enough money!");
1010 goto resources_menu;
1011 break;
1012 case 3:
1013 if(humanres.cash>=1150) {
1014 rb->splash(HZ, "Where do you want to place the farm?");
1015 tempmenu = select_square();
1016 switch(tempmenu) {
1017 case 0:
1018 rb->splash(HZ, "Cancelled");
1019 goto resources_menu;
1020 break;
1021 case PLUGIN_USB_CONNECTED:
1022 return PLUGIN_USB_CONNECTED;
1023 break;
1025 if(board[cursor.x][cursor.y].colour == COLOUR_LIGHT) {
1026 if(board[cursor.x][cursor.y].farm) {
1027 rb->splash(HZ, "There is already a farm there");
1028 } else {
1029 board[cursor.x][cursor.y].farm = true;
1030 humanres.cash -= 1150;
1031 humanres.farms++;
1033 } else {
1034 rb->splash(HZ, "Can't build on enemy territory");
1036 } else {
1037 rb->splash(HZ, "Not enough money!");
1039 goto resources_menu;
1040 break;
1041 case 4:
1042 if(humanres.cash>=1300) {
1043 rb->splash(HZ, "Where do you want to place the industrial"
1044 " plant?");
1045 tempmenu = select_square();
1046 switch(tempmenu) {
1047 case 0:
1048 rb->splash(HZ, "Cancelled");
1049 goto resources_menu;
1050 break;
1051 case PLUGIN_USB_CONNECTED:
1052 return PLUGIN_USB_CONNECTED;
1053 break;
1055 if(board[cursor.x][cursor.y].colour == COLOUR_LIGHT) {
1056 if(board[cursor.x][cursor.y].ind) {
1057 rb->splash(HZ, "There is already an industrial"
1058 " plant there");
1059 } else {
1060 board[cursor.x][cursor.y].ind = true;
1061 humanres.cash -= 1300;
1062 humanres.inds++;
1064 } else {
1065 rb->splash(HZ, "Can't build on enemy territory");
1067 } else {
1068 rb->splash(HZ, "Not enough money!");
1070 goto resources_menu;
1071 break;
1072 case 5:
1073 if(humanres.cash>=2000) {
1074 rb->splash(HZ, "Where do you want to place the nuke?");
1075 tempmenu = select_square();
1076 switch(tempmenu) {
1077 case 0:
1078 rb->splash(HZ, "Cancelled");
1079 goto resources_menu;
1080 break;
1081 case PLUGIN_USB_CONNECTED:
1082 return PLUGIN_USB_CONNECTED;
1083 break;
1085 if(board[cursor.x][cursor.y].colour == COLOUR_LIGHT) {
1086 if(board[cursor.x][cursor.y].nuke) {
1087 rb->splash(HZ, "There is already a nuke there");
1088 } else {
1089 board[cursor.x][cursor.y].nuke = true;
1090 humanres.cash -= 2000;
1091 humanres.nukes++;
1093 } else {
1094 rb->splash(HZ, "Can't place a nuke on enemy territory");
1096 } else {
1097 rb->splash(HZ, "Not enough money!");
1099 goto resources_menu;
1100 break;
1101 case 6:
1102 return 0;
1103 break;
1104 case MENU_ATTACHED_USB:
1105 return PLUGIN_USB_CONNECTED;
1106 break;
1108 return 0;
1111 int move_unit(void) {
1112 int selection, nummen;
1113 struct cursor from;
1115 MENUITEM_STRINGLIST(move_unit_menu, "Move unit", NULL, "Move men",
1116 "Move tank", "Move plane");
1117 selection=rb->do_menu(&move_unit_menu,&selection, NULL, false);
1118 switch(selection) {
1119 case 0:
1120 rb->splash(HZ, "Select where to move troops from");
1121 if(select_square() == PLUGIN_USB_CONNECTED)
1122 return PLUGIN_USB_CONNECTED;
1123 if(board[cursor.x][cursor.y].colour == COLOUR_LIGHT) {
1124 if(board[cursor.x][cursor.y].men) {
1125 from.x = cursor.x;
1126 from.y = cursor.y;
1127 nummen = board[from.x][from.y].men;
1128 if(get_number("How many men do you want to move?",
1129 &nummen) == PLUGIN_USB_CONNECTED)
1130 return PLUGIN_USB_CONNECTED;
1131 if(nummen > board[from.x][from.y].men) {
1132 rb->splash(HZ, "You don't have that many troops.");
1133 } else {
1134 rb->splash(HZ,"Select where to move the troops to");
1135 if(select_square() == PLUGIN_USB_CONNECTED)
1136 return PLUGIN_USB_CONNECTED;
1137 if((board[cursor.x][cursor.y].colour == COLOUR_LIGHT) &&
1138 (abs(cursor.x - from.x) <= 1) &&
1139 abs(cursor.y - from.y) <= 1) {
1140 board[from.x][from.y].men -= nummen;
1141 board[cursor.x][cursor.y].men += nummen;
1142 humanres.moves--;
1143 return 0;
1146 } else {
1147 rb->splash(HZ, "You don't have any troops there");
1149 } else {
1150 rb->splash(HZ, "Can't move enemy troops");
1152 break;
1153 case 1:
1154 rb->splash(HZ, "Select where you want to move the tank from");
1155 if(select_square() == PLUGIN_USB_CONNECTED)
1156 return PLUGIN_USB_CONNECTED;
1157 if(board[cursor.x][cursor.y].colour == COLOUR_LIGHT) {
1158 if(board[cursor.x][cursor.y].tank) {
1159 from.x = cursor.x;
1160 from.y = cursor.y;
1161 rb->splash(HZ, "Select where you want"
1162 " to move the tank to");
1163 if(select_square() == PLUGIN_USB_CONNECTED)
1164 return PLUGIN_USB_CONNECTED;
1165 if((board[cursor.x][cursor.y].colour == COLOUR_LIGHT)&&
1166 (abs(cursor.x-from.x) <= 1) &&
1167 (abs(cursor.y-from.y) <= 1)) {
1168 if(board[cursor.x][cursor.y].tank) {
1169 rb->splash(HZ, "There is already a tank there");
1170 } else {
1171 board[from.x][from.y].tank = false;
1172 board[cursor.x][cursor.y].tank = true;
1173 humanres.moves--;
1174 return 0;
1176 } else {
1177 rb->splash(HZ, "Invalid move");
1179 } else {
1180 rb->splash(HZ, "You don't have a tank there");
1182 } else {
1183 rb->splash(HZ, "That isn't your territory");
1185 break;
1186 case 2:
1187 rb->splash(HZ, "Select where you want"
1188 " to move the plane from");
1189 if(select_square() == PLUGIN_USB_CONNECTED)
1190 return PLUGIN_USB_CONNECTED;
1191 if(board[cursor.x][cursor.y].colour == COLOUR_LIGHT) {
1192 if(board[cursor.x][cursor.y].plane) {
1193 from.x = cursor.x;
1194 from.y = cursor.y;
1195 rb->splash(HZ, "Select where you want"
1196 " to move the plane to");
1197 if(select_square() == PLUGIN_USB_CONNECTED)
1198 return PLUGIN_USB_CONNECTED;
1199 if(board[cursor.x][cursor.y].colour == COLOUR_LIGHT) {
1200 if(board[cursor.x][cursor.y].plane) {
1201 rb->splash(HZ,"There is already a plane there");
1202 } else {
1203 board[from.x][from.y].plane = false;
1204 board[cursor.x][cursor.y].plane = true;
1205 humanres.moves--;
1206 return 0;
1208 } else {
1209 rb->splash(HZ, "Invalid move");
1211 } else {
1212 rb->splash(HZ, "You don't have a plane there");
1214 } else {
1215 rb->splash(HZ, "That isn't your territory");
1217 break;
1219 return 0;
1222 int movement_menu(void) {
1223 int selection, tempmenu;
1224 bool menu_quit = false;
1226 MENUITEM_STRINGLIST(move_menu, "Movement", NULL, "Move unit",
1227 "Buy additional moves ($100)", "Launch nuclear missile",
1228 "Check map", "Finish moving", "Game menu");
1230 while(!menu_quit) {
1231 selection=rb->do_menu(&move_menu,&selection, NULL, false);
1232 switch(selection) {
1233 case 0:
1234 if(humanres.moves) {
1235 if(move_unit()==PLUGIN_USB_CONNECTED)
1236 return PLUGIN_USB_CONNECTED;
1237 } else {
1238 rb->splash(HZ, "You have no more moves left."
1239 " You can buy more for $100 each.");
1241 break;
1242 case 1:
1243 if(humanres.cash > 100) {
1244 humanres.moves++;
1245 humanres.cash -= 100;
1246 rb->snprintf(buf, sizeof(buf), "You now have %d moves",
1247 humanres.moves);
1248 rb->splash(HZ, buf);
1250 break;
1251 case 2:
1252 if(humanres.nukes==0) {
1253 rb->splash(HZ, "You do not have any nukes to launch");
1254 } else {
1255 rb->splash(HZ, "Select place to launch nuke from");
1256 if(select_square() == PLUGIN_USB_CONNECTED) {
1257 return PLUGIN_USB_CONNECTED;
1259 if(board[cursor.x][cursor.y].nuke) {
1260 rb->splash(HZ, "Select place to target with nuke");
1261 if(select_square() == PLUGIN_USB_CONNECTED) {
1262 return PLUGIN_USB_CONNECTED;
1264 board[cursor.x][cursor.y].men = 0;
1265 board[cursor.x][cursor.y].tank = 0;
1266 board[cursor.x][cursor.y].plane = 0;
1267 board[cursor.x][cursor.y].ind = 0;
1268 board[cursor.x][cursor.y].nuke = 0;
1269 board[cursor.x][cursor.y].farm = 0;
1270 /* TODO: Fallout carried by wind */
1273 break;
1274 case 3:
1275 if(select_square() == PLUGIN_USB_CONNECTED)
1276 return PLUGIN_USB_CONNECTED;
1277 break;
1278 case 4:
1279 return 0;
1280 break;
1281 case 5:
1282 tempmenu = ingame_menu();
1283 switch(tempmenu) {
1284 case PLUGIN_USB_CONNECTED:
1285 return PLUGIN_USB_CONNECTED;
1286 break;
1287 case SUPERDOM_QUIT:
1288 return SUPERDOM_QUIT;
1289 break;
1291 break;
1292 case MENU_ATTACHED_USB:
1293 return PLUGIN_USB_CONNECTED;
1294 break;
1297 return 0;
1300 int show_inventory(void) {
1301 rb->lcd_clear_display();
1302 rb->lcd_puts(1, 0, "Inventory");
1303 char men[20], tanks[20], planes[20], inds[20], farms[20], nukes[20],
1304 cash[20], food[20], bank[20];
1305 rb->snprintf(men, sizeof(men), "Men: %d", humanres.men);
1306 rb->snprintf(tanks, sizeof(tanks), "Tanks: %d", humanres.tanks);
1307 rb->snprintf(planes, sizeof(planes), "Planes: %d", humanres.planes);
1308 rb->snprintf(inds, sizeof(inds), "Factories: %d", humanres.inds);
1309 rb->snprintf(farms, sizeof(farms), "Farms: %d", humanres.farms);
1310 rb->snprintf(nukes, sizeof(nukes), "Nukes: %d", humanres.nukes);
1311 rb->snprintf(cash, sizeof(cash), "Cash: %d", humanres.cash);
1312 rb->snprintf(food, sizeof(food), "Food: %d", humanres.food);
1313 rb->snprintf(bank, sizeof(bank), "Bank: %d", humanres.bank);
1314 rb->lcd_puts(2, 1, men);
1315 rb->lcd_puts(2, 2, tanks);
1316 rb->lcd_puts(2, 3, planes);
1317 rb->lcd_puts(2, 4, inds);
1318 rb->lcd_puts(2, 5, farms);
1319 rb->lcd_puts(2, 6, nukes);
1320 rb->lcd_puts(2, 7, cash);
1321 rb->lcd_puts(2, 8, food);
1322 rb->lcd_puts(2, 9, bank);
1323 rb->lcd_update();
1324 if(rb->default_event_handler(rb->button_get(true)) == SYS_USB_CONNECTED) {
1325 return PLUGIN_USB_CONNECTED;
1326 } else {
1327 return 0;
1331 int production_menu(void) {
1332 int selection, tempbank, tempmenu;
1334 MENUITEM_STRINGLIST(prod_menu, "Production", NULL, "Buy resources",
1335 "Show inventory", "Check map", "Invest money",
1336 "Withdraw money", "Finish turn", "Game menu");
1338 while(1) {
1339 selection=rb->do_menu(&prod_menu,&selection, NULL, false);
1340 switch(selection) {
1341 case 0:
1342 tempmenu = buy_resources_menu();
1343 switch(tempmenu) {
1344 case PLUGIN_USB_CONNECTED:
1345 return PLUGIN_USB_CONNECTED;
1346 break;
1347 case SUPERDOM_QUIT:
1348 return SUPERDOM_QUIT;
1349 break;
1351 break;
1352 case 1:
1353 tempmenu = show_inventory();
1354 switch(tempmenu) {
1355 case 0:
1356 break;
1357 case PLUGIN_USB_CONNECTED:
1358 return PLUGIN_USB_CONNECTED;
1359 break;
1361 break;
1362 case 2:
1363 tempmenu = select_square();
1364 switch(tempmenu) {
1365 case PLUGIN_USB_CONNECTED:
1366 return PLUGIN_USB_CONNECTED;
1367 break;
1368 case SUPERDOM_QUIT:
1369 return SUPERDOM_QUIT;
1370 break;
1371 case 0:
1372 break;
1374 break;
1375 case 3:
1376 tempbank = humanres.cash;
1377 if(get_number("How much do you want to invest?", &tempbank)
1378 == PLUGIN_USB_CONNECTED)
1379 return PLUGIN_USB_CONNECTED;
1380 if(tempbank>humanres.cash) {
1381 rb->splash(HZ, "You don't have that much cash to invest");
1382 } else {
1383 humanres.cash -= tempbank;
1384 humanres.bank += tempbank;
1386 break;
1387 case 4:
1388 tempbank = 0;
1389 if(get_number("How much do you want to withdraw?", &tempbank)
1390 == PLUGIN_USB_CONNECTED)
1391 return PLUGIN_USB_CONNECTED;
1392 if(tempbank>humanres.bank) {
1393 rb->splash(HZ, "You don't have that much cash to withdraw");
1394 } else {
1395 humanres.cash += tempbank;
1396 humanres.bank -= tempbank;
1398 break;
1399 case 5:
1400 return 0;
1401 break;
1402 case 6:
1403 tempmenu = ingame_menu();
1404 switch(tempmenu) {
1405 case PLUGIN_USB_CONNECTED:
1406 return PLUGIN_USB_CONNECTED;
1407 break;
1408 case SUPERDOM_QUIT:
1409 return SUPERDOM_QUIT;
1410 break;
1412 break;
1413 case MENU_ATTACHED_USB:
1414 return PLUGIN_USB_CONNECTED;
1415 break;
1418 return 0;
1421 void init_resources(void) {
1422 humanres.cash = superdom_settings.startcash;
1423 humanres.food = superdom_settings.startfood;
1424 humanres.tanks = 0;
1425 humanres.planes = 0;
1426 humanres.nukes = 0;
1427 humanres.inds = 0;
1428 humanres.farms = 0;
1429 humanres.men = 0;
1430 humanres.bank = 0;
1431 humanres.moves = 0;
1432 compres.cash = superdom_settings.startcash;
1433 compres.food = superdom_settings.startfood;
1434 compres.tanks = 0;
1435 compres.planes = 0;
1436 compres.nukes = 0;
1437 compres.inds = 0;
1438 compres.farms = 0;
1439 compres.men = 0;
1440 compres.bank = 0;
1441 compres.moves = 0;
1444 int select_square(void) {
1445 draw_board();
1446 draw_cursor();
1447 update_score();
1448 #if LCD_WIDTH >= 220
1449 rb->snprintf(buf, sizeof(buf), "Cash: %d", humanres.cash);
1450 rb->lcd_putsxy(125, LCD_HEIGHT-20, buf);
1451 rb->snprintf(buf, sizeof(buf), "Food: %d", humanres.food);
1452 rb->lcd_putsxy(125, LCD_HEIGHT-10, buf);
1453 #endif
1454 rb->lcd_update();
1455 int button = 0;
1456 while(1) {
1457 button = rb->button_get(true);
1458 switch(button) {
1459 case SUPERDOM_CANCEL:
1460 return 0;
1461 break;
1462 case SUPERDOM_OK:
1463 return 2;
1464 break;
1465 #if CONFIG_KEYPAD != IRIVER_H10_PAD
1466 case SUPERDOM_LEFT:
1467 case (SUPERDOM_LEFT|BUTTON_REPEAT):
1468 draw_cursor(); /* Deselect the current tile */
1469 if(cursor.x>1) {
1470 cursor.x--;
1471 } else {
1472 #ifdef IPOD_STYLE
1473 if(cursor.y>1)
1474 cursor.y--;
1475 else
1476 cursor.y = 10;
1477 #endif
1478 cursor.x = 10;
1480 update_score();
1481 draw_cursor();
1482 break;
1483 case SUPERDOM_RIGHT:
1484 case (SUPERDOM_RIGHT|BUTTON_REPEAT):
1485 draw_cursor(); /* Deselect the current tile */
1486 if(cursor.x<10) {
1487 cursor.x++;
1488 } else {
1489 #ifdef IPOD_STYLE
1490 if(cursor.y<10)
1491 cursor.y++;
1492 else
1493 cursor.y = 1;
1494 #endif
1495 cursor.x = 1;
1497 update_score();
1498 draw_cursor();
1499 break;
1500 #endif
1501 #ifndef IPOD_STYLE
1502 case SUPERDOM_UP:
1503 case (SUPERDOM_UP|BUTTON_REPEAT):
1504 draw_cursor(); /* Deselect the current tile */
1505 if(cursor.y>1) {
1506 cursor.y--;
1507 } else {
1508 #if CONFIG_KEYPAD == IRIVER_H10_PAD
1509 if(cursor.x > 1)
1510 cursor.x--;
1511 else
1512 cursor.x = 10;
1513 #endif
1514 cursor.y = 10;
1516 update_score();
1517 draw_cursor();
1518 break;
1519 case SUPERDOM_DOWN:
1520 case (SUPERDOM_DOWN|BUTTON_REPEAT):
1521 draw_cursor(); /* Deselect the current tile */
1522 if(cursor.y<10) {
1523 cursor.y++;
1524 } else {
1525 #if CONFIG_KEYPAD == IRIVER_H10_PAD
1526 if(cursor.x < 10)
1527 cursor.x++;
1528 else
1529 cursor.x = 1;
1530 #endif
1531 cursor.y = 1;
1533 update_score();
1534 draw_cursor();
1535 break;
1536 #endif
1537 default:
1538 if (rb->default_event_handler(button) == SYS_USB_CONNECTED)
1540 return PLUGIN_USB_CONNECTED;
1546 int killmen(bool human) {
1547 int menkilled,i,j;
1548 int percent;
1549 if(human) {
1550 percent = (humanres.food*1000)/humanres.men;
1551 humanres.food = 0;
1552 } else {
1553 percent = (compres.food*1000)/compres.men;
1554 compres.food = 0;
1556 menkilled = 0;
1557 for(i=1;i<12;i++) {
1558 for(j=1;j<12;j++) {
1559 if(board[i][j].colour == human) {
1560 menkilled += ((board[i][j].men * percent)/1000);
1561 board[i][j].men = (board[i][j].men * percent)/1000;
1566 if(human)
1567 humanres.men -= menkilled;
1568 else
1569 compres.men -= menkilled;
1570 return menkilled;
1573 int war_menu(void) {
1574 int selection, tempmenu;
1576 MENUITEM_STRINGLIST(wartime_menu, "War!", NULL,
1577 "Select territory to attack", "Finish turn", "Game menu");
1579 humanres.moves = superdom_settings.movesperturn;
1580 while(humanres.moves) {
1581 selection=rb->do_menu(&wartime_menu,&selection, NULL, false);
1582 switch(selection) {
1583 case 0:
1584 if(select_square() == PLUGIN_USB_CONNECTED)
1585 return PLUGIN_USB_CONNECTED;
1586 if(board[cursor.x][cursor.y].colour == COLOUR_DARK) {
1587 if(calc_strength(COLOUR_LIGHT, cursor.x,
1588 cursor.y) > calc_strength(COLOUR_DARK,
1589 cursor.x, cursor.y)) {
1590 board[cursor.x][cursor.y].colour = COLOUR_LIGHT;
1591 board[cursor.x][cursor.y].tank = 0;
1592 board[cursor.x][cursor.y].men = 0;
1593 board[cursor.x][cursor.y].plane = 0;
1594 board[cursor.x][cursor.y].nuke = 0;
1595 draw_board();
1596 rb->sleep(HZ*2);
1597 humanres.moves--;
1598 } else if(calc_strength(COLOUR_LIGHT, cursor.x, cursor.y)==
1599 calc_strength(COLOUR_DARK, cursor.x, cursor.y)) {
1600 if(rb->rand()%2) {
1601 board[cursor.x][cursor.y].colour = COLOUR_LIGHT;
1602 board[cursor.x][cursor.y].tank = 0;
1603 board[cursor.x][cursor.y].men = 0;
1604 board[cursor.x][cursor.y].plane = 0;
1605 board[cursor.x][cursor.y].nuke = 0;
1606 draw_board();
1607 rb->sleep(HZ*2);
1608 humanres.moves--;
1609 } else {
1610 rb->splash(HZ, "Your troops were unable to"
1611 " overcome the enemy troops");
1612 humanres.moves--;
1614 } else {
1615 rb->splash(HZ, "Your troops were unable to overcome"
1616 " the enemy troops");
1617 humanres.moves--;
1619 } else {
1620 rb->splash(HZ, "You can't attack your own territory");
1622 break;
1623 case 1:
1624 return 0;
1625 break;
1626 case 2:
1627 tempmenu = ingame_menu();
1628 switch(tempmenu) {
1629 case PLUGIN_USB_CONNECTED:
1630 return PLUGIN_USB_CONNECTED;
1631 break;
1632 case SUPERDOM_QUIT:
1633 return SUPERDOM_QUIT;
1634 break;
1636 break;
1639 return 0;
1642 struct threat {
1643 int x;
1644 int y;
1645 int str_diff;
1648 bool place_adjacent(bool tank, int x, int y) {
1649 if(tank) {
1650 if(!board[x-1][y].tank && (board[x][y].colour==board[x-1][y].colour)) {
1651 compres.cash -= 300;
1652 board[x-1][y].tank = true;
1653 compres.tanks++;
1654 return 0;
1656 if(!board[x+1][y].tank && (board[x][y].colour==board[x+1][y].colour)) {
1657 compres.cash -= 300;
1658 board[x+1][y].tank = true;
1659 compres.tanks++;
1660 return 0;
1662 if(!board[x][y-1].tank && (board[x][y].colour==board[x][y-1].colour)) {
1663 compres.cash -= 300;
1664 board[x][y-1].tank = true;
1665 compres.tanks++;
1666 return 0;
1668 if(!board[x][y+1].tank && (board[x][y].colour==board[x][y+1].colour)) {
1669 compres.cash -= 300;
1670 board[x][y+1].tank = true;
1671 compres.tanks++;
1672 return 0;
1674 } else {
1675 if(!board[x-1][y].plane && (board[x][y].colour==board[x-1][y].colour)) {
1676 compres.cash -= 600;
1677 board[x-1][y].plane = true;
1678 compres.planes++;
1679 return 0;
1681 if(!board[x+1][y].plane && (board[x][y].colour==board[x+1][y].colour)) {
1682 compres.cash -= 600;
1683 board[x+1][y].plane = true;
1684 compres.planes++;
1685 return 0;
1687 if(!board[x][y-1].plane && (board[x][y].colour==board[x][y-1].colour)) {
1688 compres.cash -= 600;
1689 board[x][y-1].plane = true;
1690 compres.planes++;
1691 return 0;
1693 if(!board[x][y+1].plane && (board[x][y].colour==board[x][y+1].colour)) {
1694 compres.cash -= 600;
1695 board[x][y+1].plane = true;
1696 compres.planes++;
1697 return 0;
1700 return 1;
1703 bool has_adjacent(int x, int y) {
1704 if((board[x][y].colour == COLOUR_LIGHT) &&
1705 ((board[x-1][y].colour == COLOUR_DARK) ||
1706 (board[x+1][y].colour == COLOUR_DARK) ||
1707 (board[x][y+1].colour == COLOUR_DARK) ||
1708 (board[x][y-1].colour == COLOUR_DARK)))
1709 return 1;
1710 else
1711 return 0;
1714 void find_adjacent(int x, int y, int* adj_x, int* adj_y, bool* full) {
1715 /* Finds adjacent squares, returning squares without tanks on them
1716 * in preference to those with them */
1717 if(((board[x-1][y].tank && (board[x-1][y].colour == COLOUR_DARK)) ||
1718 board[x-1][y].colour != COLOUR_DARK) &&
1719 ((board[x+1][y].tank && (board[x+1][y].colour == COLOUR_DARK)) ||
1720 board[x+1][y].colour != COLOUR_DARK) &&
1721 ((board[x][y-1].tank && (board[x][y-1].colour == COLOUR_DARK)) ||
1722 board[x][y-1].colour != COLOUR_DARK) &&
1723 ((board[x][y+1].tank && (board[x][y+1].colour == COLOUR_DARK)) ||
1724 board[x][y+1].colour != COLOUR_DARK)) {
1725 *full = true;
1726 } else {
1727 *full = false;
1730 if(board[x-1][y].colour == COLOUR_DARK) {
1731 *adj_x = x-1;
1732 *adj_y = y;
1733 if(board[x-1][y].tank) {
1734 if(*full)
1735 return;
1736 } else {
1737 return;
1740 if(board[x+1][y].colour == COLOUR_DARK) {
1741 *adj_x = x+1;
1742 *adj_y = y;
1743 if(board[x+1][y].tank) {
1744 if(*full)
1745 return;
1746 } else {
1747 return;
1750 if(board[x][y-1].colour == COLOUR_DARK) {
1751 *adj_x = x;
1752 *adj_y = y-1;
1753 if(board[x][y-1].tank) {
1754 if(*full)
1755 return;
1756 } else {
1757 return;
1760 if(board[x][y+1].colour == COLOUR_DARK) {
1761 *adj_x = x;
1762 *adj_y = y+1;
1763 if(board[x][y+1].tank) {
1764 if(*full)
1765 return;
1766 } else {
1767 return;
1772 void computer_allocate(void) {
1773 /* Firstly, decide whether to go offensive or defensive.
1774 * This is primarily decided by the human player posing a threat to either
1775 * the computer's farms or factories */
1776 int i, j, k;
1777 bool offensive = true;
1778 struct threat threats[4];
1779 int numthreats = 0;
1780 int total_str_diff = 0;
1781 int men_needed;
1782 struct threat targets[2];
1783 int numtargets;
1784 struct cursor adj;
1785 bool full = false;
1786 for(i=1;i<12;i++) {
1787 for(j=1;j<12;j++) {
1788 if((board[i][j].colour == COLOUR_DARK) &&
1789 (calc_strength(COLOUR_DARK,i,j) <
1790 calc_strength(COLOUR_LIGHT,i,j))) {
1791 if(board[i][j].ind || board[i][j].farm) {
1792 if(numthreats < 3) {
1793 offensive = false;
1794 threats[numthreats].x = i;
1795 threats[numthreats].y = j;
1796 threats[numthreats].str_diff =
1797 calc_strength(COLOUR_LIGHT,i,j) -
1798 calc_strength(COLOUR_DARK,i,j);
1799 numthreats++;
1805 if(offensive) {
1806 /* The AI is going to go straight for the throat here and attack
1807 * the player's farms and factories. The amount of cash
1808 * the AI has to spend will determine how many targets there are */
1809 if(compres.cash > 1200) {
1810 /* 1200 is a figure I pulled out of nowhere. Adjust as needed */
1811 numtargets = 2;
1812 } else {
1813 numtargets = 1;
1815 /* Work out which target(s) to attack. They must have adjacent squares
1816 * owned by the computer. If none are found just place troops in
1817 * random places around the map until we run out of money */
1818 k = 0;
1819 while(k<numtargets) {
1820 for(i=1;i<12;i++) {
1821 for(j=1;j<12;j++) {
1822 if((board[i][j].colour == COLOUR_LIGHT) &&
1823 (board[i][j].ind || board[i][j].farm) &&
1824 has_adjacent(i,j)) {
1825 targets[k].x = i;
1826 targets[k].y = j;
1827 targets[k].str_diff = abs(calc_strength(COLOUR_LIGHT,
1828 i, j) - calc_strength(COLOUR_DARK,
1829 i, j));
1830 k++;
1835 if(k == 0) {
1836 /* No targets found! Randomly pick squares and if they're owned
1837 * by the computer then stick a tank on it. */
1838 rb->srand(*rb->current_tick);
1839 while(compres.cash >= 300) {
1840 i = rb->rand()%11 + 1;
1841 j = rb->rand()%11 + 1;
1842 if(board[i][j].colour == COLOUR_DARK) {
1843 if(compres.cash >= 300) {
1844 if(!board[i][j].tank) {
1845 board[i][j].tank = true;
1846 compres.tanks++;
1847 compres.cash -= 300;
1848 draw_board();
1849 rb->sleep(HZ);
1854 compres.bank += compres.cash;
1855 compres.cash = 0;
1856 } else {
1857 for(i=0;i<k;i++) {
1858 men_needed = targets[i].str_diff + 20;
1859 find_adjacent(targets[i].x,targets[i].y, &adj.x, &adj.y, &full);
1860 while(((calc_strength(COLOUR_LIGHT, targets[i].x, targets[i].y)
1861 + 20) > calc_strength(COLOUR_DARK, targets[i].x,
1862 targets[i].y)) && compres.cash > 0) {
1863 /* While we still need them keep placing men */
1864 if(compres.cash >= 300 && !full) {
1865 if(board[adj.x][adj.y].tank) {
1866 find_adjacent(targets[i].x, targets[i].y,
1867 &adj.x, &adj.y, &full);
1868 } else {
1869 board[adj.x][adj.y].tank = true;
1870 compres.tanks++;
1871 compres.cash -= 300;
1872 draw_board();
1873 rb->sleep(HZ);
1875 } else {
1876 men_needed = (calc_strength(COLOUR_LIGHT, targets[i].x,
1877 targets[i].y) + 20 -
1878 calc_strength(COLOUR_DARK, targets[i].x,
1879 targets[i].y))*1000/133;
1880 if(compres.cash >= men_needed) {
1881 board[adj.x][adj.y].men += men_needed;
1882 compres.men += men_needed;
1883 compres.cash -= men_needed;
1884 compres.bank += compres.cash;
1885 compres.cash = 0;
1886 } else {
1887 board[adj.x][adj.y].men += compres.cash;
1888 compres.men += compres.cash;
1889 compres.cash = 0;
1891 draw_board();
1892 rb->sleep(HZ);
1896 compres.bank += compres.cash;
1897 compres.cash = 0;
1899 } else {
1900 /* Work out what to place on each square to defend it.
1901 * Tanks are preferential because they do not require food,
1902 * but if the budget is tight then we fall back onto troops.
1903 * Conversely if cash is not an issue and there are already tanks in
1904 * place planes will be deployed. We would like a margin of at least
1905 * 20 points to be safe. */
1907 for(i=0;i<numthreats;i++) {
1908 total_str_diff += threats[i].str_diff;
1910 if((total_str_diff+20)*10 > compres.cash) {
1911 /* Not enough cash to accomodate all threats using tanks alone -
1912 * use men as a backup */
1913 for(i=0;i<numthreats;i++) {
1914 men_needed = ((threats[i].str_diff + 20)*1000)/133;
1915 if(compres.cash >= men_needed) {
1916 board[threats[i].x][threats[i].y].men += men_needed;
1917 compres.cash -= men_needed;
1918 compres.men += men_needed;
1919 draw_board();
1920 rb->sleep(HZ);
1921 } else {
1922 board[threats[i].x][threats[i].y].men += compres.cash;
1923 compres.men += compres.cash;
1924 compres.cash = 0;
1925 draw_board();
1926 rb->sleep(HZ);
1929 } else if((total_str_diff+20)*15 < compres.cash) {
1930 /* Enough money to pay their way by planes */
1931 for(i=0;i<numthreats;i++) {
1932 while(calc_strength(COLOUR_DARK,threats[i].x, threats[i].y) <
1933 (calc_strength(COLOUR_LIGHT,threats[i].x, threats[i].y) +
1934 20)) {
1935 if(board[threats[i].x][threats[i].y].plane) {
1936 if(place_adjacent(0, threats[i].x, threats[i].y)) {
1937 /* No room for any more planes, revert to men */
1938 men_needed = (calc_strength(COLOUR_LIGHT,
1939 threats[i].x, threats[i].y) + 20 -
1940 calc_strength(COLOUR_DARK,
1941 threats[i].x, threats[i].y)*1000/133);
1942 if(compres.cash >= men_needed) {
1943 compres.cash -= men_needed;
1944 compres.men += men_needed;
1945 board[threats[i].x][threats[i].y].men +=
1946 men_needed;
1947 draw_board();
1948 rb->sleep(HZ);
1951 } else {
1952 if(compres.cash >= 600) {
1953 board[threats[i].x][threats[i].y].plane = true;
1954 compres.cash -= 600;
1955 compres.planes++;
1956 draw_board();
1957 rb->sleep(HZ);
1962 } else {
1963 /* Tanks it is */
1964 for(i=0;i<numthreats;i++) {
1965 while(calc_strength(COLOUR_DARK,threats[i].x, threats[i].y) <
1966 (calc_strength(COLOUR_LIGHT,threats[i].x, threats[i].y) +
1967 20) && compres.cash > 0) {
1968 if(board[threats[i].x][threats[i].y].tank) {
1969 if(place_adjacent(1, threats[i].x, threats[i].y)) {
1970 /* No room for any more tanks, revert to men */
1971 men_needed = (calc_strength(COLOUR_LIGHT,
1972 threats[i].x, threats[i].y) + 20 -
1973 calc_strength(COLOUR_DARK,
1974 threats[i].x, threats[i].y)*1000/133);
1975 if(compres.cash >= men_needed) {
1976 compres.cash -= men_needed;
1977 compres.men += men_needed;
1978 board[threats[i].x][threats[i].y].men +=
1979 men_needed;
1980 draw_board();
1981 rb->sleep(HZ);
1984 } else {
1985 if(compres.cash >= 300) {
1986 board[threats[i].x][threats[i].y].tank = true;
1987 compres.tanks++;
1988 compres.cash -= 300;
1989 draw_board();
1990 rb->sleep(HZ);
1996 compres.bank += compres.cash;
1997 compres.cash = 0;
2001 int find_adj_target(int x, int y, struct cursor* adj) {
2002 /* Find a square next to a computer's farm or factory owned by the player
2003 * that is vulnerable. Return 1 on success, 0 otherwise */
2004 if(board[x+1][y].colour == COLOUR_LIGHT &&
2005 calc_strength(COLOUR_LIGHT,x+1,y)<=calc_strength(COLOUR_DARK,x+1,y)) {
2006 adj->x = x+1;
2007 adj->y = y;
2008 return 1;
2010 if(board[x-1][y].colour == COLOUR_LIGHT &&
2011 calc_strength(COLOUR_LIGHT,x-1,y)<=calc_strength(COLOUR_DARK,x-1,y)) {
2012 adj->x = x-1;
2013 adj->y = y;
2014 return 1;
2016 if(board[x][y+1].colour == COLOUR_LIGHT &&
2017 calc_strength(COLOUR_LIGHT,x,y+1)<=calc_strength(COLOUR_DARK,x,y+1)) {
2018 adj->x = x;
2019 adj->y = y+1;
2020 return 1;
2022 if(board[x][y-1].colour == COLOUR_LIGHT &&
2023 calc_strength(COLOUR_LIGHT,x,y-1)<=calc_strength(COLOUR_DARK,x,y-1)) {
2024 adj->x = x;
2025 adj->y = y-1;
2026 return 1;
2028 return 0;
2031 void computer_war(void) {
2032 /* Work out where to attack - prioritise the defence of buildings */
2033 int i, j;
2034 struct cursor adj;
2036 while(compres.moves) {
2037 for(i=1;i<12;i++) {
2038 for(j=1;j<12;j++) {
2039 if((board[i][j].colour == COLOUR_DARK) &&
2040 (board[i][j].farm || board[i][j].ind)) {
2041 if(find_adj_target(i, j, &adj) && compres.moves) {
2042 if(calc_strength(COLOUR_LIGHT, adj.x, adj.y) ==
2043 calc_strength(COLOUR_DARK, adj.x, adj.y)) {
2044 rb->srand(*rb->current_tick);
2045 if(rb->rand()%2) {
2046 board[adj.x][adj.y].colour = COLOUR_DARK;
2047 board[adj.x][adj.y].tank = false;
2048 board[adj.x][adj.y].plane = false;
2049 board[adj.x][adj.y].nuke = false;
2050 humanres.men -= board[adj.x][adj.y].men;
2051 board[adj.x][adj.y].men = 0;
2052 draw_board();
2053 rb->sleep(HZ);
2054 compres.moves--;
2055 } else {
2056 rb->splash(HZ*2, "The computer attempted"
2057 " to attack, but the"
2058 " invasion was pushed"
2059 " back");
2060 compres.moves--;
2062 } else {
2063 if(compres.moves) {
2064 board[adj.x][adj.y].colour = COLOUR_DARK;
2065 board[adj.x][adj.y].tank = false;
2066 board[adj.x][adj.y].plane = false;
2067 board[adj.x][adj.y].nuke = false;
2068 humanres.men -= board[adj.x][adj.y].men;
2069 board[adj.x][adj.y].men = 0;
2070 draw_board();
2071 rb->sleep(HZ);
2072 compres.moves--;
2079 if(compres.moves) {
2080 /* Defence stage done, move on to OFFENCE */
2081 for(i=1;i<12;i++) {
2082 for(j=1;j<12;j++) {
2083 if(board[i][j].colour == COLOUR_LIGHT && compres.moves &&
2084 (board[i][j].ind || board[i][j].farm) &&
2085 (calc_strength(COLOUR_DARK, i, j) >=
2086 calc_strength(COLOUR_LIGHT, i, j))) {
2087 if(calc_strength(COLOUR_DARK, i, j) ==
2088 calc_strength(COLOUR_LIGHT, i, j)) {
2089 if(rb->rand()%2) {
2090 board[i][j].colour = COLOUR_DARK;
2091 board[i][j].tank = false;
2092 board[i][j].plane = false;
2093 board[i][j].nuke = false;
2094 board[i][j].men = 0;
2095 draw_board();
2096 rb->sleep(HZ);
2097 compres.moves--;
2098 } else {
2099 rb->splash(HZ*2, "The computer attempted to "
2100 "attack, but the invasion was"
2101 " pushed back");
2102 compres.moves--;
2104 } else {
2105 board[i][j].colour = COLOUR_DARK;
2106 board[i][j].tank = false;
2107 board[i][j].plane = false;
2108 board[i][j].nuke = false;
2109 board[i][j].men = 0;
2110 draw_board();
2111 rb->sleep(HZ);
2112 compres.moves--;
2117 while(compres.moves > 0) {
2118 /* Spend leftover moves wherever attacking randomly */
2119 rb->srand(*rb->current_tick);
2120 i = (rb->rand()%10)+1;
2121 j = (rb->rand()%10)+1;
2122 if(board[i][j].colour == COLOUR_LIGHT &&
2123 (calc_strength(COLOUR_DARK, i, j) >=
2124 calc_strength(COLOUR_LIGHT, i, j))) {
2125 if(calc_strength(COLOUR_DARK, i, j) ==
2126 calc_strength(COLOUR_LIGHT, i, j)) {
2127 if(rb->rand()%2) {
2128 board[i][j].colour = COLOUR_DARK;
2129 board[i][j].tank = false;
2130 board[i][j].plane = false;
2131 board[i][j].nuke = false;
2132 board[i][j].men = 0;
2133 draw_board();
2134 rb->sleep(HZ);
2135 compres.moves--;
2136 } else {
2137 rb->splash(HZ*2, "The computer attempted to"
2138 " attack, but the invasion was"
2139 " pushed back");
2140 compres.moves--;
2142 } else {
2143 board[i][j].colour = COLOUR_DARK;
2144 board[i][j].tank = false;
2145 board[i][j].plane = false;
2146 board[i][j].nuke = false;
2147 board[i][j].men = 0;
2148 draw_board();
2149 rb->sleep(HZ);
2150 compres.moves--;
2158 static int load_game(const char* file) {
2159 int fd;
2161 fd = rb->open(file, O_RDONLY);
2162 if(fd == 0) {
2163 DEBUGF("Couldn't open savegame\n");
2164 return -1;
2166 rb->read(fd, buf, 5);
2167 if(rb->strcmp(buf, "SSGv2")) {
2168 rb->splash(HZ, "Invalid/incompatible savegame\n");
2169 return -1;
2171 rb->read(fd, &humanres.cash, sizeof(humanres.cash));
2172 rb->read(fd, &humanres.food, sizeof(humanres.food));
2173 rb->read(fd, &humanres.bank, sizeof(humanres.bank));
2174 rb->read(fd, &humanres.planes, sizeof(humanres.planes));
2175 rb->read(fd, &humanres.tanks, sizeof(humanres.tanks));
2176 rb->read(fd, &humanres.men, sizeof(humanres.men));
2177 rb->read(fd, &humanres.nukes, sizeof(humanres.nukes));
2178 rb->read(fd, &humanres.inds, sizeof(humanres.inds));
2179 rb->read(fd, &humanres.farms, sizeof(humanres.farms));
2180 rb->read(fd, &humanres.moves, sizeof(humanres.moves));
2181 rb->read(fd, &compres.cash, sizeof(humanres.cash));
2182 rb->read(fd, &compres.food, sizeof(humanres.food));
2183 rb->read(fd, &compres.bank, sizeof(humanres.bank));
2184 rb->read(fd, &compres.planes, sizeof(humanres.planes));
2185 rb->read(fd, &compres.tanks, sizeof(humanres.tanks));
2186 rb->read(fd, &compres.men, sizeof(humanres.men));
2187 rb->read(fd, &compres.nukes, sizeof(humanres.nukes));
2188 rb->read(fd, &compres.inds, sizeof(humanres.inds));
2189 rb->read(fd, &compres.farms, sizeof(humanres.farms));
2190 rb->read(fd, &compres.moves, sizeof(humanres.moves));
2191 rb->read(fd, board, sizeof(board));
2192 rb->read(fd, &superdom_settings.compstartfarms, sizeof(int));
2193 rb->read(fd, &superdom_settings.compstartinds, sizeof(int));
2194 rb->read(fd, &superdom_settings.humanstartfarms, sizeof(int));
2195 rb->read(fd, &superdom_settings.humanstartfarms, sizeof(int));
2196 rb->read(fd, &superdom_settings.startcash, sizeof(int));
2197 rb->read(fd, &superdom_settings.startfood, sizeof(int));
2198 rb->read(fd, &superdom_settings.movesperturn, sizeof(int));
2199 return 0;
2202 void default_settings(void) {
2203 superdom_settings.compstartfarms = 1;
2204 superdom_settings.compstartinds = 1;
2205 superdom_settings.humanstartfarms = 2;
2206 superdom_settings.humanstartinds = 2;
2207 superdom_settings.startcash = 0;
2208 superdom_settings.startfood = 0;
2209 superdom_settings.movesperturn = 2;
2212 int average_strength(bool colour) {
2213 /* This function calculates the average strength of the given player,
2214 * used to determine when the computer wins or loses. */
2215 int i,j;
2216 int totalpower = 0;
2217 for(i=0;i<12;i++) {
2218 for(j=0;j<12;j++) {
2219 if(board[i][j].colour != -1) {
2220 totalpower += calc_strength(colour, i, j);
2224 return totalpower/100;
2227 enum plugin_status plugin_start(const struct plugin_api* api, const void* parameter)
2229 int tempmenu;
2230 bool statusbar_setting;
2232 rb = api;
2234 #if LCD_DEPTH > 1
2235 rb->lcd_set_backdrop(NULL);
2236 rb->lcd_set_foreground(LCD_BLACK);
2237 rb->lcd_set_background(LCD_WHITE);
2238 #endif
2240 statusbar_setting = rb->global_settings->statusbar;
2241 rb->global_settings->statusbar = false;
2242 cursor.x = 1;
2243 cursor.y = 1;
2244 default_settings();
2245 if(parameter) {
2246 if(load_game(parameter) != 0) {
2247 DEBUGF("Loading failed, generating new game\n");
2248 init_resources();
2249 init_board();
2250 } else {
2251 goto startyear;
2253 } else {
2254 init_resources();
2255 init_board();
2258 bool play = false;
2259 while(!play) {
2260 switch(menu()) {
2261 case 0:
2262 play = true;
2263 break;
2264 case 2:
2265 rb->global_settings->statusbar = statusbar_setting;
2266 return PLUGIN_OK;
2267 break;
2270 gen_resources();
2271 startyear:
2272 if((average_strength(COLOUR_LIGHT) - average_strength(COLOUR_DARK)) > 15) {
2273 rb->splash(HZ*4, "The computer has surrendered. You win.");
2274 rb->global_settings->statusbar = statusbar_setting;
2275 return PLUGIN_OK;
2277 if((average_strength(COLOUR_DARK) - average_strength(COLOUR_LIGHT)) > 15) {
2278 rb->splash(HZ*4, "Your army have suffered terrible morale from the bleak prospects of winning. You lose");
2279 rb->global_settings->statusbar = statusbar_setting;
2280 return PLUGIN_OK;
2282 tempmenu = production_menu();
2283 switch(tempmenu) {
2284 case PLUGIN_USB_CONNECTED:
2285 rb->global_settings->statusbar = statusbar_setting;
2286 return PLUGIN_USB_CONNECTED;
2287 break;
2288 case SUPERDOM_QUIT:
2289 rb->global_settings->statusbar = statusbar_setting;
2290 return PLUGIN_OK;
2291 break;
2293 computer_allocate();
2294 humanres.moves += superdom_settings.movesperturn;
2295 tempmenu = movement_menu();
2296 switch(tempmenu) {
2297 case PLUGIN_USB_CONNECTED:
2298 rb->global_settings->statusbar = statusbar_setting;
2299 return PLUGIN_USB_CONNECTED;
2300 break;
2301 case SUPERDOM_QUIT:
2302 rb->global_settings->statusbar = statusbar_setting;
2303 return PLUGIN_OK;
2304 break;
2306 if(humanres.men) {
2307 if(humanres.food > humanres.men) {
2308 rb->snprintf(buf, sizeof(buf), "Your men ate %d units of food",
2309 humanres.men);
2310 humanres.food -= humanres.men;
2311 } else {
2312 rb->snprintf(buf, sizeof(buf), "There was not enough food to feed"
2313 " all your men, %d men have died of starvation",
2314 killmen(COLOUR_LIGHT));
2316 rb->splash(HZ*2, buf);
2318 if(compres.men) {
2319 if(compres.food < compres.men) {
2320 rb->snprintf(buf, sizeof(buf), "The computer does not have enough"
2321 " food to feed its men. %d have ided of starvation",
2322 killmen(COLOUR_DARK));
2323 rb->splash(HZ, buf);
2326 tempmenu = war_menu();
2327 switch(tempmenu) {
2328 case PLUGIN_USB_CONNECTED:
2329 rb->global_settings->statusbar = statusbar_setting;
2330 return PLUGIN_USB_CONNECTED;
2331 break;
2332 case SUPERDOM_QUIT:
2333 rb->global_settings->statusbar = statusbar_setting;
2334 return PLUGIN_OK;
2335 break;
2337 compres.moves += superdom_settings.movesperturn;
2338 computer_war();
2339 gen_resources();
2340 goto startyear;
2341 rb->global_settings->statusbar = statusbar_setting;
2342 return PLUGIN_OK;