Use the AMS_LOWMEM define to indicate memory size as the .lds files do in config...
[kugel-rb.git] / apps / plugins / superdom.c
blob80dd4f518b31d2bf47ee67219cf232c8a264675d
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 PLUGIN_HEADER
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_DEPTH == 16)
34 #define MY_BITMAP_PART rb->lcd_bitmap_transparent_part
35 #else
36 #define MY_BITMAP_PART rb->lcd_mono_bitmap_part
37 #endif
39 #if LCD_WIDTH > LCD_HEIGHT
40 #define BOX_WIDTH ((LCD_WIDTH-(MARGIN*2))/10)
41 #define BOX_HEIGHT ((BOX_WIDTH*2)/3)
43 #else
44 #define BOX_HEIGHT ((LCD_HEIGHT-(MARGIN*2)-15)/10)
45 #define BOX_WIDTH ((BOX_HEIGHT*2)/3)
47 #endif
49 #if LCD_WIDTH == 220 && LCD_HEIGHT == 176
50 #define NUM_BOX_HEIGHT 25
51 #define NUM_BOX_WIDTH 30
52 #define STRIDE 14
53 #define ICON_HEIGHT 7
54 #define ICON_WIDTH 7
56 #elif (LCD_WIDTH == 160 && LCD_HEIGHT == 128) || \
57 (LCD_WIDTH == 176 && LCD_HEIGHT == 132) || \
58 (LCD_WIDTH == 176 && LCD_HEIGHT == 220)
59 #define NUM_BOX_HEIGHT 20
60 #define NUM_BOX_WIDTH 24
61 #define STRIDE 8
62 #define ICON_HEIGHT 4
63 #define ICON_WIDTH 4
65 #elif (LCD_WIDTH == 320 && LCD_HEIGHT == 240)
66 #define NUM_BOX_HEIGHT 25
67 #define NUM_BOX_WIDTH 30
68 #define STRIDE 20
69 #define ICON_HEIGHT 10
70 #define ICON_WIDTH 10
72 #elif (LCD_WIDTH == 240 && (LCD_HEIGHT == 320 || LCD_HEIGHT == 400))
73 #define NUM_BOX_HEIGHT 25
74 #define NUM_BOX_WIDTH 30
75 #define STRIDE 18
76 #define ICON_HEIGHT 9
77 #define ICON_WIDTH 9
79 #endif
81 #define NUM_MARGIN_X (LCD_WIDTH-3*NUM_BOX_WIDTH)/2
82 #define NUM_MARGIN_Y (LCD_HEIGHT-4*NUM_BOX_HEIGHT)/2
84 #if (CONFIG_KEYPAD == IPOD_4G_PAD) || (CONFIG_KEYPAD == IPOD_3G_PAD) || \
85 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
86 #define SUPERDOM_OK BUTTON_SELECT
87 #define SUPERDOM_CANCEL BUTTON_MENU
88 #define SUPERDOM_LEFT BUTTON_LEFT
89 #define SUPERDOM_RIGHT BUTTON_RIGHT
90 #define IPOD_STYLE
92 #elif CONFIG_KEYPAD == IRIVER_H300_PAD || CONFIG_KEYPAD == IRIVER_H100_PAD
93 #define SUPERDOM_OK BUTTON_SELECT
94 #define SUPERDOM_LEFT BUTTON_LEFT
95 #define SUPERDOM_RIGHT BUTTON_RIGHT
96 #define SUPERDOM_UP BUTTON_UP
97 #define SUPERDOM_DOWN BUTTON_DOWN
98 #define SUPERDOM_CANCEL BUTTON_OFF
100 #elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
101 #define SUPERDOM_OK BUTTON_SELECT
102 #define SUPERDOM_LEFT BUTTON_LEFT
103 #define SUPERDOM_RIGHT BUTTON_RIGHT
104 #define SUPERDOM_UP BUTTON_UP
105 #define SUPERDOM_DOWN BUTTON_DOWN
106 #define SUPERDOM_CANCEL BUTTON_REC
108 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
109 #define SUPERDOM_OK BUTTON_RIGHT
110 #define SUPERDOM_UP BUTTON_SCROLL_UP
111 #define SUPERDOM_DOWN BUTTON_SCROLL_DOWN
112 #define SUPERDOM_CANCEL BUTTON_LEFT
114 #elif CONFIG_KEYPAD == GIGABEAT_PAD
115 #define SUPERDOM_OK BUTTON_SELECT
116 #define SUPERDOM_UP BUTTON_UP
117 #define SUPERDOM_DOWN BUTTON_DOWN
118 #define SUPERDOM_LEFT BUTTON_LEFT
119 #define SUPERDOM_RIGHT BUTTON_RIGHT
120 #define SUPERDOM_CANCEL BUTTON_POWER
122 #elif CONFIG_KEYPAD == SANSA_E200_PAD
123 #define SUPERDOM_OK BUTTON_SELECT
124 #define SUPERDOM_UP BUTTON_SCROLL_BACK
125 #define SUPERDOM_DOWN BUTTON_SCROLL_FWD
126 #define SUPERDOM_LEFT BUTTON_LEFT
127 #define SUPERDOM_RIGHT BUTTON_RIGHT
128 #define SUPERDOM_CANCEL BUTTON_POWER
130 #elif CONFIG_KEYPAD == SANSA_FUZE_PAD
131 #define SUPERDOM_OK BUTTON_SELECT
132 #define SUPERDOM_UP BUTTON_SCROLL_BACK
133 #define SUPERDOM_DOWN BUTTON_SCROLL_FWD
134 #define SUPERDOM_LEFT BUTTON_LEFT
135 #define SUPERDOM_RIGHT BUTTON_RIGHT
136 #define SUPERDOM_CANCEL (BUTTON_HOME|BUTTON_REPEAT)
138 #elif CONFIG_KEYPAD == GIGABEAT_S_PAD
139 #define SUPERDOM_OK BUTTON_SELECT
140 #define SUPERDOM_UP BUTTON_UP
141 #define SUPERDOM_DOWN BUTTON_DOWN
142 #define SUPERDOM_LEFT BUTTON_LEFT
143 #define SUPERDOM_RIGHT BUTTON_RIGHT
144 #define SUPERDOM_CANCEL BUTTON_BACK
146 #elif CONFIG_KEYPAD == COWOND2_PAD
147 #define SUPERDOM_CANCEL BUTTON_POWER
149 #elif CONFIG_KEYPAD == CREATIVEZVM_PAD
150 #define SUPERDOM_OK BUTTON_SELECT
151 #define SUPERDOM_UP BUTTON_UP
152 #define SUPERDOM_DOWN BUTTON_DOWN
153 #define SUPERDOM_LEFT BUTTON_LEFT
154 #define SUPERDOM_RIGHT BUTTON_RIGHT
155 #define SUPERDOM_CANCEL BUTTON_BACK
157 #elif CONFIG_KEYPAD == ONDAVX747_PAD
158 #define SUPERDOM_CANCEL BUTTON_POWER
160 #endif
162 #ifdef HAVE_TOUCHSCREEN
163 #ifndef SUPERDOM_OK
164 #define SUPERDOM_OK BUTTON_CENTER
165 #endif
166 #ifndef SUPERDOM_UP
167 #define SUPERDOM_UP BUTTON_TOPMIDDLE
168 #endif
169 #ifndef SUPERDOM_LEFT
170 #define SUPERDOM_LEFT BUTTON_MIDLEFT
171 #endif
172 #ifndef SUPERDOM_RIGHT
173 #define SUPERDOM_RIGHT BUTTON_MIDRIGHT
174 #endif
175 #ifndef SUPERDOM_DOWN
176 #define SUPERDOM_DOWN BUTTON_BOTTOMMIDDLE
177 #endif
178 #ifndef SUPERDOM_CANCEL
179 #define SUPERDOM_CANCEL BUTTON_TOPLEFT
180 #endif
181 #endif
183 #define SUPERDOM_QUIT 23
185 void gen_interest(void);
186 int production_menu(void);
187 void init_resources(void);
188 int select_square(void);
189 void update_score(void);
190 void gen_resources(void);
191 void draw_cursor(void);
192 int calc_strength(int colour, int x, int y);
193 void draw_board(void);
195 struct tile{
196 signed int colour; /* -1 = Unset */
197 bool tank;
198 bool plane;
199 bool nuke;
200 bool ind;
201 bool farm;
202 int men;
205 struct resources {
206 int cash;
207 int food;
208 int farms;
209 int inds;
210 int men;
211 int tanks;
212 int planes;
213 int nukes;
214 int bank;
215 int moves;
218 struct settings {
219 int compstartfarms;
220 int compstartinds;
221 int humanstartfarms;
222 int humanstartinds;
223 int startcash;
224 int startfood;
225 int movesperturn;
226 } superdom_settings;
228 struct resources humanres;
229 struct resources compres;
230 enum { GS_PROD, GS_MOVE, GS_WAR } gamestate;
232 struct cursor{
233 int x;
234 int y;
235 } cursor;
237 struct tile board[12][12];
239 void init_board(void) {
240 int i,j;
241 rb->srand(*rb->current_tick);
242 for(i=0;i<12;i++) { /* Hopefully about 50% each colour */
243 for(j=0;j<12;j++) {
244 if((i<1)||(j<1)||(i>10)||(j>10))
245 board[i][j].colour = -1; /* Unset */
246 else
247 board[i][j].colour = rb->rand()%2;
248 board[i][j].tank = false;
249 board[i][j].plane = false;
250 board[i][j].nuke = false;
251 board[i][j].ind = false;
252 board[i][j].farm = false;
253 board[i][j].men = 0;
257 while(compres.farms < superdom_settings.compstartfarms) {
258 i = rb->rand()%10 + 1;
259 j = rb->rand()%10 + 1;
260 if((board[i][j].colour == COLOUR_DARK) && (board[i][j].farm == false)) {
261 board[i][j].farm = true;
262 compres.farms++;
265 while(compres.inds < superdom_settings.compstartinds) {
266 i = rb->rand()%10 + 1;
267 j = rb->rand()%10 + 1;
268 if((board[i][j].colour == COLOUR_DARK) && (board[i][j].ind == false)) {
269 board[i][j].ind = true;
270 compres.inds++;
273 while(humanres.farms<superdom_settings.humanstartfarms) {
274 i = rb->rand()%10 + 1;
275 j = rb->rand()%10 + 1;
276 if((board[i][j].colour == COLOUR_LIGHT)&&(board[i][j].farm == false)) {
277 board[i][j].farm = true;
278 humanres.farms++;
281 while(humanres.inds<superdom_settings.humanstartfarms) {
282 i = rb->rand()%10 + 1;
283 j = rb->rand()%10 + 1;
284 if((board[i][j].colour == COLOUR_LIGHT) && (board[i][j].ind == false)) {
285 board[i][j].ind = true;
286 humanres.inds++;
291 void draw_board(void) {
292 int i,j;
293 rb->lcd_clear_display();
294 for(i=1;i<11;i++) {
295 for(j=1;j<11;j++) {
296 if(board[i][j].colour == COLOUR_DARK) {
297 rb->lcd_set_foreground(LCD_DARKGRAY);
298 } else {
299 rb->lcd_set_foreground(LCD_LIGHTGRAY);
301 rb->lcd_fillrect(MARGIN+(BOX_WIDTH*(i-1)),
302 MARGIN+(BOX_HEIGHT*(j-1)), BOX_WIDTH,
303 BOX_HEIGHT);
304 #if LCD_DEPTH != 16
305 rb->lcd_set_drawmode(DRMODE_BG | DRMODE_INVERSEVID);
306 #endif
307 if(board[i][j].ind) {
308 MY_BITMAP_PART(superdom_boarditems,
309 board[i][j].colour?ICON_WIDTH:0, 0, STRIDE,
310 #if LCD_WIDTH > LCD_HEIGHT
311 MARGIN+(BOX_WIDTH*(i-1))+1,
312 MARGIN+(BOX_HEIGHT*(j-1))+ICON_HEIGHT+1,
313 #else
314 MARGIN+(BOX_WIDTH*(i-1))+1+ICON_WIDTH,
315 MARGIN+(BOX_HEIGHT*(j-1))+1,
316 #endif
317 ICON_WIDTH, ICON_HEIGHT);
319 if(board[i][j].farm) {
320 MY_BITMAP_PART(superdom_boarditems,
321 board[i][j].colour?ICON_WIDTH:0, ICON_HEIGHT,
322 STRIDE, MARGIN+(BOX_WIDTH*(i-1))+1,
323 MARGIN+(BOX_HEIGHT*(j-1))+1,
324 ICON_WIDTH, ICON_HEIGHT);
326 if(board[i][j].tank) {
327 MY_BITMAP_PART(superdom_boarditems,
328 board[i][j].colour?ICON_WIDTH:0, ICON_HEIGHT*2,
329 STRIDE, MARGIN+(BOX_WIDTH*(i-1))+ICON_WIDTH+1,
330 MARGIN+(BOX_HEIGHT*(j-1))+ICON_HEIGHT+1,
331 ICON_WIDTH, ICON_HEIGHT);
333 if(board[i][j].men) {
334 MY_BITMAP_PART(superdom_boarditems,
335 board[i][j].colour?ICON_WIDTH:0, ICON_HEIGHT*3,
336 #if LCD_WIDTH > LCD_HEIGHT
337 STRIDE, MARGIN+(BOX_WIDTH*(i-1))+ICON_WIDTH+1,
338 MARGIN+(BOX_HEIGHT*(j-1))+1,
339 #else
340 STRIDE, MARGIN+(BOX_WIDTH*(i-1))+1,
341 MARGIN+(BOX_HEIGHT*(j-1))+1+ICON_HEIGHT,
342 #endif
343 ICON_WIDTH, ICON_HEIGHT);
345 if(board[i][j].plane) {
346 MY_BITMAP_PART(superdom_boarditems,
347 board[i][j].colour?ICON_WIDTH:0, ICON_HEIGHT*4,
348 #if LCD_WIDTH > LCD_HEIGHT
349 STRIDE,MARGIN+(BOX_WIDTH*(i-1))+ICON_WIDTH*2+1,
350 MARGIN+(BOX_HEIGHT*(j-1))+ICON_HEIGHT+1,
351 #else
352 STRIDE,MARGIN+(BOX_WIDTH*(i-1))+ICON_WIDTH+1,
353 MARGIN+(BOX_HEIGHT*(j-1))+ICON_HEIGHT*2+1,
354 #endif
355 ICON_WIDTH, ICON_HEIGHT);
357 if(board[i][j].nuke) {
358 MY_BITMAP_PART(superdom_boarditems,
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(int 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 || a == 0) &&
389 (board[x + a][y + b].colour == colour)) {
390 score += 10;
391 if(board[x + a][y + b].tank || board[x + a][y + b].farm)
392 score += 30;
393 if(board[x + a][y + b].plane || board[x + a][y + b].ind)
394 score += 40;
395 if(board[x + a][y + b].nuke)
396 score += 20;
397 if(board[x + a][y + b].men)
398 score += (board[x + a][y + b].men*133/1000);
402 return score;
405 void gen_interest(void) {
406 /* Interest should be around 10% */
407 rb->srand(*rb->current_tick);
408 int interest = 7+rb->rand()%6;
409 humanres.bank = humanres.bank+(interest*humanres.bank/100);
410 compres.bank = compres.bank+(interest*compres.bank/100);
413 void draw_cursor(void) {
414 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
415 rb->lcd_fillrect(MARGIN+((cursor.x-1)*BOX_WIDTH),
416 MARGIN+((cursor.y-1)*BOX_HEIGHT), BOX_WIDTH+1, BOX_HEIGHT+1);
417 rb->lcd_set_drawmode(DRMODE_SOLID);
418 rb->lcd_update();
421 void gen_resources(void) {
422 int inccash = 0;
423 int incfood = 0;
424 int ratecash = 0;
425 int ratefood = 0;
426 int i;
427 gen_interest();
428 rb->srand(*rb->current_tick);
429 /* Generate Human's resources */
430 for(i=0;i<humanres.inds;i++) {
431 inccash += (300+rb->rand()%200);
433 for(i=0;i<humanres.farms;i++) {
434 incfood += (200+rb->rand()%200);
436 if(humanres.inds)
437 ratecash = inccash/humanres.inds;
438 if(humanres.farms)
439 ratefood = incfood/humanres.farms;
440 if(ratecash > 450) {
441 if(ratefood > 350) {
442 rb->splash(HZ*2, "Patriotism sweeps the land, all production"
443 " is up this year!");
444 } else {
445 rb->splash(HZ*2, "Factories working at maximum efficiency,"
446 " cash production up this year!");
448 } else if(ratecash > 350) {
449 if(ratefood > 350) {
450 rb->splash(HZ*2, "Record crop harvest this year!");
451 } else if(ratefood > 250) {
452 rb->splash(HZ*2, "Production continues as normal");
453 } else {
454 rb->splash(HZ*2, "Spoilage of crops leads to reduced farm"
455 " output this year");
457 } else {
458 if(ratefood > 350) {
459 rb->splash(HZ*2, "Record crop harvest this year!");
460 } else if(ratefood > 250) {
461 rb->splash(HZ*2, "Factory unions introduced. Industrial"
462 " production is down this year.");
463 } else {
464 rb->splash(HZ*2, "Internet created. All production is down"
465 " due to time wasted.");
468 humanres.cash += inccash;
469 humanres.food += incfood;
471 /* Generate Computer's resources */
472 inccash = 0;
473 incfood = 0;
474 for(i=0;i<compres.inds;i++) {
475 inccash += (300+rb->rand()%200);
477 for(i=0;i<compres.farms;i++) {
478 incfood += (200+rb->rand()%200);
480 compres.cash += inccash;
481 compres.food += incfood;
484 void update_score(void) {
485 int strength;
486 rb->lcd_setfont(FONT_SYSFIXED);
487 rb->lcd_set_drawmode(DRMODE_BG|DRMODE_INVERSEVID);
488 rb->lcd_fillrect(5,LCD_HEIGHT-20,105,20);
489 rb->lcd_set_drawmode(DRMODE_SOLID);
490 strength = calc_strength(COLOUR_LIGHT, cursor.x, cursor.y);
491 rb->snprintf(buf, sizeof(buf), "Your power: %d.%d",
492 strength/10, strength%10);
493 rb->lcd_putsxy(5,LCD_HEIGHT-20, buf);
494 strength = calc_strength(COLOUR_DARK, cursor.x, cursor.y);
495 rb->snprintf(buf, sizeof(buf), "Comp power: %d.%d",
496 strength/10, strength%10);
497 rb->lcd_putsxy(5,LCD_HEIGHT-10, buf);
498 rb->lcd_setfont(FONT_UI);
501 int settings_menu_function(void) {
502 int selection = 0;
504 MENUITEM_STRINGLIST(settings_menu,"Super Domination Settings",NULL,
505 "Computer starting farms","Computer starting factories",
506 "Human starting farms","Human starting factories",
507 "Starting cash","Starting food","Moves per turn");
509 while(1) {
510 selection=rb->do_menu(&settings_menu,&selection, NULL, false);
511 switch(selection) {
512 case 0:
513 rb->set_int("Computer starting farms", "", UNIT_INT,
514 &superdom_settings.compstartfarms, NULL,
515 1, 0, 5, NULL);
516 break;
517 case 1:
518 rb->set_int("Computer starting factories", "", UNIT_INT,
519 &superdom_settings.compstartinds, NULL,
520 1, 0, 5, NULL);
521 break;
522 case 2:
523 rb->set_int("Human starting farms", "", UNIT_INT,
524 &superdom_settings.humanstartfarms, NULL,
525 1, 0, 5, NULL);
526 break;
527 case 3:
528 rb->set_int("Human starting factories", "", UNIT_INT,
529 &superdom_settings.humanstartinds, NULL,
530 1, 0, 5, NULL);
531 break;
532 case 4:
533 rb->set_int("Starting cash", "", UNIT_INT,
534 &superdom_settings.startcash, NULL,
535 250, 0, 5000, NULL);
536 break;
537 case 5:
538 rb->set_int("Starting food", "", UNIT_INT,
539 &superdom_settings.startfood, NULL,
540 250, 0, 5000, NULL);
541 break;
542 case 6:
543 rb->set_int("Moves per turn", "", UNIT_INT,
544 &superdom_settings.movesperturn, NULL,
545 1, 1, 5, NULL);
546 break;
547 case MENU_ATTACHED_USB:
548 return PLUGIN_USB_CONNECTED;
549 break;
550 case GO_TO_PREVIOUS:
551 return 0;
552 break;
555 return 0;
558 static int do_help(void) {
559 int button;
560 int y = MARGIN, space_w, width, height;
561 unsigned short x = MARGIN, i = 0;
562 #define WORDS (sizeof instructions / sizeof (char*))
563 static char* instructions[] = {
564 "Super", "domination", "is", "a", "turn", "based", "strategy", "game,",
565 "where", "the", "aim", "is", "to", "overpower", "the", "computer",
566 "player", "by", "taking", "their", "territory.", "",
567 "Each", "year", "you", "are", "allocated", "an", "amount", "of", "cash",
568 "and", "food,", "depending", "on", "how", "many", "farms", "and",
569 "factories", "you", "control.", "",
570 "Use", "this", "cash", "and", "food", "to", "buy", "and", "feed", "your",
571 "army.", "Each", "tile", "has", "a", "strength,", "calculated", "by",
572 "the", "ownership", "of", "adjacent", "tiles,", "and", "the", "type",
573 "and", "number", "of", "troops", "on", "them.",
575 rb->lcd_clear_display();
576 rb->lcd_getstringsize(" ", &space_w, &height);
577 for (i = 0; i < WORDS; i++) {
578 rb->lcd_getstringsize(instructions[i], &width, NULL);
579 /* Skip to next line if the current one can't fit the word */
580 if (x + width > LCD_WIDTH - MARGIN) {
581 x = MARGIN;
582 y += height;
584 /* .. or if the word is the empty string */
585 if (rb->strcmp(instructions[i], "") == 0) {
586 x = MARGIN;
587 y += height;
588 continue;
590 /* We filled the screen */
591 if (y + height > LCD_HEIGHT - MARGIN) {
592 y = MARGIN;
593 rb->lcd_update();
594 do {
595 button = rb->button_get(true);
596 if (button == SYS_USB_CONNECTED) {
597 return PLUGIN_USB_CONNECTED;
599 } while( ( button == BUTTON_NONE )
600 || ( button & (BUTTON_REL|BUTTON_REPEAT) ) );
603 rb->lcd_clear_display();
605 rb->lcd_putsxy(x, y, instructions[i]);
606 x += width + space_w;
608 rb->lcd_update();
609 do {
610 button = rb->button_get(true);
611 if (button == SYS_USB_CONNECTED) {
612 return PLUGIN_USB_CONNECTED;
614 } while( ( button == BUTTON_NONE )
615 || ( button & (BUTTON_REL|BUTTON_REPEAT) ) );
617 return 0;
620 int menu(void) {
621 int selection = 0;
623 MENUITEM_STRINGLIST(main_menu,"Super Domination Menu",NULL,
624 "Play Super Domination","Settings","Help","Quit");
626 while(1) {
627 selection=rb->do_menu(&main_menu,&selection, NULL, false);
628 switch(selection) {
629 case 0:
630 return 0; /* start playing */
631 break;
632 case 1:
633 if(settings_menu_function()==PLUGIN_USB_CONNECTED)
634 return PLUGIN_USB_CONNECTED;
635 break;
636 case 2:
637 if(do_help()==PLUGIN_USB_CONNECTED)
638 return PLUGIN_USB_CONNECTED;
639 break;
640 default:
641 return 2; /* quit program */
642 break;
646 return 3;
649 int save_game(void) {
650 int fd;
651 char savepath[MAX_PATH];
653 rb->snprintf(savepath, sizeof(savepath), "/Savegame.ssg");
654 if(rb->kbd_input(savepath, MAX_PATH)) {
655 DEBUGF("Keyboard input failed\n");
656 return -1;
659 fd = rb->open(savepath, O_WRONLY|O_CREAT);
660 DEBUGF("savepath: %s\n", savepath);
661 if(fd < 0) {
662 DEBUGF("Couldn't create/open file\n");
663 return -1;
666 rb->write(fd, "SSGv3", 5);
667 rb->write(fd, &gamestate, sizeof(gamestate));
668 rb->write(fd, &humanres.cash, sizeof(humanres.cash));
669 rb->write(fd, &humanres.food, sizeof(humanres.food));
670 rb->write(fd, &humanres.bank, sizeof(humanres.bank));
671 rb->write(fd, &humanres.planes, sizeof(humanres.planes));
672 rb->write(fd, &humanres.tanks, sizeof(humanres.tanks));
673 rb->write(fd, &humanres.men, sizeof(humanres.men));
674 rb->write(fd, &humanres.nukes, sizeof(humanres.nukes));
675 rb->write(fd, &humanres.inds, sizeof(humanres.inds));
676 rb->write(fd, &humanres.farms, sizeof(humanres.farms));
677 rb->write(fd, &humanres.moves, sizeof(humanres.moves));
678 rb->write(fd, &compres.cash, sizeof(compres.cash));
679 rb->write(fd, &compres.food, sizeof(compres.food));
680 rb->write(fd, &compres.bank, sizeof(compres.bank));
681 rb->write(fd, &compres.planes, sizeof(compres.planes));
682 rb->write(fd, &compres.tanks, sizeof(compres.tanks));
683 rb->write(fd, &compres.men, sizeof(compres.men));
684 rb->write(fd, &compres.nukes, sizeof(compres.nukes));
685 rb->write(fd, &compres.inds, sizeof(compres.inds));
686 rb->write(fd, &compres.farms, sizeof(compres.farms));
687 rb->write(fd, &compres.moves, sizeof(compres.moves));
688 rb->write(fd, board, sizeof(board));
689 rb->write(fd, &superdom_settings.compstartfarms, sizeof(int));
690 rb->write(fd, &superdom_settings.compstartinds, sizeof(int));
691 rb->write(fd, &superdom_settings.humanstartfarms, sizeof(int));
692 rb->write(fd, &superdom_settings.humanstartfarms, sizeof(int));
693 rb->write(fd, &superdom_settings.startcash, sizeof(int));
694 rb->write(fd, &superdom_settings.startfood, sizeof(int));
695 rb->write(fd, &superdom_settings.movesperturn, sizeof(int));
696 rb->close(fd);
697 return 0;
700 int ingame_menu(void) {
701 int selection = 0;
703 MENUITEM_STRINGLIST(ingame_menu,"Super Domination Menu",NULL,
704 "Return to game","Save Game","Playback Control", "Quit");
706 selection=rb->do_menu(&ingame_menu,&selection, NULL, false);
707 switch(selection) {
708 case 0:
709 return 0;
710 break;
711 case 1:
712 if(!save_game())
713 rb->splash(HZ, "Game saved");
714 else
715 rb->splash(HZ, "Error in save");
716 break;
717 case 2:
718 playback_control(NULL);
719 break;
720 case 3:
721 return SUPERDOM_QUIT;
722 break;
723 case MENU_ATTACHED_USB:
724 return PLUGIN_USB_CONNECTED;
725 break;
726 case GO_TO_PREVIOUS:
727 return 0;
728 break;
730 return 0;
733 int get_number(char* param, int* value) {
734 //int numbers[3][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
735 int numbers[3][3];
736 int i,j,x=0,y=0;
737 int height, width;
738 int button = 0;
739 numbers[0][0] = 1;
740 numbers[0][1] = 2;
741 numbers[0][2] = 3;
742 numbers[1][0] = 4;
743 numbers[1][1] = 5;
744 numbers[1][2] = 6;
745 numbers[2][0] = 7;
746 numbers[2][1] = 8;
747 numbers[2][2] = 9;
748 rb->lcd_clear_display();
749 /* Draw a 3x4 grid */
750 for(i=0;i<=3;i++) { /* Vertical lines */
751 rb->lcd_vline(NUM_MARGIN_X+(NUM_BOX_WIDTH*i), NUM_MARGIN_Y,
752 NUM_MARGIN_Y+(4*NUM_BOX_HEIGHT));
754 for(i=0;i<=4;i++) { /* Horizontal lines */
755 rb->lcd_hline(NUM_MARGIN_X, NUM_MARGIN_X+(3*NUM_BOX_WIDTH),
756 NUM_MARGIN_Y+(NUM_BOX_HEIGHT*i));
758 for(i=0;i<3;i++) {
759 for(j=0;j<3;j++) {
760 rb->snprintf(buf, sizeof(buf), "%d", numbers[i][j]);
761 rb->lcd_putsxy(NUM_MARGIN_X+(j*NUM_BOX_WIDTH)+10,
762 NUM_MARGIN_Y+(i*NUM_BOX_HEIGHT)+8, buf);
765 rb->lcd_putsxy(NUM_MARGIN_X+5, NUM_MARGIN_Y+(3*NUM_BOX_HEIGHT)+8, "CLR");
766 rb->lcd_putsxy(NUM_MARGIN_X+NUM_BOX_WIDTH+10,
767 NUM_MARGIN_Y+(3*NUM_BOX_HEIGHT)+8, "0");
768 rb->lcd_putsxy(NUM_MARGIN_X+2*NUM_BOX_WIDTH+8,
769 NUM_MARGIN_Y+(3*NUM_BOX_HEIGHT)+8, "OK");
770 rb->snprintf(buf,sizeof(buf), "%d", *value);
771 rb->lcd_putsxy(NUM_MARGIN_X+10, NUM_MARGIN_Y+4*NUM_BOX_HEIGHT+10, buf);
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 rb->lcd_update();
780 while(1) {
781 button = rb->button_get(true);
782 switch(button) {
783 case SUPERDOM_OK:
784 if(y!=3) {
785 *value *= 10;
786 *value += numbers[y][x];
787 } else if(x==0) {
788 *value /= 10;
789 } else if(x==1) {
790 *value *= 10;
791 } else if(x==2) {
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 *value = 0;
804 rb->splash(HZ, "Cancelled");
805 return 2;
806 break;
807 #if CONFIG_KEYPAD != IRIVER_H10_PAD
808 case SUPERDOM_LEFT:
809 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
810 rb->lcd_fillrect(NUM_MARGIN_X+(NUM_BOX_WIDTH*x),
811 NUM_MARGIN_Y+(NUM_BOX_HEIGHT*y),
812 NUM_BOX_WIDTH+1, NUM_BOX_HEIGHT+1);
813 rb->lcd_set_drawmode(DRMODE_SOLID);
814 if(x==0) {
815 #ifdef IPOD_STYLE
816 if(y>0)
817 y--;
818 else
819 y=3;
820 #endif
821 x=2;
822 } else {
823 x--;
825 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
826 rb->lcd_fillrect(NUM_MARGIN_X+(NUM_BOX_WIDTH*x),
827 NUM_MARGIN_Y+(NUM_BOX_HEIGHT*y),
828 NUM_BOX_WIDTH+1, NUM_BOX_HEIGHT+1);
829 rb->lcd_set_drawmode(DRMODE_SOLID);
830 break;
831 case SUPERDOM_RIGHT:
832 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
833 rb->lcd_fillrect(NUM_MARGIN_X+(NUM_BOX_WIDTH*x),
834 NUM_MARGIN_Y+(NUM_BOX_HEIGHT*y),
835 NUM_BOX_WIDTH+1, NUM_BOX_HEIGHT+1);
836 rb->lcd_set_drawmode(DRMODE_SOLID);
837 if(x==2) {
838 #ifdef IPOD_STYLE
839 if(y==3)
840 y=0;
841 else
842 y++;
843 #endif
844 x=0;
845 } else {
846 x++;
848 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
849 rb->lcd_fillrect(NUM_MARGIN_X+(NUM_BOX_WIDTH*x),
850 NUM_MARGIN_Y+(NUM_BOX_HEIGHT*y),
851 NUM_BOX_WIDTH+1, NUM_BOX_HEIGHT+1);
852 rb->lcd_set_drawmode(DRMODE_SOLID);
853 break;
854 #endif
855 #ifndef IPOD_STYLE
856 case SUPERDOM_UP:
857 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
858 rb->lcd_fillrect(NUM_MARGIN_X+(NUM_BOX_WIDTH*x),
859 NUM_MARGIN_Y+(NUM_BOX_HEIGHT*y),
860 NUM_BOX_WIDTH+1, NUM_BOX_HEIGHT+1);
861 rb->lcd_set_drawmode(DRMODE_SOLID);
862 if(y==0) {
863 #if CONFIG_KEYPAD == IRIVER_H10_PAD
864 if(x > 0)
865 x--;
866 else
867 x=2;
868 #endif
869 y=3;
870 } else {
871 y--;
873 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
874 rb->lcd_fillrect(NUM_MARGIN_X+(NUM_BOX_WIDTH*x),
875 NUM_MARGIN_Y+(NUM_BOX_HEIGHT*y),
876 NUM_BOX_WIDTH+1, NUM_BOX_HEIGHT+1);
877 rb->lcd_set_drawmode(DRMODE_SOLID);
878 break;
879 case SUPERDOM_DOWN:
880 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
881 rb->lcd_fillrect(NUM_MARGIN_X+(NUM_BOX_WIDTH*x),
882 NUM_MARGIN_Y+(NUM_BOX_HEIGHT*y),
883 NUM_BOX_WIDTH+1, NUM_BOX_HEIGHT+1);
884 rb->lcd_set_drawmode(DRMODE_SOLID);
885 if(y==3) {
886 #if CONFIG_KEYPAD == IRIVER_H10_PAD
887 if(x < 2)
888 x++;
889 else
890 x=0;
891 #endif
892 y=0;
893 } else {
894 y++;
896 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
897 rb->lcd_fillrect(NUM_MARGIN_X+(NUM_BOX_WIDTH*x),
898 NUM_MARGIN_Y+(NUM_BOX_HEIGHT*y),
899 NUM_BOX_WIDTH+1, NUM_BOX_HEIGHT+1);
900 rb->lcd_set_drawmode(DRMODE_SOLID);
901 break;
902 #endif
903 default:
904 if (rb->default_event_handler(button) == SYS_USB_CONNECTED)
906 return PLUGIN_USB_CONNECTED;
908 break;
910 rb->lcd_update();
912 return 0;
915 bool tile_has_item(int type, int x, int y) {
916 switch(type) {
917 case 0:
918 return (board[x][y].men > 0);
919 break;
920 case 1:
921 return board[x][y].tank;
922 break;
923 case 2:
924 return board[x][y].plane;
925 break;
926 case 3:
927 return board[x][y].farm;
928 break;
929 case 4:
930 return board[x][y].ind;
931 break;
932 case 5:
933 return board[x][y].nuke;
934 break;
936 return false;
939 int buy_resources(int colour, int type, int x, int y, int nummen) {
940 const char *itemnames[][6] = {
942 "them",
943 "the tank",
944 "the plane",
945 "the farm",
946 "the industrial plant",
947 "the nuke",
948 }, {
949 "place men",
950 "place a tank",
951 "place a plane",
952 "build a farm",
953 "build an industrial plant",
954 "place a nuke",
955 }, {
956 NULL,
957 "a tank",
958 "a plane",
959 "a farm",
960 "an industrial plant",
961 "a nuke",
965 bool human = (colour == COLOUR_LIGHT);
966 int price = 0;
967 struct resources *res;
969 if(human) {
970 res = &humanres;
971 } else {
972 res = &compres;
974 switch(type) {
975 case 0: /* men */
976 price = 1*nummen;
977 break;
978 case 1: /* tank */
979 price = 300;
980 break;
981 case 2: /* plane */
982 price = 600;
983 break;
984 case 3: /* Farm */
985 price = 1150;
986 break;
987 case 4: /* Factory */
988 price = 1300;
989 break;
990 case 5: /* nuke */
991 price = 2000;
992 break;
994 if(res->cash < price) {
995 if(human)
996 rb->splash(HZ, "Not enough money!");
997 return 2;
999 if(human) {
1000 rb->splashf(HZ, "Where do you want to place %s?", itemnames[0][type]);
1001 switch(select_square()) {
1002 case 2:
1003 return 2;
1004 break;
1005 case PLUGIN_USB_CONNECTED:
1006 return PLUGIN_USB_CONNECTED;
1007 break;
1009 x = cursor.x;
1010 y = cursor.y;
1012 if(board[x][y].colour != colour) {
1013 if(human)
1014 rb->splashf(HZ, "Can't %s on enemy territory", itemnames[1][type]);
1015 return 2;
1017 if(type != 0 && tile_has_item(type, x, y)) {
1018 if(human)
1019 rb->splashf(HZ, "There is already %s there", itemnames[2][type]);
1020 return 2;
1022 switch(type) {
1023 case 0:
1024 board[x][y].men += nummen;
1025 res->men += nummen;
1026 break;
1027 case 1:
1028 board[x][y].tank = true;
1029 res->tanks++;
1030 break;
1031 case 2:
1032 board[x][y].plane = true;
1033 res->planes++;
1034 break;
1035 case 3:
1036 board[x][y].farm = true;
1037 res->farms++;
1038 break;
1039 case 4:
1040 board[x][y].ind = true;
1041 res->inds++;
1042 break;
1043 case 5:
1044 board[x][y].nuke = true;
1045 res->nukes++;
1046 break;
1048 res->cash -= price;
1050 draw_board();
1051 rb->sleep(HZ);
1053 return 0;
1056 int buy_resources_menu(void) {
1057 int selection,nummen;
1059 MENUITEM_STRINGLIST(res_menu, "Buy Resources", NULL, "Buy men ($1)",
1060 "Buy tank ($300)", "Buy plane ($600)", "Buy Farm ($1150)",
1061 "Buy Factory ($1300)", "Buy Nuke ($2000)",
1062 "Finish buying");
1064 while(1) {
1065 selection=rb->do_menu(&res_menu,&selection, NULL, false);
1066 switch(selection) {
1067 case 0:
1068 nummen = 0;
1069 if(get_number("How many men would you like?", &nummen)
1070 == PLUGIN_USB_CONNECTED)
1071 return PLUGIN_USB_CONNECTED;
1072 if(!nummen)
1073 break;
1074 /* fall through */
1075 case 1:
1076 case 2:
1077 case 3:
1078 case 4:
1079 case 5:
1080 if(buy_resources(COLOUR_LIGHT, selection, 0, 0, nummen)
1081 == PLUGIN_USB_CONNECTED)
1082 return PLUGIN_USB_CONNECTED;
1083 break;
1084 case 6:
1085 return 0;
1086 break;
1087 case MENU_ATTACHED_USB:
1088 return PLUGIN_USB_CONNECTED;
1089 break;
1090 case GO_TO_PREVIOUS:
1091 return 0;
1092 break;
1095 return 0;
1098 int move_unit(int colour, int type, int fromx, int fromy,
1099 int tox, int toy, int nummen) {
1100 const char *itemnames[][3] = {
1102 "troops",
1103 "the tank",
1104 "the plane",
1105 }, {
1106 "any troops",
1107 "a tank",
1108 "a plane",
1109 }, {
1110 "the troops",
1111 "the tank",
1112 "the plane",
1115 bool human = (colour == COLOUR_LIGHT);
1117 if(human) {
1118 rb->splashf(HZ, "Select where you want to move %s from",
1119 itemnames[0][type]);
1120 switch(select_square()) {
1121 case 2:
1122 return 2;
1123 break;
1124 case PLUGIN_USB_CONNECTED:
1125 return PLUGIN_USB_CONNECTED;
1126 break;
1128 fromx = cursor.x;
1129 fromy = cursor.y;
1131 if(board[fromx][fromy].colour != colour) {
1132 if(human)
1133 rb->splash(HZ, "That isn't your territory");
1134 return 2;
1136 if(!tile_has_item(type, fromx, fromy)) {
1137 if(human)
1138 rb->splashf(HZ, "You don't have %s there", itemnames[1][type]);
1139 return 2;
1141 if(type == 0) {
1142 if(human) {
1143 nummen = board[fromx][fromy].men;
1144 switch(get_number("How many men do you want to move?", &nummen)) {
1145 case 2:
1146 return 2;
1147 break;
1148 case PLUGIN_USB_CONNECTED:
1149 return PLUGIN_USB_CONNECTED;
1150 break;
1153 if(nummen > board[fromx][fromy].men) {
1154 if(human)
1155 rb->splash(HZ, "You don't have that many troops.");
1156 return 2;
1159 if(human) {
1160 rb->splashf(HZ, "Select where you want to move %s to",
1161 itemnames[2][type]);
1162 switch(select_square()) {
1163 case 2:
1164 return 2;
1165 break;
1166 case PLUGIN_USB_CONNECTED:
1167 return PLUGIN_USB_CONNECTED;
1168 break;
1170 tox = cursor.x;
1171 toy = cursor.y;
1173 if((tox == fromx && toy == fromy) ||
1174 board[tox][toy].colour != colour ||
1175 (type != 2 && (abs(tox - fromx) > 1 || abs(toy - fromy) > 1))) {
1176 if(human)
1177 rb->splash(HZ, "Invalid move");
1178 return 2;
1180 if(type != 0 && tile_has_item(type, tox, toy)) {
1181 if(human)
1182 rb->splashf(HZ, "There is already %s there", itemnames[1][type]);
1183 return 2;
1185 switch(type) {
1186 case 0:
1187 board[fromx][fromy].men -= nummen;
1188 board[tox][toy].men += nummen;
1189 break;
1190 case 1:
1191 board[fromx][fromy].tank = false;
1192 board[tox][toy].tank = true;
1193 break;
1194 case 2:
1195 board[fromx][fromy].plane = false;
1196 board[tox][toy].plane = true;
1197 break;
1199 return 0;
1202 int move_unit_menu(void) {
1203 int selection;
1205 MENUITEM_STRINGLIST(move_unit_menu, "Move unit", NULL, "Move men",
1206 "Move tank", "Move plane");
1207 selection=rb->do_menu(&move_unit_menu,&selection, NULL, false);
1208 switch(selection) {
1209 case 0:
1210 case 1:
1211 case 2:
1212 switch(move_unit(COLOUR_LIGHT, selection, 0, 0, 0, 0, 0)) {
1213 case 0:
1214 humanres.moves--;
1215 break;
1216 case PLUGIN_USB_CONNECTED:
1217 return PLUGIN_USB_CONNECTED;
1218 break;
1220 break;
1221 case MENU_ATTACHED_USB:
1222 return PLUGIN_USB_CONNECTED;
1224 return 0;
1227 int launch_nuke(int colour, int nukex, int nukey, int targetx, int targety) {
1228 bool human = (colour == COLOUR_LIGHT);
1229 struct resources *res;
1231 if(board[nukex][nukey].colour != colour) {
1232 if(human)
1233 rb->splash(HZ, "That isn't your territory");
1234 return 2;
1236 if(! board[nukex][nukey].nuke) {
1237 if(human)
1238 rb->splashf(HZ, "You don't have %s there", "a nuke");
1239 return 2;
1241 if(human) {
1242 rb->splash(HZ, "Select place to target with nuke");
1243 switch(select_square()) {
1244 case 2:
1245 return 2;
1246 break;
1247 case PLUGIN_USB_CONNECTED:
1248 return PLUGIN_USB_CONNECTED;
1249 break;
1251 targetx = cursor.x;
1252 targety = cursor.y;
1254 if(human) {
1255 humanres.nukes--;
1256 } else {
1257 compres.nukes--;
1259 board[nukex][nukey].nuke = false;
1261 if(board[targetx][targety].colour == COLOUR_LIGHT) {
1262 res = &humanres;
1263 } else {
1264 res = &compres;
1266 res->men -= board[targetx][targety].men;
1267 res->tanks -= board[targetx][targety].tank;
1268 res->planes -= board[targetx][targety].plane;
1269 res->nukes -= board[targetx][targety].nuke;
1270 res->farms -= board[targetx][targety].farm;
1271 res->inds -= board[targetx][targety].ind;
1272 board[targetx][targety].men = 0;
1273 board[targetx][targety].tank = false;
1274 board[targetx][targety].plane = false;
1275 board[targetx][targety].ind = false;
1276 board[targetx][targety].nuke = false;
1277 board[targetx][targety].farm = false;
1278 /* TODO: Fallout carried by wind */
1280 return 0;
1283 int movement_menu(void) {
1284 int selection, tempmenu;
1286 MENUITEM_STRINGLIST(move_menu, "Movement", NULL, "Move unit",
1287 "Buy additional moves ($100)", "Launch nuclear missile",
1288 "Check map", "Finish moving", "Game menu");
1290 while(1) {
1291 selection=rb->do_menu(&move_menu,&selection, NULL, false);
1292 switch(selection) {
1293 case 0:
1294 if(humanres.moves) {
1295 if(move_unit_menu()==PLUGIN_USB_CONNECTED)
1296 return PLUGIN_USB_CONNECTED;
1297 } else {
1298 rb->splash(HZ, "You have no more moves left."
1299 " You can buy more for $100 each.");
1301 break;
1302 case 1:
1303 if(humanres.cash > 100) {
1304 humanres.moves++;
1305 humanres.cash -= 100;
1306 rb->snprintf(buf, sizeof(buf), "You now have %d moves",
1307 humanres.moves);
1308 rb->splash(HZ, buf);
1310 break;
1311 case 2:
1312 if(humanres.nukes==0) {
1313 rb->splash(HZ, "You do not have any nukes to launch");
1314 } else {
1315 rb->splash(HZ, "Select place to launch nuke from");
1316 switch(select_square()) {
1317 case 0:
1318 if(launch_nuke(COLOUR_LIGHT, cursor.x, cursor.y,
1319 0, 0) == PLUGIN_USB_CONNECTED)
1320 return PLUGIN_USB_CONNECTED;
1321 break;
1322 case PLUGIN_USB_CONNECTED:
1323 return PLUGIN_USB_CONNECTED;
1324 break;
1327 break;
1328 case 3:
1329 if(select_square() == PLUGIN_USB_CONNECTED)
1330 return PLUGIN_USB_CONNECTED;
1331 break;
1332 case 4:
1333 return 0;
1334 break;
1335 case 5:
1336 tempmenu = ingame_menu();
1337 switch(tempmenu) {
1338 case PLUGIN_USB_CONNECTED:
1339 return PLUGIN_USB_CONNECTED;
1340 break;
1341 case SUPERDOM_QUIT:
1342 return SUPERDOM_QUIT;
1343 break;
1345 break;
1346 case MENU_ATTACHED_USB:
1347 return PLUGIN_USB_CONNECTED;
1348 break;
1351 return 0;
1354 int show_inventory(void) {
1355 char men[20], tanks[20], planes[20], inds[20], farms[20], nukes[20],
1356 cash[20], food[20], bank[20];
1357 rb->snprintf(men, sizeof(men), "Men: %d", humanres.men);
1358 rb->snprintf(tanks, sizeof(tanks), "Tanks: %d", humanres.tanks);
1359 rb->snprintf(planes, sizeof(planes), "Planes: %d", humanres.planes);
1360 rb->snprintf(inds, sizeof(inds), "Factories: %d", humanres.inds);
1361 rb->snprintf(farms, sizeof(farms), "Farms: %d", humanres.farms);
1362 rb->snprintf(nukes, sizeof(nukes), "Nukes: %d", humanres.nukes);
1363 rb->snprintf(cash, sizeof(cash), "Cash: %d", humanres.cash);
1364 rb->snprintf(food, sizeof(food), "Food: %d", humanres.food);
1365 rb->snprintf(bank, sizeof(bank), "Bank: %d", humanres.bank);
1366 rb->lcd_clear_display();
1367 rb->lcd_puts(1, 0, "Inventory");
1368 rb->lcd_puts(2, 1, men);
1369 rb->lcd_puts(2, 2, tanks);
1370 rb->lcd_puts(2, 3, planes);
1371 rb->lcd_puts(2, 4, inds);
1372 rb->lcd_puts(2, 5, farms);
1373 rb->lcd_puts(2, 6, nukes);
1374 rb->lcd_puts(2, 7, cash);
1375 rb->lcd_puts(2, 8, food);
1376 rb->lcd_puts(2, 9, bank);
1377 rb->lcd_update();
1378 if(rb->default_event_handler(rb->button_get(true)) == SYS_USB_CONNECTED) {
1379 return PLUGIN_USB_CONNECTED;
1380 } else {
1381 return 0;
1385 int production_menu(void) {
1386 int selection, tempbank, tempmenu;
1388 MENUITEM_STRINGLIST(prod_menu, "Production", NULL, "Buy resources",
1389 "Show inventory", "Check map", "Invest money",
1390 "Withdraw money", "Finish turn", "Game menu");
1392 while(1) {
1393 selection=rb->do_menu(&prod_menu,&selection, NULL, false);
1394 switch(selection) {
1395 case 0:
1396 if(buy_resources_menu() == PLUGIN_USB_CONNECTED)
1397 return PLUGIN_USB_CONNECTED;
1398 break;
1399 case 1:
1400 if(show_inventory() == PLUGIN_USB_CONNECTED)
1401 return PLUGIN_USB_CONNECTED;
1402 break;
1403 case 2:
1404 if(select_square() == PLUGIN_USB_CONNECTED)
1405 return PLUGIN_USB_CONNECTED;
1406 break;
1407 case 3:
1408 tempbank = humanres.cash;
1409 if(get_number("How much do you want to invest?", &tempbank)
1410 == PLUGIN_USB_CONNECTED)
1411 return PLUGIN_USB_CONNECTED;
1412 if(tempbank>humanres.cash) {
1413 rb->splash(HZ, "You don't have that much cash to invest");
1414 } else {
1415 humanres.cash -= tempbank;
1416 humanres.bank += tempbank;
1418 break;
1419 case 4:
1420 tempbank = 0;
1421 if(get_number("How much do you want to withdraw?", &tempbank)
1422 == PLUGIN_USB_CONNECTED)
1423 return PLUGIN_USB_CONNECTED;
1424 if(tempbank>humanres.bank) {
1425 rb->splash(HZ, "You don't have that much cash to withdraw");
1426 } else {
1427 humanres.cash += tempbank;
1428 humanres.bank -= tempbank;
1430 break;
1431 case 5:
1432 return 0;
1433 break;
1434 case 6:
1435 tempmenu = ingame_menu();
1436 switch(tempmenu) {
1437 case PLUGIN_USB_CONNECTED:
1438 return PLUGIN_USB_CONNECTED;
1439 break;
1440 case SUPERDOM_QUIT:
1441 return SUPERDOM_QUIT;
1442 break;
1444 break;
1445 case MENU_ATTACHED_USB:
1446 return PLUGIN_USB_CONNECTED;
1447 break;
1450 return 0;
1453 void init_resources(void) {
1454 humanres.cash = superdom_settings.startcash;
1455 humanres.food = superdom_settings.startfood;
1456 humanres.tanks = 0;
1457 humanres.planes = 0;
1458 humanres.nukes = 0;
1459 humanres.inds = 0;
1460 humanres.farms = 0;
1461 humanres.men = 0;
1462 humanres.bank = 0;
1463 humanres.moves = 0;
1464 compres.cash = superdom_settings.startcash;
1465 compres.food = superdom_settings.startfood;
1466 compres.tanks = 0;
1467 compres.planes = 0;
1468 compres.nukes = 0;
1469 compres.inds = 0;
1470 compres.farms = 0;
1471 compres.men = 0;
1472 compres.bank = 0;
1473 compres.moves = 0;
1476 int select_square(void) {
1477 int button = 0;
1478 draw_board();
1479 draw_cursor();
1480 update_score();
1481 #if LCD_WIDTH >= 220
1482 rb->lcd_setfont(FONT_SYSFIXED);
1483 rb->snprintf(buf, sizeof(buf), "Cash: %d", humanres.cash);
1484 rb->lcd_putsxy(125, LCD_HEIGHT-20, buf);
1485 rb->snprintf(buf, sizeof(buf), "Food: %d", humanres.food);
1486 rb->lcd_putsxy(125, LCD_HEIGHT-10, buf);
1487 rb->lcd_setfont(FONT_UI);
1488 #endif
1489 rb->lcd_update();
1490 while(1) {
1491 button = rb->button_get(true);
1492 switch(button) {
1493 case SUPERDOM_CANCEL:
1494 rb->splash(HZ, "Cancelled");
1495 return 2;
1496 break;
1497 case SUPERDOM_OK:
1498 return 0;
1499 break;
1500 #if CONFIG_KEYPAD != IRIVER_H10_PAD
1501 case SUPERDOM_LEFT:
1502 case (SUPERDOM_LEFT|BUTTON_REPEAT):
1503 draw_cursor(); /* Deselect the current tile */
1504 if(cursor.x>1) {
1505 cursor.x--;
1506 } else {
1507 #ifdef IPOD_STYLE
1508 if(cursor.y>1)
1509 cursor.y--;
1510 else
1511 cursor.y = 10;
1512 #endif
1513 cursor.x = 10;
1515 update_score();
1516 draw_cursor();
1517 break;
1518 case SUPERDOM_RIGHT:
1519 case (SUPERDOM_RIGHT|BUTTON_REPEAT):
1520 draw_cursor(); /* Deselect the current tile */
1521 if(cursor.x<10) {
1522 cursor.x++;
1523 } else {
1524 #ifdef IPOD_STYLE
1525 if(cursor.y<10)
1526 cursor.y++;
1527 else
1528 cursor.y = 1;
1529 #endif
1530 cursor.x = 1;
1532 update_score();
1533 draw_cursor();
1534 break;
1535 #endif
1536 #ifndef IPOD_STYLE
1537 case SUPERDOM_UP:
1538 case (SUPERDOM_UP|BUTTON_REPEAT):
1539 draw_cursor(); /* Deselect the current tile */
1540 if(cursor.y>1) {
1541 cursor.y--;
1542 } else {
1543 #if CONFIG_KEYPAD == IRIVER_H10_PAD
1544 if(cursor.x > 1)
1545 cursor.x--;
1546 else
1547 cursor.x = 10;
1548 #endif
1549 cursor.y = 10;
1551 update_score();
1552 draw_cursor();
1553 break;
1554 case SUPERDOM_DOWN:
1555 case (SUPERDOM_DOWN|BUTTON_REPEAT):
1556 draw_cursor(); /* Deselect the current tile */
1557 if(cursor.y<10) {
1558 cursor.y++;
1559 } else {
1560 #if CONFIG_KEYPAD == IRIVER_H10_PAD
1561 if(cursor.x < 10)
1562 cursor.x++;
1563 else
1564 cursor.x = 1;
1565 #endif
1566 cursor.y = 1;
1568 update_score();
1569 draw_cursor();
1570 break;
1571 #endif
1572 default:
1573 if (rb->default_event_handler(button) == SYS_USB_CONNECTED)
1575 return PLUGIN_USB_CONNECTED;
1581 int killmen(int colour) {
1582 bool human = (colour == COLOUR_LIGHT);
1583 int menkilled,i,j;
1584 int percent;
1585 if(human) {
1586 percent = (humanres.food*1000)/humanres.men;
1587 humanres.food = 0;
1588 } else {
1589 percent = (compres.food*1000)/compres.men;
1590 compres.food = 0;
1592 menkilled = 0;
1593 for(i=1;i<11;i++) {
1594 for(j=1;j<11;j++) {
1595 if(board[i][j].colour == colour) {
1596 int nummen = ((board[i][j].men * percent)/1000);
1597 menkilled += board[i][j].men - nummen;
1598 board[i][j].men = nummen;
1603 if(human)
1604 humanres.men -= menkilled;
1605 else
1606 compres.men -= menkilled;
1607 return menkilled;
1610 /* return -1 if error, 1 if attack is succeeded, 0 otherwise */
1611 int attack_territory(int colour, int x, int y) {
1612 bool human = (colour == COLOUR_LIGHT);
1613 int str_diff;
1615 if(board[x][y].colour == colour) {
1616 if(human)
1617 rb->splash(HZ, "You can't attack your own territory");
1618 return -1;
1620 str_diff = calc_strength(COLOUR_DARK, x, y) -
1621 calc_strength(COLOUR_LIGHT, x, y);
1622 if(human) {
1623 str_diff = -str_diff;
1625 rb->srand(*rb->current_tick);
1626 if(str_diff > 0 || (str_diff == 0 && rb->rand()%2)) {
1627 struct resources *offres, *defres;
1628 if(human) {
1629 offres = &humanres;
1630 defres = &compres;
1631 } else {
1632 offres = &compres;
1633 defres = &humanres;
1635 defres->men -= board[x][y].men;
1636 defres->tanks -= board[x][y].tank;
1637 defres->planes -= board[x][y].plane;
1638 defres->nukes -= board[x][y].nuke;
1639 defres->farms -= board[x][y].farm;
1640 defres->inds -= board[x][y].ind;
1641 offres->farms += board[x][y].farm;
1642 offres->inds += board[x][y].ind;
1643 board[x][y].colour = colour;
1644 board[x][y].men = 0;
1645 board[x][y].tank = false;
1646 board[x][y].plane = false;
1647 board[x][y].nuke = false;
1648 draw_board();
1649 if(human)
1650 rb->sleep(HZ*2);
1651 else
1652 rb->sleep(HZ);
1653 return 1;
1654 } else {
1655 if(human)
1656 rb->splash(HZ, "Your troops were unable to overcome"
1657 " the enemy troops");
1658 else
1659 rb->splash(HZ*2, "The computer attempted to "
1660 "attack, but the invasion was"
1661 " pushed back");
1662 return 0;
1664 return 0;
1667 int war_menu(void) {
1668 int selection, tempmenu;
1670 MENUITEM_STRINGLIST(wartime_menu, "War!", NULL,
1671 "Select territory to attack", "Finish turn", "Game menu");
1673 while(humanres.moves) {
1674 selection=rb->do_menu(&wartime_menu,&selection, NULL, false);
1675 switch(selection) {
1676 case 0:
1677 switch(select_square()) {
1678 case 0:
1679 if(attack_territory(COLOUR_LIGHT, cursor.x, cursor.y)
1680 >= 0)
1681 humanres.moves--;
1682 break;
1683 case PLUGIN_USB_CONNECTED:
1684 return PLUGIN_USB_CONNECTED;
1685 break;
1687 break;
1688 case 1:
1689 return 0;
1690 break;
1691 case 2:
1692 tempmenu = ingame_menu();
1693 switch(tempmenu) {
1694 case PLUGIN_USB_CONNECTED:
1695 return PLUGIN_USB_CONNECTED;
1696 break;
1697 case SUPERDOM_QUIT:
1698 return SUPERDOM_QUIT;
1699 break;
1701 break;
1704 return 0;
1707 struct threat {
1708 int x;
1709 int y;
1710 int str_diff;
1713 bool place_adjacent(bool tank, int x, int y) {
1714 int type = (tank? 1: 2);
1715 if(!buy_resources(COLOUR_DARK, type, x, y, 0)) {
1716 return true;
1718 if(!buy_resources(COLOUR_DARK, type, x-1, y, 0)) {
1719 return true;
1721 if(!buy_resources(COLOUR_DARK, type, x+1, y, 0)) {
1722 return true;
1724 if(!buy_resources(COLOUR_DARK, type, x, y-1, 0)) {
1725 return true;
1727 if(!buy_resources(COLOUR_DARK, type, x, y+1, 0)) {
1728 return true;
1730 return false;
1733 bool has_adjacent(int x, int y) {
1734 if((board[x][y].colour == COLOUR_LIGHT) &&
1735 ((board[x-1][y].colour == COLOUR_DARK) ||
1736 (board[x+1][y].colour == COLOUR_DARK) ||
1737 (board[x][y+1].colour == COLOUR_DARK) ||
1738 (board[x][y-1].colour == COLOUR_DARK)))
1739 return 1;
1740 else
1741 return 0;
1744 void find_adjacent(int x, int y, int* adj_x, int* adj_y) {
1745 /* Finds adjacent squares, returning squares without tanks on them
1746 * in preference to those with them */
1747 if(board[x-1][y].colour == COLOUR_DARK) {
1748 *adj_x = x-1;
1749 *adj_y = y;
1750 return;
1752 if(board[x+1][y].colour == COLOUR_DARK) {
1753 *adj_x = x+1;
1754 *adj_y = y;
1755 return;
1757 if(board[x][y-1].colour == COLOUR_DARK) {
1758 *adj_x = x;
1759 *adj_y = y-1;
1760 return;
1762 if(board[x][y+1].colour == COLOUR_DARK) {
1763 *adj_x = x;
1764 *adj_y = y+1;
1765 return;
1769 void computer_allocate(void) {
1770 /* Firstly, decide whether to go offensive or defensive.
1771 * This is primarily decided by the human player posing a threat to either
1772 * the computer's farms or factories */
1773 int i, j, k;
1774 bool offensive = true;
1775 struct threat threats[4];
1776 int numthreats = 0;
1777 int total_str_diff = 0;
1778 int numterritory = 0;
1779 int str_diff;
1780 int men_needed;
1781 struct threat targets[2];
1782 int numtargets;
1783 struct cursor adj;
1785 compres.cash += compres.bank;
1786 compres.bank = 0;
1787 for(i=1;i<11;i++) {
1788 for(j=1;j<11;j++) {
1789 if(board[i][j].colour == COLOUR_DARK) {
1790 numterritory++;
1791 str_diff = calc_strength(COLOUR_LIGHT,i,j) -
1792 calc_strength(COLOUR_DARK,i,j);
1793 if(str_diff > 0 && (board[i][j].ind || board[i][j].farm)) {
1794 if(numthreats < 3) {
1795 offensive = false;
1796 threats[numthreats].x = i;
1797 threats[numthreats].y = j;
1798 threats[numthreats].str_diff = str_diff;
1799 numthreats++;
1803 rb->yield();
1806 if(offensive) {
1807 /* The AI is going to go straight for the throat here and attack
1808 * the player's farms and factories. The amount of cash
1809 * the AI has to spend will determine how many targets there are */
1810 if(compres.cash > 1200) {
1811 /* 1200 is a figure I pulled out of nowhere. Adjust as needed */
1812 numtargets = 2;
1813 } else {
1814 numtargets = 1;
1816 /* Work out which target(s) to attack. They must have adjacent squares
1817 * owned by the computer. If none are found just place troops in
1818 * random places around the map until we run out of money */
1819 k = 0;
1820 for(i=1;i<11;i++) {
1821 for(j=1;j<11;j++) {
1822 if(has_adjacent(i,j) &&
1823 (board[i][j].ind || board[i][j].farm)) {
1824 if(k<numtargets) {
1825 targets[k].x = i;
1826 targets[k].y = j;
1827 targets[k].str_diff =
1828 calc_strength(COLOUR_LIGHT, i, j) -
1829 calc_strength(COLOUR_DARK, i, j);
1830 k++;
1833 rb->yield();
1836 if(k == 0) {
1837 /* No targets found! Randomly pick squares and if they're owned
1838 * by the computer then stick a tank on it. */
1839 rb->srand(*rb->current_tick);
1840 while(compres.cash >= 300 && compres.tanks < numterritory) {
1841 i = rb->rand()%10 + 1;
1842 j = rb->rand()%10 + 1;
1843 if(board[i][j].colour == COLOUR_DARK) {
1844 buy_resources(COLOUR_DARK, 1, i, j, 0);
1846 rb->yield();
1848 } else {
1849 for(i=0;i<k;i++) {
1850 str_diff = targets[i].str_diff;
1851 while(str_diff + 20 > 0 && compres.cash > 0) {
1852 /* While we still need them keep placing men */
1853 if(!place_adjacent(true, targets[i].x, targets[i].y)) {
1854 find_adjacent(targets[i].x, targets[i].y,
1855 &adj.x, &adj.y);
1856 men_needed = (str_diff + 20)*1000/133;
1857 if(compres.cash < men_needed) {
1858 men_needed = compres.cash;
1860 buy_resources(COLOUR_DARK, 0, adj.x, adj.y,
1861 men_needed);
1862 break;
1864 str_diff = calc_strength(COLOUR_LIGHT,
1865 targets[i].x, targets[i].y) -
1866 calc_strength(COLOUR_DARK,
1867 targets[i].x, targets[i].y);
1871 } else {
1872 /* Work out what to place on each square to defend it.
1873 * Tanks are preferential because they do not require food,
1874 * but if the budget is tight then we fall back onto troops.
1875 * Conversely if cash is not an issue and there are already tanks in
1876 * place planes will be deployed. We would like a margin of at least
1877 * 20 points to be safe. */
1879 for(i=0;i<numthreats;i++) {
1880 total_str_diff += threats[i].str_diff;
1882 if((total_str_diff+20)*10 > compres.cash) {
1883 /* Not enough cash to accomodate all threats using tanks alone -
1884 * use men as a backup */
1885 for(i=0;i<numthreats;i++) {
1886 men_needed = ((threats[i].str_diff + 20)*1000)/133;
1887 if(compres.cash < men_needed) {
1888 men_needed = compres.cash;
1890 buy_resources(COLOUR_DARK, 0, threats[i].x, threats[i].y,
1891 men_needed);
1893 } else {
1894 /* Tanks it is */
1895 /* Enough money to pay their way by planes? */
1896 bool tank = ((total_str_diff+20)*15 >= compres.cash);
1897 for(i=0;i<numthreats;i++) {
1898 str_diff = threats[i].str_diff;
1899 while(str_diff + 20 > 0) {
1900 if(!place_adjacent(tank, threats[i].x, threats[i].y)) {
1901 /* No room for any more planes or tanks, revert to
1902 * men */
1903 find_adjacent(threats[i].x, threats[i].y,
1904 &adj.x, &adj.y);
1905 men_needed = (str_diff + 20)*1000/133;
1906 if(compres.cash < men_needed) {
1907 men_needed = compres.cash;
1909 buy_resources(COLOUR_DARK, 0, threats[i].x,
1910 threats[i].y, men_needed);
1911 break;
1913 str_diff = calc_strength(COLOUR_LIGHT,
1914 threats[i].x, threats[i].y) -
1915 calc_strength(COLOUR_DARK,
1916 threats[i].x, threats[i].y);
1921 compres.bank += compres.cash;
1922 compres.cash = 0;
1925 int find_adj_target(int x, int y, struct cursor* adj) {
1926 /* Find a square next to a computer's farm or factory owned by the player
1927 * that is vulnerable. Return 1 on success, 0 otherwise */
1928 if(board[x+1][y].colour == COLOUR_LIGHT &&
1929 calc_strength(COLOUR_LIGHT,x+1,y)<=calc_strength(COLOUR_DARK,x+1,y)) {
1930 adj->x = x+1;
1931 adj->y = y;
1932 return 1;
1934 if(board[x-1][y].colour == COLOUR_LIGHT &&
1935 calc_strength(COLOUR_LIGHT,x-1,y)<=calc_strength(COLOUR_DARK,x-1,y)) {
1936 adj->x = x-1;
1937 adj->y = y;
1938 return 1;
1940 if(board[x][y+1].colour == COLOUR_LIGHT &&
1941 calc_strength(COLOUR_LIGHT,x,y+1)<=calc_strength(COLOUR_DARK,x,y+1)) {
1942 adj->x = x;
1943 adj->y = y+1;
1944 return 1;
1946 if(board[x][y-1].colour == COLOUR_LIGHT &&
1947 calc_strength(COLOUR_LIGHT,x,y-1)<=calc_strength(COLOUR_DARK,x,y-1)) {
1948 adj->x = x;
1949 adj->y = y-1;
1950 return 1;
1952 return 0;
1955 void computer_war(void) {
1956 /* Work out where to attack - prioritise the defence of buildings */
1957 int i, j;
1958 bool found_target = true;
1959 struct cursor adj;
1961 while(found_target) {
1962 found_target = false;
1963 for(i=1;i<11;i++) {
1964 for(j=1;j<11;j++) {
1965 if((board[i][j].colour == COLOUR_DARK) &&
1966 (board[i][j].farm || board[i][j].ind) &&
1967 find_adj_target(i, j, &adj)) {
1968 found_target = true;
1969 if(attack_territory(COLOUR_DARK, adj.x, adj.y) >= 0) {
1970 compres.moves--;
1971 if(!compres.moves)
1972 return;
1975 rb->yield();
1979 /* Defence stage done, move on to OFFENCE */
1980 found_target = true;
1981 while(found_target) {
1982 found_target = false;
1983 for(i=1;i<11;i++) {
1984 for(j=1;j<11;j++) {
1985 if(board[i][j].colour == COLOUR_LIGHT &&
1986 (board[i][j].ind || board[i][j].farm) &&
1987 (calc_strength(COLOUR_DARK, i, j) >=
1988 calc_strength(COLOUR_LIGHT, i, j))) {
1989 found_target = true;
1990 if(attack_territory(COLOUR_DARK, i, j) >= 0) {
1991 compres.moves--;
1992 if(!compres.moves)
1993 return;
1996 rb->yield();
2000 /* Spend leftover moves wherever attacking randomly */
2001 found_target = true;
2002 while(found_target) {
2003 found_target = false;
2004 for(i=1;i<11;i++) {
2005 for(j=1;j<11;j++) {
2006 if(board[i][j].colour == COLOUR_LIGHT &&
2007 (calc_strength(COLOUR_DARK, i, j) >=
2008 calc_strength(COLOUR_LIGHT, i, j))) {
2009 found_target = true;
2010 if(attack_territory(COLOUR_DARK, i, j) >= 0) {
2011 compres.moves--;
2012 if(!compres.moves)
2013 return;
2016 rb->yield();
2022 static int load_game(const char* file) {
2023 int fd;
2025 fd = rb->open(file, O_RDONLY);
2026 if(fd == 0) {
2027 DEBUGF("Couldn't open savegame\n");
2028 return -1;
2030 rb->read(fd, buf, 5);
2031 if(rb->strcmp(buf, "SSGv3")) {
2032 rb->splash(HZ, "Invalid/incompatible savegame");
2033 return -1;
2035 rb->read(fd, &gamestate, sizeof(gamestate));
2036 rb->read(fd, &humanres.cash, sizeof(humanres.cash));
2037 rb->read(fd, &humanres.food, sizeof(humanres.food));
2038 rb->read(fd, &humanres.bank, sizeof(humanres.bank));
2039 rb->read(fd, &humanres.planes, sizeof(humanres.planes));
2040 rb->read(fd, &humanres.tanks, sizeof(humanres.tanks));
2041 rb->read(fd, &humanres.men, sizeof(humanres.men));
2042 rb->read(fd, &humanres.nukes, sizeof(humanres.nukes));
2043 rb->read(fd, &humanres.inds, sizeof(humanres.inds));
2044 rb->read(fd, &humanres.farms, sizeof(humanres.farms));
2045 rb->read(fd, &humanres.moves, sizeof(humanres.moves));
2046 rb->read(fd, &compres.cash, sizeof(humanres.cash));
2047 rb->read(fd, &compres.food, sizeof(humanres.food));
2048 rb->read(fd, &compres.bank, sizeof(humanres.bank));
2049 rb->read(fd, &compres.planes, sizeof(humanres.planes));
2050 rb->read(fd, &compres.tanks, sizeof(humanres.tanks));
2051 rb->read(fd, &compres.men, sizeof(humanres.men));
2052 rb->read(fd, &compres.nukes, sizeof(humanres.nukes));
2053 rb->read(fd, &compres.inds, sizeof(humanres.inds));
2054 rb->read(fd, &compres.farms, sizeof(humanres.farms));
2055 rb->read(fd, &compres.moves, sizeof(humanres.moves));
2056 rb->read(fd, board, sizeof(board));
2057 rb->read(fd, &superdom_settings.compstartfarms, sizeof(int));
2058 rb->read(fd, &superdom_settings.compstartinds, sizeof(int));
2059 rb->read(fd, &superdom_settings.humanstartfarms, sizeof(int));
2060 rb->read(fd, &superdom_settings.humanstartfarms, sizeof(int));
2061 rb->read(fd, &superdom_settings.startcash, sizeof(int));
2062 rb->read(fd, &superdom_settings.startfood, sizeof(int));
2063 rb->read(fd, &superdom_settings.movesperturn, sizeof(int));
2064 rb->close(fd);
2065 return 0;
2068 void default_settings(void) {
2069 superdom_settings.compstartfarms = 1;
2070 superdom_settings.compstartinds = 1;
2071 superdom_settings.humanstartfarms = 2;
2072 superdom_settings.humanstartinds = 2;
2073 superdom_settings.startcash = 0;
2074 superdom_settings.startfood = 0;
2075 superdom_settings.movesperturn = 2;
2078 int average_strength(int colour) {
2079 /* This function calculates the average strength of the given player,
2080 * used to determine when the computer wins or loses. */
2081 int i,j;
2082 int totalpower = 0;
2083 for(i=1;i<11;i++) {
2084 for(j=1;j<11;j++) {
2085 if(board[i][j].colour != -1) {
2086 totalpower += calc_strength(colour, i, j);
2090 return totalpower/100;
2093 enum plugin_status plugin_start(const void* parameter)
2095 #if LCD_DEPTH > 1
2096 rb->lcd_set_backdrop(NULL);
2097 rb->lcd_set_foreground(LCD_BLACK);
2098 rb->lcd_set_background(LCD_WHITE);
2099 #endif
2101 cursor.x = 1;
2102 cursor.y = 1;
2103 default_settings();
2104 if(parameter) {
2105 if(load_game(parameter) != 0) {
2106 DEBUGF("Loading failed, generating new game\n");
2107 } else {
2108 switch(gamestate) {
2109 case GS_PROD:
2110 goto startprod;
2111 break;
2112 case GS_MOVE:
2113 goto startmove;
2114 break;
2115 case GS_WAR:
2116 goto startwar;
2117 break;
2118 default:
2119 goto startyear;
2120 break;
2125 bool play = false;
2126 while(!play) {
2127 switch(menu()) {
2128 case 0:
2129 play = true;
2130 break;
2131 case 2:
2132 return PLUGIN_OK;
2133 break;
2134 case PLUGIN_USB_CONNECTED:
2135 return PLUGIN_USB_CONNECTED;
2136 break;
2139 init_resources();
2140 init_board();
2141 gen_resources();
2142 startyear:
2143 while(1) {
2144 int avg_str_diff = (average_strength(COLOUR_LIGHT) -
2145 average_strength(COLOUR_DARK));
2146 if(avg_str_diff > 15) {
2147 rb->splash(HZ*4, "The computer has surrendered. You win.");
2148 return PLUGIN_OK;
2150 if(-avg_str_diff > 15) {
2151 rb->splash(HZ*4, "Your army have suffered terrible morale from"
2152 " the bleak prospects of winning. You lose.");
2153 return PLUGIN_OK;
2156 /* production */
2157 startprod:
2158 gamestate = GS_PROD;
2159 switch(production_menu()) {
2160 case PLUGIN_USB_CONNECTED:
2161 return PLUGIN_USB_CONNECTED;
2162 break;
2163 case SUPERDOM_QUIT:
2164 return PLUGIN_OK;
2165 break;
2167 computer_allocate();
2169 /* movement */
2170 humanres.moves = superdom_settings.movesperturn;
2171 startmove:
2172 gamestate = GS_MOVE;
2173 switch(movement_menu()) {
2174 case PLUGIN_USB_CONNECTED:
2175 return PLUGIN_USB_CONNECTED;
2176 break;
2177 case SUPERDOM_QUIT:
2178 return PLUGIN_OK;
2179 break;
2181 /* feed men */
2182 if(humanres.men) {
2183 if(humanres.food > humanres.men) {
2184 rb->snprintf(buf, sizeof(buf), "Your men ate %d units of food",
2185 humanres.men);
2186 humanres.food -= humanres.men;
2187 } else {
2188 rb->snprintf(buf, sizeof(buf), "There was not enough food"
2189 " to feed all your men, %d men have died of starvation",
2190 killmen(COLOUR_LIGHT));
2192 rb->splash(HZ*2, buf);
2194 if(compres.men) {
2195 if(compres.food > compres.men) {
2196 compres.food -= compres.men;
2197 } else {
2198 rb->snprintf(buf, sizeof(buf), "The computer does not have"
2199 " enough food to feed its men. %d have died of starvation",
2200 killmen(COLOUR_DARK));
2201 rb->splash(HZ, buf);
2204 /* war */
2205 humanres.moves = superdom_settings.movesperturn;
2206 startwar:
2207 gamestate = GS_WAR;
2208 switch(war_menu()) {
2209 case PLUGIN_USB_CONNECTED:
2210 return PLUGIN_USB_CONNECTED;
2211 break;
2212 case SUPERDOM_QUIT:
2213 return PLUGIN_OK;
2214 break;
2216 compres.moves = superdom_settings.movesperturn;
2217 computer_war();
2218 gen_resources();
2220 return PLUGIN_OK;