use lib display text to display help messages (FS#10099).
[kugel-rb.git] / apps / plugins / superdom.c
blob1a44bad518fafcc1c407e9f9d1d4c45bc42a24a7
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 #include "lib/playback_control.h"
23 #include "lib/display_text.h"
24 PLUGIN_HEADER
26 extern const fb_data superdom_boarditems[];
27 char buf[255];
29 #define COLOUR_DARK 0
30 #define COLOUR_LIGHT 1
32 #define MARGIN 5
34 #if (LCD_DEPTH == 16)
35 #define MY_BITMAP_PART rb->lcd_bitmap_transparent_part
36 #else
37 #define MY_BITMAP_PART rb->lcd_mono_bitmap_part
38 #endif
40 #if LCD_WIDTH > LCD_HEIGHT
41 #define BOX_WIDTH ((LCD_WIDTH-(MARGIN*2))/10)
42 #define BOX_HEIGHT ((BOX_WIDTH*2)/3)
44 #else
45 #define BOX_HEIGHT ((LCD_HEIGHT-(MARGIN*2)-15)/10)
46 #define BOX_WIDTH ((BOX_HEIGHT*2)/3)
48 #endif
50 #if LCD_WIDTH == 220 && LCD_HEIGHT == 176
51 #define NUM_BOX_HEIGHT 25
52 #define NUM_BOX_WIDTH 30
53 #define STRIDE 14
54 #define ICON_HEIGHT 7
55 #define ICON_WIDTH 7
57 #elif (LCD_WIDTH == 160 && LCD_HEIGHT == 128) || \
58 (LCD_WIDTH == 176 && LCD_HEIGHT == 132) || \
59 (LCD_WIDTH == 176 && LCD_HEIGHT == 220)
60 #define NUM_BOX_HEIGHT 20
61 #define NUM_BOX_WIDTH 24
62 #define STRIDE 8
63 #define ICON_HEIGHT 4
64 #define ICON_WIDTH 4
66 #elif (LCD_WIDTH == 320 && LCD_HEIGHT == 240)
67 #define NUM_BOX_HEIGHT 25
68 #define NUM_BOX_WIDTH 30
69 #define STRIDE 20
70 #define ICON_HEIGHT 10
71 #define ICON_WIDTH 10
73 #elif (LCD_WIDTH == 240 && (LCD_HEIGHT == 320 || LCD_HEIGHT == 400))
74 #define NUM_BOX_HEIGHT 25
75 #define NUM_BOX_WIDTH 30
76 #define STRIDE 18
77 #define ICON_HEIGHT 9
78 #define ICON_WIDTH 9
80 #endif
82 #define NUM_MARGIN_X (LCD_WIDTH-3*NUM_BOX_WIDTH)/2
83 #define NUM_MARGIN_Y (LCD_HEIGHT-4*NUM_BOX_HEIGHT)/2
85 #if (CONFIG_KEYPAD == IPOD_4G_PAD) || (CONFIG_KEYPAD == IPOD_3G_PAD) || \
86 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
87 #define SUPERDOM_OK BUTTON_SELECT
88 #define SUPERDOM_CANCEL BUTTON_MENU
89 #define SUPERDOM_LEFT BUTTON_LEFT
90 #define SUPERDOM_RIGHT BUTTON_RIGHT
91 #define IPOD_STYLE
93 #elif CONFIG_KEYPAD == IRIVER_H300_PAD || CONFIG_KEYPAD == IRIVER_H100_PAD
94 #define SUPERDOM_OK BUTTON_SELECT
95 #define SUPERDOM_LEFT BUTTON_LEFT
96 #define SUPERDOM_RIGHT BUTTON_RIGHT
97 #define SUPERDOM_UP BUTTON_UP
98 #define SUPERDOM_DOWN BUTTON_DOWN
99 #define SUPERDOM_CANCEL BUTTON_OFF
101 #elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
102 #define SUPERDOM_OK BUTTON_SELECT
103 #define SUPERDOM_LEFT BUTTON_LEFT
104 #define SUPERDOM_RIGHT BUTTON_RIGHT
105 #define SUPERDOM_UP BUTTON_UP
106 #define SUPERDOM_DOWN BUTTON_DOWN
107 #define SUPERDOM_CANCEL BUTTON_REC
109 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
110 #define SUPERDOM_OK BUTTON_RIGHT
111 #define SUPERDOM_UP BUTTON_SCROLL_UP
112 #define SUPERDOM_DOWN BUTTON_SCROLL_DOWN
113 #define SUPERDOM_CANCEL BUTTON_LEFT
115 #elif CONFIG_KEYPAD == GIGABEAT_PAD
116 #define SUPERDOM_OK BUTTON_SELECT
117 #define SUPERDOM_UP BUTTON_UP
118 #define SUPERDOM_DOWN BUTTON_DOWN
119 #define SUPERDOM_LEFT BUTTON_LEFT
120 #define SUPERDOM_RIGHT BUTTON_RIGHT
121 #define SUPERDOM_CANCEL BUTTON_POWER
123 #elif CONFIG_KEYPAD == SANSA_E200_PAD
124 #define SUPERDOM_OK BUTTON_SELECT
125 #define SUPERDOM_UP BUTTON_SCROLL_BACK
126 #define SUPERDOM_DOWN BUTTON_SCROLL_FWD
127 #define SUPERDOM_LEFT BUTTON_LEFT
128 #define SUPERDOM_RIGHT BUTTON_RIGHT
129 #define SUPERDOM_CANCEL BUTTON_POWER
131 #elif CONFIG_KEYPAD == SANSA_FUZE_PAD
132 #define SUPERDOM_OK BUTTON_SELECT
133 #define SUPERDOM_UP BUTTON_SCROLL_BACK
134 #define SUPERDOM_DOWN BUTTON_SCROLL_FWD
135 #define SUPERDOM_LEFT BUTTON_LEFT
136 #define SUPERDOM_RIGHT BUTTON_RIGHT
137 #define SUPERDOM_CANCEL (BUTTON_HOME|BUTTON_REPEAT)
139 #elif CONFIG_KEYPAD == GIGABEAT_S_PAD
140 #define SUPERDOM_OK BUTTON_SELECT
141 #define SUPERDOM_UP BUTTON_UP
142 #define SUPERDOM_DOWN BUTTON_DOWN
143 #define SUPERDOM_LEFT BUTTON_LEFT
144 #define SUPERDOM_RIGHT BUTTON_RIGHT
145 #define SUPERDOM_CANCEL BUTTON_BACK
147 #elif CONFIG_KEYPAD == COWOND2_PAD
148 #define SUPERDOM_CANCEL BUTTON_POWER
150 #elif CONFIG_KEYPAD == CREATIVEZVM_PAD
151 #define SUPERDOM_OK BUTTON_SELECT
152 #define SUPERDOM_UP BUTTON_UP
153 #define SUPERDOM_DOWN BUTTON_DOWN
154 #define SUPERDOM_LEFT BUTTON_LEFT
155 #define SUPERDOM_RIGHT BUTTON_RIGHT
156 #define SUPERDOM_CANCEL BUTTON_BACK
158 #elif CONFIG_KEYPAD == ONDAVX747_PAD
159 #define SUPERDOM_CANCEL BUTTON_POWER
161 #endif
163 #ifdef HAVE_TOUCHSCREEN
164 #ifndef SUPERDOM_OK
165 #define SUPERDOM_OK BUTTON_CENTER
166 #endif
167 #ifndef SUPERDOM_UP
168 #define SUPERDOM_UP BUTTON_TOPMIDDLE
169 #endif
170 #ifndef SUPERDOM_LEFT
171 #define SUPERDOM_LEFT BUTTON_MIDLEFT
172 #endif
173 #ifndef SUPERDOM_RIGHT
174 #define SUPERDOM_RIGHT BUTTON_MIDRIGHT
175 #endif
176 #ifndef SUPERDOM_DOWN
177 #define SUPERDOM_DOWN BUTTON_BOTTOMMIDDLE
178 #endif
179 #ifndef SUPERDOM_CANCEL
180 #define SUPERDOM_CANCEL BUTTON_TOPLEFT
181 #endif
182 #endif
184 #define SUPERDOM_QUIT 23
186 void gen_interest(void);
187 int production_menu(void);
188 void init_resources(void);
189 int select_square(void);
190 void update_score(void);
191 void gen_resources(void);
192 void draw_cursor(void);
193 int calc_strength(int colour, int x, int y);
194 void draw_board(void);
196 struct tile{
197 signed int colour; /* -1 = Unset */
198 bool tank;
199 bool plane;
200 bool nuke;
201 bool ind;
202 bool farm;
203 int men;
206 struct resources {
207 int cash;
208 int food;
209 int farms;
210 int inds;
211 int men;
212 int tanks;
213 int planes;
214 int nukes;
215 int bank;
216 int moves;
219 struct settings {
220 int compstartfarms;
221 int compstartinds;
222 int humanstartfarms;
223 int humanstartinds;
224 int startcash;
225 int startfood;
226 int movesperturn;
227 } superdom_settings;
229 struct resources humanres;
230 struct resources compres;
231 enum { GS_PROD, GS_MOVE, GS_WAR } gamestate;
233 struct cursor{
234 int x;
235 int y;
236 } cursor;
238 struct tile board[12][12];
240 void init_board(void) {
241 int i,j;
242 rb->srand(*rb->current_tick);
243 for(i=0;i<12;i++) { /* Hopefully about 50% each colour */
244 for(j=0;j<12;j++) {
245 if((i<1)||(j<1)||(i>10)||(j>10))
246 board[i][j].colour = -1; /* Unset */
247 else
248 board[i][j].colour = rb->rand()%2;
249 board[i][j].tank = false;
250 board[i][j].plane = false;
251 board[i][j].nuke = false;
252 board[i][j].ind = false;
253 board[i][j].farm = false;
254 board[i][j].men = 0;
258 while(compres.farms < superdom_settings.compstartfarms) {
259 i = rb->rand()%10 + 1;
260 j = rb->rand()%10 + 1;
261 if((board[i][j].colour == COLOUR_DARK) && (board[i][j].farm == false)) {
262 board[i][j].farm = true;
263 compres.farms++;
266 while(compres.inds < superdom_settings.compstartinds) {
267 i = rb->rand()%10 + 1;
268 j = rb->rand()%10 + 1;
269 if((board[i][j].colour == COLOUR_DARK) && (board[i][j].ind == false)) {
270 board[i][j].ind = true;
271 compres.inds++;
274 while(humanres.farms<superdom_settings.humanstartfarms) {
275 i = rb->rand()%10 + 1;
276 j = rb->rand()%10 + 1;
277 if((board[i][j].colour == COLOUR_LIGHT)&&(board[i][j].farm == false)) {
278 board[i][j].farm = true;
279 humanres.farms++;
282 while(humanres.inds<superdom_settings.humanstartfarms) {
283 i = rb->rand()%10 + 1;
284 j = rb->rand()%10 + 1;
285 if((board[i][j].colour == COLOUR_LIGHT) && (board[i][j].ind == false)) {
286 board[i][j].ind = true;
287 humanres.inds++;
292 void draw_board(void) {
293 int i,j;
294 rb->lcd_clear_display();
295 for(i=1;i<11;i++) {
296 for(j=1;j<11;j++) {
297 if(board[i][j].colour == COLOUR_DARK) {
298 rb->lcd_set_foreground(LCD_DARKGRAY);
299 } else {
300 rb->lcd_set_foreground(LCD_LIGHTGRAY);
302 rb->lcd_fillrect(MARGIN+(BOX_WIDTH*(i-1)),
303 MARGIN+(BOX_HEIGHT*(j-1)), BOX_WIDTH,
304 BOX_HEIGHT);
305 #if LCD_DEPTH != 16
306 rb->lcd_set_drawmode(DRMODE_BG | DRMODE_INVERSEVID);
307 #endif
308 if(board[i][j].ind) {
309 MY_BITMAP_PART(superdom_boarditems,
310 board[i][j].colour?ICON_WIDTH:0, 0, STRIDE,
311 #if LCD_WIDTH > LCD_HEIGHT
312 MARGIN+(BOX_WIDTH*(i-1))+1,
313 MARGIN+(BOX_HEIGHT*(j-1))+ICON_HEIGHT+1,
314 #else
315 MARGIN+(BOX_WIDTH*(i-1))+1+ICON_WIDTH,
316 MARGIN+(BOX_HEIGHT*(j-1))+1,
317 #endif
318 ICON_WIDTH, ICON_HEIGHT);
320 if(board[i][j].farm) {
321 MY_BITMAP_PART(superdom_boarditems,
322 board[i][j].colour?ICON_WIDTH:0, ICON_HEIGHT,
323 STRIDE, MARGIN+(BOX_WIDTH*(i-1))+1,
324 MARGIN+(BOX_HEIGHT*(j-1))+1,
325 ICON_WIDTH, ICON_HEIGHT);
327 if(board[i][j].tank) {
328 MY_BITMAP_PART(superdom_boarditems,
329 board[i][j].colour?ICON_WIDTH:0, ICON_HEIGHT*2,
330 STRIDE, MARGIN+(BOX_WIDTH*(i-1))+ICON_WIDTH+1,
331 MARGIN+(BOX_HEIGHT*(j-1))+ICON_HEIGHT+1,
332 ICON_WIDTH, ICON_HEIGHT);
334 if(board[i][j].men) {
335 MY_BITMAP_PART(superdom_boarditems,
336 board[i][j].colour?ICON_WIDTH:0, ICON_HEIGHT*3,
337 #if LCD_WIDTH > LCD_HEIGHT
338 STRIDE, MARGIN+(BOX_WIDTH*(i-1))+ICON_WIDTH+1,
339 MARGIN+(BOX_HEIGHT*(j-1))+1,
340 #else
341 STRIDE, MARGIN+(BOX_WIDTH*(i-1))+1,
342 MARGIN+(BOX_HEIGHT*(j-1))+1+ICON_HEIGHT,
343 #endif
344 ICON_WIDTH, ICON_HEIGHT);
346 if(board[i][j].plane) {
347 MY_BITMAP_PART(superdom_boarditems,
348 board[i][j].colour?ICON_WIDTH:0, ICON_HEIGHT*4,
349 #if LCD_WIDTH > LCD_HEIGHT
350 STRIDE,MARGIN+(BOX_WIDTH*(i-1))+ICON_WIDTH*2+1,
351 MARGIN+(BOX_HEIGHT*(j-1))+ICON_HEIGHT+1,
352 #else
353 STRIDE,MARGIN+(BOX_WIDTH*(i-1))+ICON_WIDTH+1,
354 MARGIN+(BOX_HEIGHT*(j-1))+ICON_HEIGHT*2+1,
355 #endif
356 ICON_WIDTH, ICON_HEIGHT);
358 if(board[i][j].nuke) {
359 MY_BITMAP_PART(superdom_boarditems,
360 board[i][j].colour?ICON_WIDTH:0, ICON_HEIGHT*5,
361 #if LCD_WIDTH > LCD_HEIGHT
362 STRIDE,MARGIN+(BOX_WIDTH*(i-1))+ICON_WIDTH*2+1,
363 MARGIN+(BOX_HEIGHT*(j-1))+1,
364 #else
365 STRIDE,MARGIN+(BOX_WIDTH*(i-1))+1,
366 MARGIN+(BOX_HEIGHT*(j-1))+ICON_HEIGHT*2+1,
367 #endif
368 ICON_WIDTH, ICON_HEIGHT);
370 #if LCD_DEPTH != 16
371 rb->lcd_set_drawmode(DRMODE_SOLID);
372 #endif
375 rb->lcd_set_foreground(LCD_BLACK);
376 for(i=0;i<=10;i++) { /* Draw Horizontal lines */
377 rb->lcd_hline(MARGIN, MARGIN+(BOX_WIDTH*10), MARGIN+(BOX_HEIGHT*i));
379 for(i=0;i<=10;i++) { /* Draw Vertical lines */
380 rb->lcd_vline(MARGIN+(BOX_WIDTH*i), MARGIN, MARGIN+(BOX_HEIGHT*10));
382 rb->lcd_update();
385 int calc_strength(int colour, int x, int y) {
386 int a, b, score=0;
387 for (a = -1; a < 2; a++) {
388 for (b = -1; b < 2; b++) {
389 if ((b == 0 || a == 0) &&
390 (board[x + a][y + b].colour == colour)) {
391 score += 10;
392 if(board[x + a][y + b].tank || board[x + a][y + b].farm)
393 score += 30;
394 if(board[x + a][y + b].plane || board[x + a][y + b].ind)
395 score += 40;
396 if(board[x + a][y + b].nuke)
397 score += 20;
398 if(board[x + a][y + b].men)
399 score += (board[x + a][y + b].men*133/1000);
403 return score;
406 void gen_interest(void) {
407 /* Interest should be around 10% */
408 rb->srand(*rb->current_tick);
409 int interest = 7+rb->rand()%6;
410 humanres.bank = humanres.bank+(interest*humanres.bank/100);
411 compres.bank = compres.bank+(interest*compres.bank/100);
414 void draw_cursor(void) {
415 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
416 rb->lcd_fillrect(MARGIN+((cursor.x-1)*BOX_WIDTH),
417 MARGIN+((cursor.y-1)*BOX_HEIGHT), BOX_WIDTH+1, BOX_HEIGHT+1);
418 rb->lcd_set_drawmode(DRMODE_SOLID);
419 rb->lcd_update();
422 void gen_resources(void) {
423 int inccash = 0;
424 int incfood = 0;
425 int ratecash = 0;
426 int ratefood = 0;
427 int i;
428 gen_interest();
429 rb->srand(*rb->current_tick);
430 /* Generate Human's resources */
431 for(i=0;i<humanres.inds;i++) {
432 inccash += (300+rb->rand()%200);
434 for(i=0;i<humanres.farms;i++) {
435 incfood += (200+rb->rand()%200);
437 if(humanres.inds)
438 ratecash = inccash/humanres.inds;
439 if(humanres.farms)
440 ratefood = incfood/humanres.farms;
441 if(ratecash > 450) {
442 if(ratefood > 350) {
443 rb->splash(HZ*2, "Patriotism sweeps the land, all production"
444 " is up this year!");
445 } else {
446 rb->splash(HZ*2, "Factories working at maximum efficiency,"
447 " cash production up this year!");
449 } else if(ratecash > 350) {
450 if(ratefood > 350) {
451 rb->splash(HZ*2, "Record crop harvest this year!");
452 } else if(ratefood > 250) {
453 rb->splash(HZ*2, "Production continues as normal");
454 } else {
455 rb->splash(HZ*2, "Spoilage of crops leads to reduced farm"
456 " output this year");
458 } else {
459 if(ratefood > 350) {
460 rb->splash(HZ*2, "Record crop harvest this year!");
461 } else if(ratefood > 250) {
462 rb->splash(HZ*2, "Factory unions introduced. Industrial"
463 " production is down this year.");
464 } else {
465 rb->splash(HZ*2, "Internet created. All production is down"
466 " due to time wasted.");
469 humanres.cash += inccash;
470 humanres.food += incfood;
472 /* Generate Computer's resources */
473 inccash = 0;
474 incfood = 0;
475 for(i=0;i<compres.inds;i++) {
476 inccash += (300+rb->rand()%200);
478 for(i=0;i<compres.farms;i++) {
479 incfood += (200+rb->rand()%200);
481 compres.cash += inccash;
482 compres.food += incfood;
485 void update_score(void) {
486 int strength;
487 rb->lcd_setfont(FONT_SYSFIXED);
488 rb->lcd_set_drawmode(DRMODE_BG|DRMODE_INVERSEVID);
489 rb->lcd_fillrect(5,LCD_HEIGHT-20,105,20);
490 rb->lcd_set_drawmode(DRMODE_SOLID);
491 strength = calc_strength(COLOUR_LIGHT, cursor.x, cursor.y);
492 rb->snprintf(buf, sizeof(buf), "Your power: %d.%d",
493 strength/10, strength%10);
494 rb->lcd_putsxy(5,LCD_HEIGHT-20, buf);
495 strength = calc_strength(COLOUR_DARK, cursor.x, cursor.y);
496 rb->snprintf(buf, sizeof(buf), "Comp power: %d.%d",
497 strength/10, strength%10);
498 rb->lcd_putsxy(5,LCD_HEIGHT-10, buf);
499 rb->lcd_setfont(FONT_UI);
502 int settings_menu_function(void) {
503 int selection = 0;
505 MENUITEM_STRINGLIST(settings_menu,"Super Domination Settings",NULL,
506 "Computer starting farms","Computer starting factories",
507 "Human starting farms","Human starting factories",
508 "Starting cash","Starting food","Moves per turn");
510 while(1) {
511 selection=rb->do_menu(&settings_menu,&selection, NULL, false);
512 switch(selection) {
513 case 0:
514 rb->set_int("Computer starting farms", "", UNIT_INT,
515 &superdom_settings.compstartfarms, NULL,
516 1, 0, 5, NULL);
517 break;
518 case 1:
519 rb->set_int("Computer starting factories", "", UNIT_INT,
520 &superdom_settings.compstartinds, NULL,
521 1, 0, 5, NULL);
522 break;
523 case 2:
524 rb->set_int("Human starting farms", "", UNIT_INT,
525 &superdom_settings.humanstartfarms, NULL,
526 1, 0, 5, NULL);
527 break;
528 case 3:
529 rb->set_int("Human starting factories", "", UNIT_INT,
530 &superdom_settings.humanstartinds, NULL,
531 1, 0, 5, NULL);
532 break;
533 case 4:
534 rb->set_int("Starting cash", "", UNIT_INT,
535 &superdom_settings.startcash, NULL,
536 250, 0, 5000, NULL);
537 break;
538 case 5:
539 rb->set_int("Starting food", "", UNIT_INT,
540 &superdom_settings.startfood, NULL,
541 250, 0, 5000, NULL);
542 break;
543 case 6:
544 rb->set_int("Moves per turn", "", UNIT_INT,
545 &superdom_settings.movesperturn, NULL,
546 1, 1, 5, NULL);
547 break;
548 case MENU_ATTACHED_USB:
549 return PLUGIN_USB_CONNECTED;
550 break;
551 case GO_TO_PREVIOUS:
552 return 0;
553 break;
556 return 0;
559 static int do_help(void) {
560 int button;
561 #define WORDS (sizeof help_text / sizeof (char*))
562 static char* help_text[] = {
563 "Super", "domination", "is", "a", "turn", "based", "strategy", "game,",
564 "where", "the", "aim", "is", "to", "overpower", "the", "computer",
565 "player", "by", "taking", "their", "territory.", "",
566 "Each", "year", "you", "are", "allocated", "an", "amount", "of", "cash",
567 "and", "food,", "depending", "on", "how", "many", "farms", "and",
568 "factories", "you", "control.", "",
569 "Use", "this", "cash", "and", "food", "to", "buy", "and", "feed", "your",
570 "army.", "Each", "tile", "has", "a", "strength,", "calculated", "by",
571 "the", "ownership", "of", "adjacent", "tiles,", "and", "the", "type",
572 "and", "number", "of", "troops", "on", "them.",
575 if (display_text(WORDS, help_text, NULL, NULL))
576 return PLUGIN_USB_CONNECTED;
577 do {
578 button = rb->button_get(true);
579 if ( rb->default_event_handler( button ) == SYS_USB_CONNECTED )
580 return PLUGIN_USB_CONNECTED;
581 } while( ( button == BUTTON_NONE )
582 || ( button & (BUTTON_REL|BUTTON_REPEAT) ) );
584 return PLUGIN_OK;
587 int menu(void) {
588 int selection = 0;
590 MENUITEM_STRINGLIST(main_menu,"Super Domination Menu",NULL,
591 "Play Super Domination","Settings","Help","Quit");
593 while(1) {
594 selection=rb->do_menu(&main_menu,&selection, NULL, false);
595 switch(selection) {
596 case 0:
597 return 0; /* start playing */
598 break;
599 case 1:
600 if(settings_menu_function()==PLUGIN_USB_CONNECTED)
601 return PLUGIN_USB_CONNECTED;
602 break;
603 case 2:
604 if(do_help()==PLUGIN_USB_CONNECTED)
605 return PLUGIN_USB_CONNECTED;
606 break;
607 default:
608 return 2; /* quit program */
609 break;
613 return 3;
616 int save_game(void) {
617 int fd;
618 char savepath[MAX_PATH];
620 rb->snprintf(savepath, sizeof(savepath), "/Savegame.ssg");
621 if(rb->kbd_input(savepath, MAX_PATH)) {
622 DEBUGF("Keyboard input failed\n");
623 return -1;
626 fd = rb->open(savepath, O_WRONLY|O_CREAT);
627 DEBUGF("savepath: %s\n", savepath);
628 if(fd < 0) {
629 DEBUGF("Couldn't create/open file\n");
630 return -1;
633 rb->write(fd, "SSGv3", 5);
634 rb->write(fd, &gamestate, sizeof(gamestate));
635 rb->write(fd, &humanres.cash, sizeof(humanres.cash));
636 rb->write(fd, &humanres.food, sizeof(humanres.food));
637 rb->write(fd, &humanres.bank, sizeof(humanres.bank));
638 rb->write(fd, &humanres.planes, sizeof(humanres.planes));
639 rb->write(fd, &humanres.tanks, sizeof(humanres.tanks));
640 rb->write(fd, &humanres.men, sizeof(humanres.men));
641 rb->write(fd, &humanres.nukes, sizeof(humanres.nukes));
642 rb->write(fd, &humanres.inds, sizeof(humanres.inds));
643 rb->write(fd, &humanres.farms, sizeof(humanres.farms));
644 rb->write(fd, &humanres.moves, sizeof(humanres.moves));
645 rb->write(fd, &compres.cash, sizeof(compres.cash));
646 rb->write(fd, &compres.food, sizeof(compres.food));
647 rb->write(fd, &compres.bank, sizeof(compres.bank));
648 rb->write(fd, &compres.planes, sizeof(compres.planes));
649 rb->write(fd, &compres.tanks, sizeof(compres.tanks));
650 rb->write(fd, &compres.men, sizeof(compres.men));
651 rb->write(fd, &compres.nukes, sizeof(compres.nukes));
652 rb->write(fd, &compres.inds, sizeof(compres.inds));
653 rb->write(fd, &compres.farms, sizeof(compres.farms));
654 rb->write(fd, &compres.moves, sizeof(compres.moves));
655 rb->write(fd, board, sizeof(board));
656 rb->write(fd, &superdom_settings.compstartfarms, sizeof(int));
657 rb->write(fd, &superdom_settings.compstartinds, sizeof(int));
658 rb->write(fd, &superdom_settings.humanstartfarms, sizeof(int));
659 rb->write(fd, &superdom_settings.humanstartfarms, sizeof(int));
660 rb->write(fd, &superdom_settings.startcash, sizeof(int));
661 rb->write(fd, &superdom_settings.startfood, sizeof(int));
662 rb->write(fd, &superdom_settings.movesperturn, sizeof(int));
663 rb->close(fd);
664 return 0;
667 int ingame_menu(void) {
668 int selection = 0;
670 MENUITEM_STRINGLIST(ingame_menu,"Super Domination Menu",NULL,
671 "Return to game","Save Game","Playback Control", "Quit");
673 selection=rb->do_menu(&ingame_menu,&selection, NULL, false);
674 switch(selection) {
675 case 0:
676 return 0;
677 break;
678 case 1:
679 if(!save_game())
680 rb->splash(HZ, "Game saved");
681 else
682 rb->splash(HZ, "Error in save");
683 break;
684 case 2:
685 playback_control(NULL);
686 break;
687 case 3:
688 return SUPERDOM_QUIT;
689 break;
690 case MENU_ATTACHED_USB:
691 return PLUGIN_USB_CONNECTED;
692 break;
693 case GO_TO_PREVIOUS:
694 return 0;
695 break;
697 return 0;
700 int get_number(char* param, int* value) {
701 //int numbers[3][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
702 int numbers[3][3];
703 int i,j,x=0,y=0;
704 int height, width;
705 int button = 0;
706 numbers[0][0] = 1;
707 numbers[0][1] = 2;
708 numbers[0][2] = 3;
709 numbers[1][0] = 4;
710 numbers[1][1] = 5;
711 numbers[1][2] = 6;
712 numbers[2][0] = 7;
713 numbers[2][1] = 8;
714 numbers[2][2] = 9;
715 rb->lcd_clear_display();
716 /* Draw a 3x4 grid */
717 for(i=0;i<=3;i++) { /* Vertical lines */
718 rb->lcd_vline(NUM_MARGIN_X+(NUM_BOX_WIDTH*i), NUM_MARGIN_Y,
719 NUM_MARGIN_Y+(4*NUM_BOX_HEIGHT));
721 for(i=0;i<=4;i++) { /* Horizontal lines */
722 rb->lcd_hline(NUM_MARGIN_X, NUM_MARGIN_X+(3*NUM_BOX_WIDTH),
723 NUM_MARGIN_Y+(NUM_BOX_HEIGHT*i));
725 for(i=0;i<3;i++) {
726 for(j=0;j<3;j++) {
727 rb->snprintf(buf, sizeof(buf), "%d", numbers[i][j]);
728 rb->lcd_putsxy(NUM_MARGIN_X+(j*NUM_BOX_WIDTH)+10,
729 NUM_MARGIN_Y+(i*NUM_BOX_HEIGHT)+8, buf);
732 rb->lcd_putsxy(NUM_MARGIN_X+5, NUM_MARGIN_Y+(3*NUM_BOX_HEIGHT)+8, "CLR");
733 rb->lcd_putsxy(NUM_MARGIN_X+NUM_BOX_WIDTH+10,
734 NUM_MARGIN_Y+(3*NUM_BOX_HEIGHT)+8, "0");
735 rb->lcd_putsxy(NUM_MARGIN_X+2*NUM_BOX_WIDTH+8,
736 NUM_MARGIN_Y+(3*NUM_BOX_HEIGHT)+8, "OK");
737 rb->snprintf(buf,sizeof(buf), "%d", *value);
738 rb->lcd_putsxy(NUM_MARGIN_X+10, NUM_MARGIN_Y+4*NUM_BOX_HEIGHT+10, buf);
739 rb->lcd_getstringsize(param, &width, &height);
740 rb->lcd_putsxy((LCD_WIDTH-width)/2, (NUM_MARGIN_Y-height)/2, param);
741 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
742 rb->lcd_fillrect(NUM_MARGIN_X+(NUM_BOX_WIDTH*x),
743 NUM_MARGIN_Y+(NUM_BOX_HEIGHT*y), NUM_BOX_WIDTH+1,
744 NUM_BOX_HEIGHT+1);
745 rb->lcd_set_drawmode(DRMODE_SOLID);
746 rb->lcd_update();
747 while(1) {
748 button = rb->button_get(true);
749 switch(button) {
750 case SUPERDOM_OK:
751 if(y!=3) {
752 *value *= 10;
753 *value += numbers[y][x];
754 } else if(x==0) {
755 *value /= 10;
756 } else if(x==1) {
757 *value *= 10;
758 } else if(x==2) {
759 return 0;
761 rb->lcd_set_drawmode(DRMODE_BG|DRMODE_INVERSEVID);
762 rb->lcd_fillrect(0, NUM_MARGIN_Y+4*NUM_BOX_HEIGHT+10,
763 LCD_WIDTH, 30);
764 rb->lcd_set_drawmode(DRMODE_SOLID);
765 rb->snprintf(buf,sizeof(buf), "%d", *value);
766 rb->lcd_putsxy(NUM_MARGIN_X+10,
767 NUM_MARGIN_Y+4*NUM_BOX_HEIGHT+10, buf);
768 break;
769 case SUPERDOM_CANCEL:
770 *value = 0;
771 rb->splash(HZ, "Cancelled");
772 return 2;
773 break;
774 #if CONFIG_KEYPAD != IRIVER_H10_PAD
775 case SUPERDOM_LEFT:
776 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
777 rb->lcd_fillrect(NUM_MARGIN_X+(NUM_BOX_WIDTH*x),
778 NUM_MARGIN_Y+(NUM_BOX_HEIGHT*y),
779 NUM_BOX_WIDTH+1, NUM_BOX_HEIGHT+1);
780 rb->lcd_set_drawmode(DRMODE_SOLID);
781 if(x==0) {
782 #ifdef IPOD_STYLE
783 if(y>0)
784 y--;
785 else
786 y=3;
787 #endif
788 x=2;
789 } else {
790 x--;
792 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
793 rb->lcd_fillrect(NUM_MARGIN_X+(NUM_BOX_WIDTH*x),
794 NUM_MARGIN_Y+(NUM_BOX_HEIGHT*y),
795 NUM_BOX_WIDTH+1, NUM_BOX_HEIGHT+1);
796 rb->lcd_set_drawmode(DRMODE_SOLID);
797 break;
798 case SUPERDOM_RIGHT:
799 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
800 rb->lcd_fillrect(NUM_MARGIN_X+(NUM_BOX_WIDTH*x),
801 NUM_MARGIN_Y+(NUM_BOX_HEIGHT*y),
802 NUM_BOX_WIDTH+1, NUM_BOX_HEIGHT+1);
803 rb->lcd_set_drawmode(DRMODE_SOLID);
804 if(x==2) {
805 #ifdef IPOD_STYLE
806 if(y==3)
807 y=0;
808 else
809 y++;
810 #endif
811 x=0;
812 } else {
813 x++;
815 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
816 rb->lcd_fillrect(NUM_MARGIN_X+(NUM_BOX_WIDTH*x),
817 NUM_MARGIN_Y+(NUM_BOX_HEIGHT*y),
818 NUM_BOX_WIDTH+1, NUM_BOX_HEIGHT+1);
819 rb->lcd_set_drawmode(DRMODE_SOLID);
820 break;
821 #endif
822 #ifndef IPOD_STYLE
823 case SUPERDOM_UP:
824 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
825 rb->lcd_fillrect(NUM_MARGIN_X+(NUM_BOX_WIDTH*x),
826 NUM_MARGIN_Y+(NUM_BOX_HEIGHT*y),
827 NUM_BOX_WIDTH+1, NUM_BOX_HEIGHT+1);
828 rb->lcd_set_drawmode(DRMODE_SOLID);
829 if(y==0) {
830 #if CONFIG_KEYPAD == IRIVER_H10_PAD
831 if(x > 0)
832 x--;
833 else
834 x=2;
835 #endif
836 y=3;
837 } else {
838 y--;
840 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
841 rb->lcd_fillrect(NUM_MARGIN_X+(NUM_BOX_WIDTH*x),
842 NUM_MARGIN_Y+(NUM_BOX_HEIGHT*y),
843 NUM_BOX_WIDTH+1, NUM_BOX_HEIGHT+1);
844 rb->lcd_set_drawmode(DRMODE_SOLID);
845 break;
846 case SUPERDOM_DOWN:
847 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
848 rb->lcd_fillrect(NUM_MARGIN_X+(NUM_BOX_WIDTH*x),
849 NUM_MARGIN_Y+(NUM_BOX_HEIGHT*y),
850 NUM_BOX_WIDTH+1, NUM_BOX_HEIGHT+1);
851 rb->lcd_set_drawmode(DRMODE_SOLID);
852 if(y==3) {
853 #if CONFIG_KEYPAD == IRIVER_H10_PAD
854 if(x < 2)
855 x++;
856 else
857 x=0;
858 #endif
859 y=0;
860 } else {
861 y++;
863 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
864 rb->lcd_fillrect(NUM_MARGIN_X+(NUM_BOX_WIDTH*x),
865 NUM_MARGIN_Y+(NUM_BOX_HEIGHT*y),
866 NUM_BOX_WIDTH+1, NUM_BOX_HEIGHT+1);
867 rb->lcd_set_drawmode(DRMODE_SOLID);
868 break;
869 #endif
870 default:
871 if (rb->default_event_handler(button) == SYS_USB_CONNECTED)
873 return PLUGIN_USB_CONNECTED;
875 break;
877 rb->lcd_update();
879 return 0;
882 bool tile_has_item(int type, int x, int y) {
883 switch(type) {
884 case 0:
885 return (board[x][y].men > 0);
886 break;
887 case 1:
888 return board[x][y].tank;
889 break;
890 case 2:
891 return board[x][y].plane;
892 break;
893 case 3:
894 return board[x][y].farm;
895 break;
896 case 4:
897 return board[x][y].ind;
898 break;
899 case 5:
900 return board[x][y].nuke;
901 break;
903 return false;
906 int buy_resources(int colour, int type, int x, int y, int nummen) {
907 const char *itemnames[][6] = {
909 "them",
910 "the tank",
911 "the plane",
912 "the farm",
913 "the industrial plant",
914 "the nuke",
915 }, {
916 "place men",
917 "place a tank",
918 "place a plane",
919 "build a farm",
920 "build an industrial plant",
921 "place a nuke",
922 }, {
923 NULL,
924 "a tank",
925 "a plane",
926 "a farm",
927 "an industrial plant",
928 "a nuke",
932 bool human = (colour == COLOUR_LIGHT);
933 int price = 0;
934 struct resources *res;
936 if(human) {
937 res = &humanres;
938 } else {
939 res = &compres;
941 switch(type) {
942 case 0: /* men */
943 price = 1*nummen;
944 break;
945 case 1: /* tank */
946 price = 300;
947 break;
948 case 2: /* plane */
949 price = 600;
950 break;
951 case 3: /* Farm */
952 price = 1150;
953 break;
954 case 4: /* Factory */
955 price = 1300;
956 break;
957 case 5: /* nuke */
958 price = 2000;
959 break;
961 if(res->cash < price) {
962 if(human)
963 rb->splash(HZ, "Not enough money!");
964 return 2;
966 if(human) {
967 rb->splashf(HZ, "Where do you want to place %s?", itemnames[0][type]);
968 switch(select_square()) {
969 case 2:
970 return 2;
971 break;
972 case PLUGIN_USB_CONNECTED:
973 return PLUGIN_USB_CONNECTED;
974 break;
976 x = cursor.x;
977 y = cursor.y;
979 if(board[x][y].colour != colour) {
980 if(human)
981 rb->splashf(HZ, "Can't %s on enemy territory", itemnames[1][type]);
982 return 2;
984 if(type != 0 && tile_has_item(type, x, y)) {
985 if(human)
986 rb->splashf(HZ, "There is already %s there", itemnames[2][type]);
987 return 2;
989 switch(type) {
990 case 0:
991 board[x][y].men += nummen;
992 res->men += nummen;
993 break;
994 case 1:
995 board[x][y].tank = true;
996 res->tanks++;
997 break;
998 case 2:
999 board[x][y].plane = true;
1000 res->planes++;
1001 break;
1002 case 3:
1003 board[x][y].farm = true;
1004 res->farms++;
1005 break;
1006 case 4:
1007 board[x][y].ind = true;
1008 res->inds++;
1009 break;
1010 case 5:
1011 board[x][y].nuke = true;
1012 res->nukes++;
1013 break;
1015 res->cash -= price;
1017 draw_board();
1018 rb->sleep(HZ);
1020 return 0;
1023 int buy_resources_menu(void) {
1024 int selection,nummen;
1026 MENUITEM_STRINGLIST(res_menu, "Buy Resources", NULL, "Buy men ($1)",
1027 "Buy tank ($300)", "Buy plane ($600)", "Buy Farm ($1150)",
1028 "Buy Factory ($1300)", "Buy Nuke ($2000)",
1029 "Finish buying");
1031 while(1) {
1032 selection=rb->do_menu(&res_menu,&selection, NULL, false);
1033 switch(selection) {
1034 case 0:
1035 nummen = 0;
1036 if(get_number("How many men would you like?", &nummen)
1037 == PLUGIN_USB_CONNECTED)
1038 return PLUGIN_USB_CONNECTED;
1039 if(!nummen)
1040 break;
1041 /* fall through */
1042 case 1:
1043 case 2:
1044 case 3:
1045 case 4:
1046 case 5:
1047 if(buy_resources(COLOUR_LIGHT, selection, 0, 0, nummen)
1048 == PLUGIN_USB_CONNECTED)
1049 return PLUGIN_USB_CONNECTED;
1050 break;
1051 case 6:
1052 return 0;
1053 break;
1054 case MENU_ATTACHED_USB:
1055 return PLUGIN_USB_CONNECTED;
1056 break;
1057 case GO_TO_PREVIOUS:
1058 return 0;
1059 break;
1062 return 0;
1065 int move_unit(int colour, int type, int fromx, int fromy,
1066 int tox, int toy, int nummen) {
1067 const char *itemnames[][3] = {
1069 "troops",
1070 "the tank",
1071 "the plane",
1072 }, {
1073 "any troops",
1074 "a tank",
1075 "a plane",
1076 }, {
1077 "the troops",
1078 "the tank",
1079 "the plane",
1082 bool human = (colour == COLOUR_LIGHT);
1084 if(human) {
1085 rb->splashf(HZ, "Select where you want to move %s from",
1086 itemnames[0][type]);
1087 switch(select_square()) {
1088 case 2:
1089 return 2;
1090 break;
1091 case PLUGIN_USB_CONNECTED:
1092 return PLUGIN_USB_CONNECTED;
1093 break;
1095 fromx = cursor.x;
1096 fromy = cursor.y;
1098 if(board[fromx][fromy].colour != colour) {
1099 if(human)
1100 rb->splash(HZ, "That isn't your territory");
1101 return 2;
1103 if(!tile_has_item(type, fromx, fromy)) {
1104 if(human)
1105 rb->splashf(HZ, "You don't have %s there", itemnames[1][type]);
1106 return 2;
1108 if(type == 0) {
1109 if(human) {
1110 nummen = board[fromx][fromy].men;
1111 switch(get_number("How many men do you want to move?", &nummen)) {
1112 case 2:
1113 return 2;
1114 break;
1115 case PLUGIN_USB_CONNECTED:
1116 return PLUGIN_USB_CONNECTED;
1117 break;
1120 if(nummen > board[fromx][fromy].men) {
1121 if(human)
1122 rb->splash(HZ, "You don't have that many troops.");
1123 return 2;
1126 if(human) {
1127 rb->splashf(HZ, "Select where you want to move %s to",
1128 itemnames[2][type]);
1129 switch(select_square()) {
1130 case 2:
1131 return 2;
1132 break;
1133 case PLUGIN_USB_CONNECTED:
1134 return PLUGIN_USB_CONNECTED;
1135 break;
1137 tox = cursor.x;
1138 toy = cursor.y;
1140 if((tox == fromx && toy == fromy) ||
1141 board[tox][toy].colour != colour ||
1142 (type != 2 && (abs(tox - fromx) > 1 || abs(toy - fromy) > 1))) {
1143 if(human)
1144 rb->splash(HZ, "Invalid move");
1145 return 2;
1147 if(type != 0 && tile_has_item(type, tox, toy)) {
1148 if(human)
1149 rb->splashf(HZ, "There is already %s there", itemnames[1][type]);
1150 return 2;
1152 switch(type) {
1153 case 0:
1154 board[fromx][fromy].men -= nummen;
1155 board[tox][toy].men += nummen;
1156 break;
1157 case 1:
1158 board[fromx][fromy].tank = false;
1159 board[tox][toy].tank = true;
1160 break;
1161 case 2:
1162 board[fromx][fromy].plane = false;
1163 board[tox][toy].plane = true;
1164 break;
1166 return 0;
1169 int move_unit_menu(void) {
1170 int selection;
1172 MENUITEM_STRINGLIST(move_unit_menu, "Move unit", NULL, "Move men",
1173 "Move tank", "Move plane");
1174 selection=rb->do_menu(&move_unit_menu,&selection, NULL, false);
1175 switch(selection) {
1176 case 0:
1177 case 1:
1178 case 2:
1179 switch(move_unit(COLOUR_LIGHT, selection, 0, 0, 0, 0, 0)) {
1180 case 0:
1181 humanres.moves--;
1182 break;
1183 case PLUGIN_USB_CONNECTED:
1184 return PLUGIN_USB_CONNECTED;
1185 break;
1187 break;
1188 case MENU_ATTACHED_USB:
1189 return PLUGIN_USB_CONNECTED;
1191 return 0;
1194 int launch_nuke(int colour, int nukex, int nukey, int targetx, int targety) {
1195 bool human = (colour == COLOUR_LIGHT);
1196 struct resources *res;
1198 if(board[nukex][nukey].colour != colour) {
1199 if(human)
1200 rb->splash(HZ, "That isn't your territory");
1201 return 2;
1203 if(! board[nukex][nukey].nuke) {
1204 if(human)
1205 rb->splashf(HZ, "You don't have %s there", "a nuke");
1206 return 2;
1208 if(human) {
1209 rb->splash(HZ, "Select place to target with nuke");
1210 switch(select_square()) {
1211 case 2:
1212 return 2;
1213 break;
1214 case PLUGIN_USB_CONNECTED:
1215 return PLUGIN_USB_CONNECTED;
1216 break;
1218 targetx = cursor.x;
1219 targety = cursor.y;
1221 if(human) {
1222 humanres.nukes--;
1223 } else {
1224 compres.nukes--;
1226 board[nukex][nukey].nuke = false;
1228 if(board[targetx][targety].colour == COLOUR_LIGHT) {
1229 res = &humanres;
1230 } else {
1231 res = &compres;
1233 res->men -= board[targetx][targety].men;
1234 res->tanks -= board[targetx][targety].tank;
1235 res->planes -= board[targetx][targety].plane;
1236 res->nukes -= board[targetx][targety].nuke;
1237 res->farms -= board[targetx][targety].farm;
1238 res->inds -= board[targetx][targety].ind;
1239 board[targetx][targety].men = 0;
1240 board[targetx][targety].tank = false;
1241 board[targetx][targety].plane = false;
1242 board[targetx][targety].ind = false;
1243 board[targetx][targety].nuke = false;
1244 board[targetx][targety].farm = false;
1245 /* TODO: Fallout carried by wind */
1247 return 0;
1250 int movement_menu(void) {
1251 int selection, tempmenu;
1253 MENUITEM_STRINGLIST(move_menu, "Movement", NULL, "Move unit",
1254 "Buy additional moves ($100)", "Launch nuclear missile",
1255 "Check map", "Finish moving", "Game menu");
1257 while(1) {
1258 selection=rb->do_menu(&move_menu,&selection, NULL, false);
1259 switch(selection) {
1260 case 0:
1261 if(humanres.moves) {
1262 if(move_unit_menu()==PLUGIN_USB_CONNECTED)
1263 return PLUGIN_USB_CONNECTED;
1264 } else {
1265 rb->splash(HZ, "You have no more moves left."
1266 " You can buy more for $100 each.");
1268 break;
1269 case 1:
1270 if(humanres.cash > 100) {
1271 humanres.moves++;
1272 humanres.cash -= 100;
1273 rb->snprintf(buf, sizeof(buf), "You now have %d moves",
1274 humanres.moves);
1275 rb->splash(HZ, buf);
1277 break;
1278 case 2:
1279 if(humanres.nukes==0) {
1280 rb->splash(HZ, "You do not have any nukes to launch");
1281 } else {
1282 rb->splash(HZ, "Select place to launch nuke from");
1283 switch(select_square()) {
1284 case 0:
1285 if(launch_nuke(COLOUR_LIGHT, cursor.x, cursor.y,
1286 0, 0) == PLUGIN_USB_CONNECTED)
1287 return PLUGIN_USB_CONNECTED;
1288 break;
1289 case PLUGIN_USB_CONNECTED:
1290 return PLUGIN_USB_CONNECTED;
1291 break;
1294 break;
1295 case 3:
1296 if(select_square() == PLUGIN_USB_CONNECTED)
1297 return PLUGIN_USB_CONNECTED;
1298 break;
1299 case 4:
1300 return 0;
1301 break;
1302 case 5:
1303 tempmenu = ingame_menu();
1304 switch(tempmenu) {
1305 case PLUGIN_USB_CONNECTED:
1306 return PLUGIN_USB_CONNECTED;
1307 break;
1308 case SUPERDOM_QUIT:
1309 return SUPERDOM_QUIT;
1310 break;
1312 break;
1313 case MENU_ATTACHED_USB:
1314 return PLUGIN_USB_CONNECTED;
1315 break;
1318 return 0;
1321 int show_inventory(void) {
1322 char men[20], tanks[20], planes[20], inds[20], farms[20], nukes[20],
1323 cash[20], food[20], bank[20];
1324 rb->snprintf(men, sizeof(men), "Men: %d", humanres.men);
1325 rb->snprintf(tanks, sizeof(tanks), "Tanks: %d", humanres.tanks);
1326 rb->snprintf(planes, sizeof(planes), "Planes: %d", humanres.planes);
1327 rb->snprintf(inds, sizeof(inds), "Factories: %d", humanres.inds);
1328 rb->snprintf(farms, sizeof(farms), "Farms: %d", humanres.farms);
1329 rb->snprintf(nukes, sizeof(nukes), "Nukes: %d", humanres.nukes);
1330 rb->snprintf(cash, sizeof(cash), "Cash: %d", humanres.cash);
1331 rb->snprintf(food, sizeof(food), "Food: %d", humanres.food);
1332 rb->snprintf(bank, sizeof(bank), "Bank: %d", humanres.bank);
1333 rb->lcd_clear_display();
1334 rb->lcd_puts(1, 0, "Inventory");
1335 rb->lcd_puts(2, 1, men);
1336 rb->lcd_puts(2, 2, tanks);
1337 rb->lcd_puts(2, 3, planes);
1338 rb->lcd_puts(2, 4, inds);
1339 rb->lcd_puts(2, 5, farms);
1340 rb->lcd_puts(2, 6, nukes);
1341 rb->lcd_puts(2, 7, cash);
1342 rb->lcd_puts(2, 8, food);
1343 rb->lcd_puts(2, 9, bank);
1344 rb->lcd_update();
1345 if(rb->default_event_handler(rb->button_get(true)) == SYS_USB_CONNECTED) {
1346 return PLUGIN_USB_CONNECTED;
1347 } else {
1348 return 0;
1352 int production_menu(void) {
1353 int selection, tempbank, tempmenu;
1355 MENUITEM_STRINGLIST(prod_menu, "Production", NULL, "Buy resources",
1356 "Show inventory", "Check map", "Invest money",
1357 "Withdraw money", "Finish turn", "Game menu");
1359 while(1) {
1360 selection=rb->do_menu(&prod_menu,&selection, NULL, false);
1361 switch(selection) {
1362 case 0:
1363 if(buy_resources_menu() == PLUGIN_USB_CONNECTED)
1364 return PLUGIN_USB_CONNECTED;
1365 break;
1366 case 1:
1367 if(show_inventory() == PLUGIN_USB_CONNECTED)
1368 return PLUGIN_USB_CONNECTED;
1369 break;
1370 case 2:
1371 if(select_square() == PLUGIN_USB_CONNECTED)
1372 return PLUGIN_USB_CONNECTED;
1373 break;
1374 case 3:
1375 tempbank = humanres.cash;
1376 if(get_number("How much do you want to invest?", &tempbank)
1377 == PLUGIN_USB_CONNECTED)
1378 return PLUGIN_USB_CONNECTED;
1379 if(tempbank>humanres.cash) {
1380 rb->splash(HZ, "You don't have that much cash to invest");
1381 } else {
1382 humanres.cash -= tempbank;
1383 humanres.bank += tempbank;
1385 break;
1386 case 4:
1387 tempbank = 0;
1388 if(get_number("How much do you want to withdraw?", &tempbank)
1389 == PLUGIN_USB_CONNECTED)
1390 return PLUGIN_USB_CONNECTED;
1391 if(tempbank>humanres.bank) {
1392 rb->splash(HZ, "You don't have that much cash to withdraw");
1393 } else {
1394 humanres.cash += tempbank;
1395 humanres.bank -= tempbank;
1397 break;
1398 case 5:
1399 return 0;
1400 break;
1401 case 6:
1402 tempmenu = ingame_menu();
1403 switch(tempmenu) {
1404 case PLUGIN_USB_CONNECTED:
1405 return PLUGIN_USB_CONNECTED;
1406 break;
1407 case SUPERDOM_QUIT:
1408 return SUPERDOM_QUIT;
1409 break;
1411 break;
1412 case MENU_ATTACHED_USB:
1413 return PLUGIN_USB_CONNECTED;
1414 break;
1417 return 0;
1420 void init_resources(void) {
1421 humanres.cash = superdom_settings.startcash;
1422 humanres.food = superdom_settings.startfood;
1423 humanres.tanks = 0;
1424 humanres.planes = 0;
1425 humanres.nukes = 0;
1426 humanres.inds = 0;
1427 humanres.farms = 0;
1428 humanres.men = 0;
1429 humanres.bank = 0;
1430 humanres.moves = 0;
1431 compres.cash = superdom_settings.startcash;
1432 compres.food = superdom_settings.startfood;
1433 compres.tanks = 0;
1434 compres.planes = 0;
1435 compres.nukes = 0;
1436 compres.inds = 0;
1437 compres.farms = 0;
1438 compres.men = 0;
1439 compres.bank = 0;
1440 compres.moves = 0;
1443 int select_square(void) {
1444 int button = 0;
1445 draw_board();
1446 draw_cursor();
1447 update_score();
1448 #if LCD_WIDTH >= 220
1449 rb->lcd_setfont(FONT_SYSFIXED);
1450 rb->snprintf(buf, sizeof(buf), "Cash: %d", humanres.cash);
1451 rb->lcd_putsxy(125, LCD_HEIGHT-20, buf);
1452 rb->snprintf(buf, sizeof(buf), "Food: %d", humanres.food);
1453 rb->lcd_putsxy(125, LCD_HEIGHT-10, buf);
1454 rb->lcd_setfont(FONT_UI);
1455 #endif
1456 rb->lcd_update();
1457 while(1) {
1458 button = rb->button_get(true);
1459 switch(button) {
1460 case SUPERDOM_CANCEL:
1461 rb->splash(HZ, "Cancelled");
1462 return 2;
1463 break;
1464 case SUPERDOM_OK:
1465 return 0;
1466 break;
1467 #if CONFIG_KEYPAD != IRIVER_H10_PAD
1468 case SUPERDOM_LEFT:
1469 case (SUPERDOM_LEFT|BUTTON_REPEAT):
1470 draw_cursor(); /* Deselect the current tile */
1471 if(cursor.x>1) {
1472 cursor.x--;
1473 } else {
1474 #ifdef IPOD_STYLE
1475 if(cursor.y>1)
1476 cursor.y--;
1477 else
1478 cursor.y = 10;
1479 #endif
1480 cursor.x = 10;
1482 update_score();
1483 draw_cursor();
1484 break;
1485 case SUPERDOM_RIGHT:
1486 case (SUPERDOM_RIGHT|BUTTON_REPEAT):
1487 draw_cursor(); /* Deselect the current tile */
1488 if(cursor.x<10) {
1489 cursor.x++;
1490 } else {
1491 #ifdef IPOD_STYLE
1492 if(cursor.y<10)
1493 cursor.y++;
1494 else
1495 cursor.y = 1;
1496 #endif
1497 cursor.x = 1;
1499 update_score();
1500 draw_cursor();
1501 break;
1502 #endif
1503 #ifndef IPOD_STYLE
1504 case SUPERDOM_UP:
1505 case (SUPERDOM_UP|BUTTON_REPEAT):
1506 draw_cursor(); /* Deselect the current tile */
1507 if(cursor.y>1) {
1508 cursor.y--;
1509 } else {
1510 #if CONFIG_KEYPAD == IRIVER_H10_PAD
1511 if(cursor.x > 1)
1512 cursor.x--;
1513 else
1514 cursor.x = 10;
1515 #endif
1516 cursor.y = 10;
1518 update_score();
1519 draw_cursor();
1520 break;
1521 case SUPERDOM_DOWN:
1522 case (SUPERDOM_DOWN|BUTTON_REPEAT):
1523 draw_cursor(); /* Deselect the current tile */
1524 if(cursor.y<10) {
1525 cursor.y++;
1526 } else {
1527 #if CONFIG_KEYPAD == IRIVER_H10_PAD
1528 if(cursor.x < 10)
1529 cursor.x++;
1530 else
1531 cursor.x = 1;
1532 #endif
1533 cursor.y = 1;
1535 update_score();
1536 draw_cursor();
1537 break;
1538 #endif
1539 default:
1540 if (rb->default_event_handler(button) == SYS_USB_CONNECTED)
1542 return PLUGIN_USB_CONNECTED;
1548 int killmen(int colour) {
1549 bool human = (colour == COLOUR_LIGHT);
1550 int menkilled,i,j;
1551 int percent;
1552 if(human) {
1553 percent = (humanres.food*1000)/humanres.men;
1554 humanres.food = 0;
1555 } else {
1556 percent = (compres.food*1000)/compres.men;
1557 compres.food = 0;
1559 menkilled = 0;
1560 for(i=1;i<11;i++) {
1561 for(j=1;j<11;j++) {
1562 if(board[i][j].colour == colour) {
1563 int nummen = ((board[i][j].men * percent)/1000);
1564 menkilled += board[i][j].men - nummen;
1565 board[i][j].men = nummen;
1570 if(human)
1571 humanres.men -= menkilled;
1572 else
1573 compres.men -= menkilled;
1574 return menkilled;
1577 /* return -1 if error, 1 if attack is succeeded, 0 otherwise */
1578 int attack_territory(int colour, int x, int y) {
1579 bool human = (colour == COLOUR_LIGHT);
1580 int str_diff;
1582 if(board[x][y].colour == colour) {
1583 if(human)
1584 rb->splash(HZ, "You can't attack your own territory");
1585 return -1;
1587 str_diff = calc_strength(COLOUR_DARK, x, y) -
1588 calc_strength(COLOUR_LIGHT, x, y);
1589 if(human) {
1590 str_diff = -str_diff;
1592 rb->srand(*rb->current_tick);
1593 if(str_diff > 0 || (str_diff == 0 && rb->rand()%2)) {
1594 struct resources *offres, *defres;
1595 if(human) {
1596 offres = &humanres;
1597 defres = &compres;
1598 } else {
1599 offres = &compres;
1600 defres = &humanres;
1602 defres->men -= board[x][y].men;
1603 defres->tanks -= board[x][y].tank;
1604 defres->planes -= board[x][y].plane;
1605 defres->nukes -= board[x][y].nuke;
1606 defres->farms -= board[x][y].farm;
1607 defres->inds -= board[x][y].ind;
1608 offres->farms += board[x][y].farm;
1609 offres->inds += board[x][y].ind;
1610 board[x][y].colour = colour;
1611 board[x][y].men = 0;
1612 board[x][y].tank = false;
1613 board[x][y].plane = false;
1614 board[x][y].nuke = false;
1615 draw_board();
1616 if(human)
1617 rb->sleep(HZ*2);
1618 else
1619 rb->sleep(HZ);
1620 return 1;
1621 } else {
1622 if(human)
1623 rb->splash(HZ, "Your troops were unable to overcome"
1624 " the enemy troops");
1625 else
1626 rb->splash(HZ*2, "The computer attempted to "
1627 "attack, but the invasion was"
1628 " pushed back");
1629 return 0;
1631 return 0;
1634 int war_menu(void) {
1635 int selection, tempmenu;
1637 MENUITEM_STRINGLIST(wartime_menu, "War!", NULL,
1638 "Select territory to attack", "Finish turn", "Game menu");
1640 while(humanres.moves) {
1641 selection=rb->do_menu(&wartime_menu,&selection, NULL, false);
1642 switch(selection) {
1643 case 0:
1644 switch(select_square()) {
1645 case 0:
1646 if(attack_territory(COLOUR_LIGHT, cursor.x, cursor.y)
1647 >= 0)
1648 humanres.moves--;
1649 break;
1650 case PLUGIN_USB_CONNECTED:
1651 return PLUGIN_USB_CONNECTED;
1652 break;
1654 break;
1655 case 1:
1656 return 0;
1657 break;
1658 case 2:
1659 tempmenu = ingame_menu();
1660 switch(tempmenu) {
1661 case PLUGIN_USB_CONNECTED:
1662 return PLUGIN_USB_CONNECTED;
1663 break;
1664 case SUPERDOM_QUIT:
1665 return SUPERDOM_QUIT;
1666 break;
1668 break;
1671 return 0;
1674 struct threat {
1675 int x;
1676 int y;
1677 int str_diff;
1680 bool place_adjacent(bool tank, int x, int y) {
1681 int type = (tank? 1: 2);
1682 if(!buy_resources(COLOUR_DARK, type, x, y, 0)) {
1683 return true;
1685 if(!buy_resources(COLOUR_DARK, type, x-1, y, 0)) {
1686 return true;
1688 if(!buy_resources(COLOUR_DARK, type, x+1, y, 0)) {
1689 return true;
1691 if(!buy_resources(COLOUR_DARK, type, x, y-1, 0)) {
1692 return true;
1694 if(!buy_resources(COLOUR_DARK, type, x, y+1, 0)) {
1695 return true;
1697 return false;
1700 bool has_adjacent(int x, int y) {
1701 if((board[x][y].colour == COLOUR_LIGHT) &&
1702 ((board[x-1][y].colour == COLOUR_DARK) ||
1703 (board[x+1][y].colour == COLOUR_DARK) ||
1704 (board[x][y+1].colour == COLOUR_DARK) ||
1705 (board[x][y-1].colour == COLOUR_DARK)))
1706 return 1;
1707 else
1708 return 0;
1711 void find_adjacent(int x, int y, int* adj_x, int* adj_y) {
1712 /* Finds adjacent squares, returning squares without tanks on them
1713 * in preference to those with them */
1714 if(board[x-1][y].colour == COLOUR_DARK) {
1715 *adj_x = x-1;
1716 *adj_y = y;
1717 return;
1719 if(board[x+1][y].colour == COLOUR_DARK) {
1720 *adj_x = x+1;
1721 *adj_y = y;
1722 return;
1724 if(board[x][y-1].colour == COLOUR_DARK) {
1725 *adj_x = x;
1726 *adj_y = y-1;
1727 return;
1729 if(board[x][y+1].colour == COLOUR_DARK) {
1730 *adj_x = x;
1731 *adj_y = y+1;
1732 return;
1736 void computer_allocate(void) {
1737 /* Firstly, decide whether to go offensive or defensive.
1738 * This is primarily decided by the human player posing a threat to either
1739 * the computer's farms or factories */
1740 int i, j, k;
1741 bool offensive = true;
1742 struct threat threats[4];
1743 int numthreats = 0;
1744 int total_str_diff = 0;
1745 int numterritory = 0;
1746 int str_diff;
1747 int men_needed;
1748 struct threat targets[2];
1749 int numtargets;
1750 struct cursor adj;
1752 compres.cash += compres.bank;
1753 compres.bank = 0;
1754 for(i=1;i<11;i++) {
1755 for(j=1;j<11;j++) {
1756 if(board[i][j].colour == COLOUR_DARK) {
1757 numterritory++;
1758 str_diff = calc_strength(COLOUR_LIGHT,i,j) -
1759 calc_strength(COLOUR_DARK,i,j);
1760 if(str_diff > 0 && (board[i][j].ind || board[i][j].farm)) {
1761 if(numthreats < 3) {
1762 offensive = false;
1763 threats[numthreats].x = i;
1764 threats[numthreats].y = j;
1765 threats[numthreats].str_diff = str_diff;
1766 numthreats++;
1770 rb->yield();
1773 if(offensive) {
1774 /* The AI is going to go straight for the throat here and attack
1775 * the player's farms and factories. The amount of cash
1776 * the AI has to spend will determine how many targets there are */
1777 if(compres.cash > 1200) {
1778 /* 1200 is a figure I pulled out of nowhere. Adjust as needed */
1779 numtargets = 2;
1780 } else {
1781 numtargets = 1;
1783 /* Work out which target(s) to attack. They must have adjacent squares
1784 * owned by the computer. If none are found just place troops in
1785 * random places around the map until we run out of money */
1786 k = 0;
1787 for(i=1;i<11;i++) {
1788 for(j=1;j<11;j++) {
1789 if(has_adjacent(i,j) &&
1790 (board[i][j].ind || board[i][j].farm)) {
1791 if(k<numtargets) {
1792 targets[k].x = i;
1793 targets[k].y = j;
1794 targets[k].str_diff =
1795 calc_strength(COLOUR_LIGHT, i, j) -
1796 calc_strength(COLOUR_DARK, i, j);
1797 k++;
1800 rb->yield();
1803 if(k == 0) {
1804 /* No targets found! Randomly pick squares and if they're owned
1805 * by the computer then stick a tank on it. */
1806 rb->srand(*rb->current_tick);
1807 while(compres.cash >= 300 && compres.tanks < numterritory) {
1808 i = rb->rand()%10 + 1;
1809 j = rb->rand()%10 + 1;
1810 if(board[i][j].colour == COLOUR_DARK) {
1811 buy_resources(COLOUR_DARK, 1, i, j, 0);
1813 rb->yield();
1815 } else {
1816 for(i=0;i<k;i++) {
1817 str_diff = targets[i].str_diff;
1818 while(str_diff + 20 > 0 && compres.cash > 0) {
1819 /* While we still need them keep placing men */
1820 if(!place_adjacent(true, targets[i].x, targets[i].y)) {
1821 find_adjacent(targets[i].x, targets[i].y,
1822 &adj.x, &adj.y);
1823 men_needed = (str_diff + 20)*1000/133;
1824 if(compres.cash < men_needed) {
1825 men_needed = compres.cash;
1827 buy_resources(COLOUR_DARK, 0, adj.x, adj.y,
1828 men_needed);
1829 break;
1831 str_diff = calc_strength(COLOUR_LIGHT,
1832 targets[i].x, targets[i].y) -
1833 calc_strength(COLOUR_DARK,
1834 targets[i].x, targets[i].y);
1838 } else {
1839 /* Work out what to place on each square to defend it.
1840 * Tanks are preferential because they do not require food,
1841 * but if the budget is tight then we fall back onto troops.
1842 * Conversely if cash is not an issue and there are already tanks in
1843 * place planes will be deployed. We would like a margin of at least
1844 * 20 points to be safe. */
1846 for(i=0;i<numthreats;i++) {
1847 total_str_diff += threats[i].str_diff;
1849 if((total_str_diff+20)*10 > compres.cash) {
1850 /* Not enough cash to accomodate all threats using tanks alone -
1851 * use men as a backup */
1852 for(i=0;i<numthreats;i++) {
1853 men_needed = ((threats[i].str_diff + 20)*1000)/133;
1854 if(compres.cash < men_needed) {
1855 men_needed = compres.cash;
1857 buy_resources(COLOUR_DARK, 0, threats[i].x, threats[i].y,
1858 men_needed);
1860 } else {
1861 /* Tanks it is */
1862 /* Enough money to pay their way by planes? */
1863 bool tank = ((total_str_diff+20)*15 >= compres.cash);
1864 for(i=0;i<numthreats;i++) {
1865 str_diff = threats[i].str_diff;
1866 while(str_diff + 20 > 0) {
1867 if(!place_adjacent(tank, threats[i].x, threats[i].y)) {
1868 /* No room for any more planes or tanks, revert to
1869 * men */
1870 find_adjacent(threats[i].x, threats[i].y,
1871 &adj.x, &adj.y);
1872 men_needed = (str_diff + 20)*1000/133;
1873 if(compres.cash < men_needed) {
1874 men_needed = compres.cash;
1876 buy_resources(COLOUR_DARK, 0, threats[i].x,
1877 threats[i].y, men_needed);
1878 break;
1880 str_diff = calc_strength(COLOUR_LIGHT,
1881 threats[i].x, threats[i].y) -
1882 calc_strength(COLOUR_DARK,
1883 threats[i].x, threats[i].y);
1888 compres.bank += compres.cash;
1889 compres.cash = 0;
1892 int find_adj_target(int x, int y, struct cursor* adj) {
1893 /* Find a square next to a computer's farm or factory owned by the player
1894 * that is vulnerable. Return 1 on success, 0 otherwise */
1895 if(board[x+1][y].colour == COLOUR_LIGHT &&
1896 calc_strength(COLOUR_LIGHT,x+1,y)<=calc_strength(COLOUR_DARK,x+1,y)) {
1897 adj->x = x+1;
1898 adj->y = y;
1899 return 1;
1901 if(board[x-1][y].colour == COLOUR_LIGHT &&
1902 calc_strength(COLOUR_LIGHT,x-1,y)<=calc_strength(COLOUR_DARK,x-1,y)) {
1903 adj->x = x-1;
1904 adj->y = y;
1905 return 1;
1907 if(board[x][y+1].colour == COLOUR_LIGHT &&
1908 calc_strength(COLOUR_LIGHT,x,y+1)<=calc_strength(COLOUR_DARK,x,y+1)) {
1909 adj->x = x;
1910 adj->y = y+1;
1911 return 1;
1913 if(board[x][y-1].colour == COLOUR_LIGHT &&
1914 calc_strength(COLOUR_LIGHT,x,y-1)<=calc_strength(COLOUR_DARK,x,y-1)) {
1915 adj->x = x;
1916 adj->y = y-1;
1917 return 1;
1919 return 0;
1922 void computer_war(void) {
1923 /* Work out where to attack - prioritise the defence of buildings */
1924 int i, j;
1925 bool found_target = true;
1926 struct cursor adj;
1928 while(found_target) {
1929 found_target = false;
1930 for(i=1;i<11;i++) {
1931 for(j=1;j<11;j++) {
1932 if((board[i][j].colour == COLOUR_DARK) &&
1933 (board[i][j].farm || board[i][j].ind) &&
1934 find_adj_target(i, j, &adj)) {
1935 found_target = true;
1936 if(attack_territory(COLOUR_DARK, adj.x, adj.y) >= 0) {
1937 compres.moves--;
1938 if(!compres.moves)
1939 return;
1942 rb->yield();
1946 /* Defence stage done, move on to OFFENCE */
1947 found_target = true;
1948 while(found_target) {
1949 found_target = false;
1950 for(i=1;i<11;i++) {
1951 for(j=1;j<11;j++) {
1952 if(board[i][j].colour == COLOUR_LIGHT &&
1953 (board[i][j].ind || board[i][j].farm) &&
1954 (calc_strength(COLOUR_DARK, i, j) >=
1955 calc_strength(COLOUR_LIGHT, i, j))) {
1956 found_target = true;
1957 if(attack_territory(COLOUR_DARK, i, j) >= 0) {
1958 compres.moves--;
1959 if(!compres.moves)
1960 return;
1963 rb->yield();
1967 /* Spend leftover moves wherever attacking randomly */
1968 found_target = true;
1969 while(found_target) {
1970 found_target = false;
1971 for(i=1;i<11;i++) {
1972 for(j=1;j<11;j++) {
1973 if(board[i][j].colour == COLOUR_LIGHT &&
1974 (calc_strength(COLOUR_DARK, i, j) >=
1975 calc_strength(COLOUR_LIGHT, i, j))) {
1976 found_target = true;
1977 if(attack_territory(COLOUR_DARK, i, j) >= 0) {
1978 compres.moves--;
1979 if(!compres.moves)
1980 return;
1983 rb->yield();
1989 static int load_game(const char* file) {
1990 int fd;
1992 fd = rb->open(file, O_RDONLY);
1993 if(fd == 0) {
1994 DEBUGF("Couldn't open savegame\n");
1995 return -1;
1997 rb->read(fd, buf, 5);
1998 if(rb->strcmp(buf, "SSGv3")) {
1999 rb->splash(HZ, "Invalid/incompatible savegame");
2000 return -1;
2002 rb->read(fd, &gamestate, sizeof(gamestate));
2003 rb->read(fd, &humanres.cash, sizeof(humanres.cash));
2004 rb->read(fd, &humanres.food, sizeof(humanres.food));
2005 rb->read(fd, &humanres.bank, sizeof(humanres.bank));
2006 rb->read(fd, &humanres.planes, sizeof(humanres.planes));
2007 rb->read(fd, &humanres.tanks, sizeof(humanres.tanks));
2008 rb->read(fd, &humanres.men, sizeof(humanres.men));
2009 rb->read(fd, &humanres.nukes, sizeof(humanres.nukes));
2010 rb->read(fd, &humanres.inds, sizeof(humanres.inds));
2011 rb->read(fd, &humanres.farms, sizeof(humanres.farms));
2012 rb->read(fd, &humanres.moves, sizeof(humanres.moves));
2013 rb->read(fd, &compres.cash, sizeof(humanres.cash));
2014 rb->read(fd, &compres.food, sizeof(humanres.food));
2015 rb->read(fd, &compres.bank, sizeof(humanres.bank));
2016 rb->read(fd, &compres.planes, sizeof(humanres.planes));
2017 rb->read(fd, &compres.tanks, sizeof(humanres.tanks));
2018 rb->read(fd, &compres.men, sizeof(humanres.men));
2019 rb->read(fd, &compres.nukes, sizeof(humanres.nukes));
2020 rb->read(fd, &compres.inds, sizeof(humanres.inds));
2021 rb->read(fd, &compres.farms, sizeof(humanres.farms));
2022 rb->read(fd, &compres.moves, sizeof(humanres.moves));
2023 rb->read(fd, board, sizeof(board));
2024 rb->read(fd, &superdom_settings.compstartfarms, sizeof(int));
2025 rb->read(fd, &superdom_settings.compstartinds, sizeof(int));
2026 rb->read(fd, &superdom_settings.humanstartfarms, sizeof(int));
2027 rb->read(fd, &superdom_settings.humanstartfarms, sizeof(int));
2028 rb->read(fd, &superdom_settings.startcash, sizeof(int));
2029 rb->read(fd, &superdom_settings.startfood, sizeof(int));
2030 rb->read(fd, &superdom_settings.movesperturn, sizeof(int));
2031 rb->close(fd);
2032 return 0;
2035 void default_settings(void) {
2036 superdom_settings.compstartfarms = 1;
2037 superdom_settings.compstartinds = 1;
2038 superdom_settings.humanstartfarms = 2;
2039 superdom_settings.humanstartinds = 2;
2040 superdom_settings.startcash = 0;
2041 superdom_settings.startfood = 0;
2042 superdom_settings.movesperturn = 2;
2045 int average_strength(int colour) {
2046 /* This function calculates the average strength of the given player,
2047 * used to determine when the computer wins or loses. */
2048 int i,j;
2049 int totalpower = 0;
2050 for(i=1;i<11;i++) {
2051 for(j=1;j<11;j++) {
2052 if(board[i][j].colour != -1) {
2053 totalpower += calc_strength(colour, i, j);
2057 return totalpower/100;
2060 enum plugin_status plugin_start(const void* parameter)
2062 #if LCD_DEPTH > 1
2063 rb->lcd_set_backdrop(NULL);
2064 rb->lcd_set_foreground(LCD_BLACK);
2065 rb->lcd_set_background(LCD_WHITE);
2066 #endif
2068 cursor.x = 1;
2069 cursor.y = 1;
2070 default_settings();
2071 if(parameter) {
2072 if(load_game(parameter) != 0) {
2073 DEBUGF("Loading failed, generating new game\n");
2074 } else {
2075 switch(gamestate) {
2076 case GS_PROD:
2077 goto startprod;
2078 break;
2079 case GS_MOVE:
2080 goto startmove;
2081 break;
2082 case GS_WAR:
2083 goto startwar;
2084 break;
2085 default:
2086 goto startyear;
2087 break;
2092 bool play = false;
2093 while(!play) {
2094 switch(menu()) {
2095 case 0:
2096 play = true;
2097 break;
2098 case 2:
2099 return PLUGIN_OK;
2100 break;
2101 case PLUGIN_USB_CONNECTED:
2102 return PLUGIN_USB_CONNECTED;
2103 break;
2106 init_resources();
2107 init_board();
2108 gen_resources();
2109 startyear:
2110 while(1) {
2111 int avg_str_diff = (average_strength(COLOUR_LIGHT) -
2112 average_strength(COLOUR_DARK));
2113 if(avg_str_diff > 15) {
2114 rb->splash(HZ*4, "The computer has surrendered. You win.");
2115 return PLUGIN_OK;
2117 if(-avg_str_diff > 15) {
2118 rb->splash(HZ*4, "Your army have suffered terrible morale from"
2119 " the bleak prospects of winning. You lose.");
2120 return PLUGIN_OK;
2123 /* production */
2124 startprod:
2125 gamestate = GS_PROD;
2126 switch(production_menu()) {
2127 case PLUGIN_USB_CONNECTED:
2128 return PLUGIN_USB_CONNECTED;
2129 break;
2130 case SUPERDOM_QUIT:
2131 return PLUGIN_OK;
2132 break;
2134 computer_allocate();
2136 /* movement */
2137 humanres.moves = superdom_settings.movesperturn;
2138 startmove:
2139 gamestate = GS_MOVE;
2140 switch(movement_menu()) {
2141 case PLUGIN_USB_CONNECTED:
2142 return PLUGIN_USB_CONNECTED;
2143 break;
2144 case SUPERDOM_QUIT:
2145 return PLUGIN_OK;
2146 break;
2148 /* feed men */
2149 if(humanres.men) {
2150 if(humanres.food > humanres.men) {
2151 rb->snprintf(buf, sizeof(buf), "Your men ate %d units of food",
2152 humanres.men);
2153 humanres.food -= humanres.men;
2154 } else {
2155 rb->snprintf(buf, sizeof(buf), "There was not enough food"
2156 " to feed all your men, %d men have died of starvation",
2157 killmen(COLOUR_LIGHT));
2159 rb->splash(HZ*2, buf);
2161 if(compres.men) {
2162 if(compres.food > compres.men) {
2163 compres.food -= compres.men;
2164 } else {
2165 rb->snprintf(buf, sizeof(buf), "The computer does not have"
2166 " enough food to feed its men. %d have died of starvation",
2167 killmen(COLOUR_DARK));
2168 rb->splash(HZ, buf);
2171 /* war */
2172 humanres.moves = superdom_settings.movesperturn;
2173 startwar:
2174 gamestate = GS_WAR;
2175 switch(war_menu()) {
2176 case PLUGIN_USB_CONNECTED:
2177 return PLUGIN_USB_CONNECTED;
2178 break;
2179 case SUPERDOM_QUIT:
2180 return PLUGIN_OK;
2181 break;
2183 compres.moves = superdom_settings.movesperturn;
2184 computer_war();
2185 gen_resources();
2187 return PLUGIN_OK;