1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
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 ****************************************************************************/
22 #include "lib/playback_control.h"
25 extern const fb_data superdom_boarditems
[];
29 #define COLOUR_LIGHT 1
34 #define MY_BITMAP_PART rb->lcd_bitmap_transparent_part
36 #define MY_BITMAP_PART rb->lcd_mono_bitmap_part
39 #if LCD_WIDTH > LCD_HEIGHT
40 #define BOX_WIDTH ((LCD_WIDTH-(MARGIN*2))/10)
41 #define BOX_HEIGHT ((BOX_WIDTH*2)/3)
44 #define BOX_HEIGHT ((LCD_HEIGHT-(MARGIN*2)-15)/10)
45 #define BOX_WIDTH ((BOX_HEIGHT*2)/3)
49 #if LCD_WIDTH == 220 && LCD_HEIGHT == 176
50 #define NUM_BOX_HEIGHT 25
51 #define NUM_BOX_WIDTH 30
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
65 #elif (LCD_WIDTH == 320 && LCD_HEIGHT == 240)
66 #define NUM_BOX_HEIGHT 25
67 #define NUM_BOX_WIDTH 30
69 #define ICON_HEIGHT 10
72 #elif (LCD_WIDTH == 240 && (LCD_HEIGHT == 320 || LCD_HEIGHT == 400))
73 #define NUM_BOX_HEIGHT 25
74 #define NUM_BOX_WIDTH 30
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
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
162 #ifdef HAVE_TOUCHSCREEN
164 #define SUPERDOM_OK BUTTON_CENTER
167 #define SUPERDOM_UP BUTTON_TOPMIDDLE
169 #ifndef SUPERDOM_LEFT
170 #define SUPERDOM_LEFT BUTTON_MIDLEFT
172 #ifndef SUPERDOM_RIGHT
173 #define SUPERDOM_RIGHT BUTTON_MIDRIGHT
175 #ifndef SUPERDOM_DOWN
176 #define SUPERDOM_DOWN BUTTON_BOTTOMMIDDLE
178 #ifndef SUPERDOM_CANCEL
179 #define SUPERDOM_CANCEL BUTTON_TOPLEFT
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);
196 signed int colour
; /* -1 = Unset */
228 struct resources humanres
;
229 struct resources compres
;
230 enum { GS_PROD
, GS_MOVE
, GS_WAR
} gamestate
;
237 struct tile board
[12][12];
239 void init_board(void) {
241 rb
->srand(*rb
->current_tick
);
242 for(i
=0;i
<12;i
++) { /* Hopefully about 50% each colour */
244 if((i
<1)||(j
<1)||(i
>10)||(j
>10))
245 board
[i
][j
].colour
= -1; /* Unset */
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;
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;
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;
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;
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;
291 void draw_board(void) {
293 rb
->lcd_clear_display();
296 if(board
[i
][j
].colour
== COLOUR_DARK
) {
297 rb
->lcd_set_foreground(LCD_DARKGRAY
);
299 rb
->lcd_set_foreground(LCD_LIGHTGRAY
);
301 rb
->lcd_fillrect(MARGIN
+(BOX_WIDTH
*(i
-1)),
302 MARGIN
+(BOX_HEIGHT
*(j
-1)), BOX_WIDTH
,
305 rb
->lcd_set_drawmode(DRMODE_BG
| DRMODE_INVERSEVID
);
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,
314 MARGIN
+(BOX_WIDTH
*(i
-1))+1+ICON_WIDTH
,
315 MARGIN
+(BOX_HEIGHT
*(j
-1))+1,
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,
340 STRIDE
, MARGIN
+(BOX_WIDTH
*(i
-1))+1,
341 MARGIN
+(BOX_HEIGHT
*(j
-1))+1+ICON_HEIGHT
,
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,
352 STRIDE
,MARGIN
+(BOX_WIDTH
*(i
-1))+ICON_WIDTH
+1,
353 MARGIN
+(BOX_HEIGHT
*(j
-1))+ICON_HEIGHT
*2+1,
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,
364 STRIDE
,MARGIN
+(BOX_WIDTH
*(i
-1))+1,
365 MARGIN
+(BOX_HEIGHT
*(j
-1))+ICON_HEIGHT
*2+1,
367 ICON_WIDTH
, ICON_HEIGHT
);
370 rb
->lcd_set_drawmode(DRMODE_SOLID
);
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));
384 int calc_strength(int colour
, int x
, int y
) {
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
)) {
391 if(board
[x
+ a
][y
+ b
].tank
|| board
[x
+ a
][y
+ b
].farm
)
393 if(board
[x
+ a
][y
+ b
].plane
|| board
[x
+ a
][y
+ b
].ind
)
395 if(board
[x
+ a
][y
+ b
].nuke
)
397 if(board
[x
+ a
][y
+ b
].men
)
398 score
+= (board
[x
+ a
][y
+ b
].men
*133/1000);
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
);
421 void gen_resources(void) {
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);
437 ratecash
= inccash
/humanres
.inds
;
439 ratefood
= incfood
/humanres
.farms
;
442 rb
->splash(HZ
*2, "Patriotism sweeps the land, all production"
443 " is up this year!");
445 rb
->splash(HZ
*2, "Factories working at maximum efficiency,"
446 " cash production up this year!");
448 } else if(ratecash
> 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");
454 rb
->splash(HZ
*2, "Spoilage of crops leads to reduced farm"
455 " output this year");
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.");
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 */
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) {
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) {
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");
510 selection
=rb
->do_menu(&settings_menu
,&selection
, NULL
, false);
513 rb
->set_int("Computer starting farms", "", UNIT_INT
,
514 &superdom_settings
.compstartfarms
, NULL
,
518 rb
->set_int("Computer starting factories", "", UNIT_INT
,
519 &superdom_settings
.compstartinds
, NULL
,
523 rb
->set_int("Human starting farms", "", UNIT_INT
,
524 &superdom_settings
.humanstartfarms
, NULL
,
528 rb
->set_int("Human starting factories", "", UNIT_INT
,
529 &superdom_settings
.humanstartinds
, NULL
,
533 rb
->set_int("Starting cash", "", UNIT_INT
,
534 &superdom_settings
.startcash
, NULL
,
538 rb
->set_int("Starting food", "", UNIT_INT
,
539 &superdom_settings
.startfood
, NULL
,
543 rb
->set_int("Moves per turn", "", UNIT_INT
,
544 &superdom_settings
.movesperturn
, NULL
,
547 case MENU_ATTACHED_USB
:
548 return PLUGIN_USB_CONNECTED
;
558 static int do_help(void) {
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
) {
584 /* .. or if the word is the empty string */
585 if (rb
->strcmp(instructions
[i
], "") == 0) {
590 /* We filled the screen */
591 if (y
+ height
> LCD_HEIGHT
- MARGIN
) {
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
;
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
) ) );
623 MENUITEM_STRINGLIST(main_menu
,"Super Domination Menu",NULL
,
624 "Play Super Domination","Settings","Help","Quit");
627 selection
=rb
->do_menu(&main_menu
,&selection
, NULL
, false);
630 return 0; /* start playing */
633 if(settings_menu_function()==PLUGIN_USB_CONNECTED
)
634 return PLUGIN_USB_CONNECTED
;
637 if(do_help()==PLUGIN_USB_CONNECTED
)
638 return PLUGIN_USB_CONNECTED
;
641 return 2; /* quit program */
649 int save_game(void) {
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");
659 fd
= rb
->open(savepath
, O_WRONLY
|O_CREAT
);
660 DEBUGF("savepath: %s\n", savepath
);
662 DEBUGF("Couldn't create/open file\n");
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));
700 int ingame_menu(void) {
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);
713 rb
->splash(HZ
, "Game saved");
715 rb
->splash(HZ
, "Error in save");
718 playback_control(NULL
);
721 return SUPERDOM_QUIT
;
723 case MENU_ATTACHED_USB
:
724 return PLUGIN_USB_CONNECTED
;
733 int get_number(char* param
, int* value
) {
734 //int numbers[3][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 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
));
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,
778 rb
->lcd_set_drawmode(DRMODE_SOLID
);
781 button
= rb
->button_get(true);
786 *value
+= numbers
[y
][x
];
794 rb
->lcd_set_drawmode(DRMODE_BG
|DRMODE_INVERSEVID
);
795 rb
->lcd_fillrect(0, NUM_MARGIN_Y
+4*NUM_BOX_HEIGHT
+10,
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
);
802 case SUPERDOM_CANCEL
:
804 rb
->splash(HZ
, "Cancelled");
807 #if CONFIG_KEYPAD != IRIVER_H10_PAD
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
);
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
);
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
);
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
);
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
);
863 #if CONFIG_KEYPAD == IRIVER_H10_PAD
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
);
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
);
886 #if CONFIG_KEYPAD == IRIVER_H10_PAD
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
);
904 if (rb
->default_event_handler(button
) == SYS_USB_CONNECTED
)
906 return PLUGIN_USB_CONNECTED
;
915 bool tile_has_item(int type
, int x
, int y
) {
918 return (board
[x
][y
].men
> 0);
921 return board
[x
][y
].tank
;
924 return board
[x
][y
].plane
;
927 return board
[x
][y
].farm
;
930 return board
[x
][y
].ind
;
933 return board
[x
][y
].nuke
;
939 int buy_resources(int colour
, int type
, int x
, int y
, int nummen
) {
940 const char *itemnames
[][6] = {
946 "the industrial plant",
953 "build an industrial plant",
960 "an industrial plant",
965 bool human
= (colour
== COLOUR_LIGHT
);
967 struct resources
*res
;
987 case 4: /* Factory */
994 if(res
->cash
< price
) {
996 rb
->splash(HZ
, "Not enough money!");
1000 rb
->splashf(HZ
, "Where do you want to place %s?", itemnames
[0][type
]);
1001 switch(select_square()) {
1005 case PLUGIN_USB_CONNECTED
:
1006 return PLUGIN_USB_CONNECTED
;
1012 if(board
[x
][y
].colour
!= colour
) {
1014 rb
->splashf(HZ
, "Can't %s on enemy territory", itemnames
[1][type
]);
1017 if(type
!= 0 && tile_has_item(type
, x
, y
)) {
1019 rb
->splashf(HZ
, "There is already %s there", itemnames
[2][type
]);
1024 board
[x
][y
].men
+= nummen
;
1028 board
[x
][y
].tank
= true;
1032 board
[x
][y
].plane
= true;
1036 board
[x
][y
].farm
= true;
1040 board
[x
][y
].ind
= true;
1044 board
[x
][y
].nuke
= true;
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)",
1065 selection
=rb
->do_menu(&res_menu
,&selection
, NULL
, false);
1069 if(get_number("How many men would you like?", &nummen
)
1070 == PLUGIN_USB_CONNECTED
)
1071 return PLUGIN_USB_CONNECTED
;
1080 if(buy_resources(COLOUR_LIGHT
, selection
, 0, 0, nummen
)
1081 == PLUGIN_USB_CONNECTED
)
1082 return PLUGIN_USB_CONNECTED
;
1087 case MENU_ATTACHED_USB
:
1088 return PLUGIN_USB_CONNECTED
;
1090 case GO_TO_PREVIOUS
:
1098 int move_unit(int colour
, int type
, int fromx
, int fromy
,
1099 int tox
, int toy
, int nummen
) {
1100 const char *itemnames
[][3] = {
1115 bool human
= (colour
== COLOUR_LIGHT
);
1118 rb
->splashf(HZ
, "Select where you want to move %s from",
1119 itemnames
[0][type
]);
1120 switch(select_square()) {
1124 case PLUGIN_USB_CONNECTED
:
1125 return PLUGIN_USB_CONNECTED
;
1131 if(board
[fromx
][fromy
].colour
!= colour
) {
1133 rb
->splash(HZ
, "That isn't your territory");
1136 if(!tile_has_item(type
, fromx
, fromy
)) {
1138 rb
->splashf(HZ
, "You don't have %s there", itemnames
[1][type
]);
1143 nummen
= board
[fromx
][fromy
].men
;
1144 switch(get_number("How many men do you want to move?", &nummen
)) {
1148 case PLUGIN_USB_CONNECTED
:
1149 return PLUGIN_USB_CONNECTED
;
1153 if(nummen
> board
[fromx
][fromy
].men
) {
1155 rb
->splash(HZ
, "You don't have that many troops.");
1160 rb
->splashf(HZ
, "Select where you want to move %s to",
1161 itemnames
[2][type
]);
1162 switch(select_square()) {
1166 case PLUGIN_USB_CONNECTED
:
1167 return PLUGIN_USB_CONNECTED
;
1173 if((tox
== fromx
&& toy
== fromy
) ||
1174 board
[tox
][toy
].colour
!= colour
||
1175 (type
!= 2 && (abs(tox
- fromx
) > 1 || abs(toy
- fromy
) > 1))) {
1177 rb
->splash(HZ
, "Invalid move");
1180 if(type
!= 0 && tile_has_item(type
, tox
, toy
)) {
1182 rb
->splashf(HZ
, "There is already %s there", itemnames
[1][type
]);
1187 board
[fromx
][fromy
].men
-= nummen
;
1188 board
[tox
][toy
].men
+= nummen
;
1191 board
[fromx
][fromy
].tank
= false;
1192 board
[tox
][toy
].tank
= true;
1195 board
[fromx
][fromy
].plane
= false;
1196 board
[tox
][toy
].plane
= true;
1202 int move_unit_menu(void) {
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);
1212 switch(move_unit(COLOUR_LIGHT
, selection
, 0, 0, 0, 0, 0)) {
1216 case PLUGIN_USB_CONNECTED
:
1217 return PLUGIN_USB_CONNECTED
;
1221 case MENU_ATTACHED_USB
:
1222 return PLUGIN_USB_CONNECTED
;
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
) {
1233 rb
->splash(HZ
, "That isn't your territory");
1236 if(! board
[nukex
][nukey
].nuke
) {
1238 rb
->splashf(HZ
, "You don't have %s there", "a nuke");
1242 rb
->splash(HZ
, "Select place to target with nuke");
1243 switch(select_square()) {
1247 case PLUGIN_USB_CONNECTED
:
1248 return PLUGIN_USB_CONNECTED
;
1259 board
[nukex
][nukey
].nuke
= false;
1261 if(board
[targetx
][targety
].colour
== COLOUR_LIGHT
) {
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 */
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");
1291 selection
=rb
->do_menu(&move_menu
,&selection
, NULL
, false);
1294 if(humanres
.moves
) {
1295 if(move_unit_menu()==PLUGIN_USB_CONNECTED
)
1296 return PLUGIN_USB_CONNECTED
;
1298 rb
->splash(HZ
, "You have no more moves left."
1299 " You can buy more for $100 each.");
1303 if(humanres
.cash
> 100) {
1305 humanres
.cash
-= 100;
1306 rb
->snprintf(buf
, sizeof(buf
), "You now have %d moves",
1308 rb
->splash(HZ
, buf
);
1312 if(humanres
.nukes
==0) {
1313 rb
->splash(HZ
, "You do not have any nukes to launch");
1315 rb
->splash(HZ
, "Select place to launch nuke from");
1316 switch(select_square()) {
1318 if(launch_nuke(COLOUR_LIGHT
, cursor
.x
, cursor
.y
,
1319 0, 0) == PLUGIN_USB_CONNECTED
)
1320 return PLUGIN_USB_CONNECTED
;
1322 case PLUGIN_USB_CONNECTED
:
1323 return PLUGIN_USB_CONNECTED
;
1329 if(select_square() == PLUGIN_USB_CONNECTED
)
1330 return PLUGIN_USB_CONNECTED
;
1336 tempmenu
= ingame_menu();
1338 case PLUGIN_USB_CONNECTED
:
1339 return PLUGIN_USB_CONNECTED
;
1342 return SUPERDOM_QUIT
;
1346 case MENU_ATTACHED_USB
:
1347 return PLUGIN_USB_CONNECTED
;
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
);
1378 if(rb
->default_event_handler(rb
->button_get(true)) == SYS_USB_CONNECTED
) {
1379 return PLUGIN_USB_CONNECTED
;
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");
1393 selection
=rb
->do_menu(&prod_menu
,&selection
, NULL
, false);
1396 if(buy_resources_menu() == PLUGIN_USB_CONNECTED
)
1397 return PLUGIN_USB_CONNECTED
;
1400 if(show_inventory() == PLUGIN_USB_CONNECTED
)
1401 return PLUGIN_USB_CONNECTED
;
1404 if(select_square() == PLUGIN_USB_CONNECTED
)
1405 return PLUGIN_USB_CONNECTED
;
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");
1415 humanres
.cash
-= tempbank
;
1416 humanres
.bank
+= tempbank
;
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");
1427 humanres
.cash
+= tempbank
;
1428 humanres
.bank
-= tempbank
;
1435 tempmenu
= ingame_menu();
1437 case PLUGIN_USB_CONNECTED
:
1438 return PLUGIN_USB_CONNECTED
;
1441 return SUPERDOM_QUIT
;
1445 case MENU_ATTACHED_USB
:
1446 return PLUGIN_USB_CONNECTED
;
1453 void init_resources(void) {
1454 humanres
.cash
= superdom_settings
.startcash
;
1455 humanres
.food
= superdom_settings
.startfood
;
1457 humanres
.planes
= 0;
1464 compres
.cash
= superdom_settings
.startcash
;
1465 compres
.food
= superdom_settings
.startfood
;
1476 int select_square(void) {
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
);
1491 button
= rb
->button_get(true);
1493 case SUPERDOM_CANCEL
:
1494 rb
->splash(HZ
, "Cancelled");
1500 #if CONFIG_KEYPAD != IRIVER_H10_PAD
1502 case (SUPERDOM_LEFT
|BUTTON_REPEAT
):
1503 draw_cursor(); /* Deselect the current tile */
1518 case SUPERDOM_RIGHT
:
1519 case (SUPERDOM_RIGHT
|BUTTON_REPEAT
):
1520 draw_cursor(); /* Deselect the current tile */
1538 case (SUPERDOM_UP
|BUTTON_REPEAT
):
1539 draw_cursor(); /* Deselect the current tile */
1543 #if CONFIG_KEYPAD == IRIVER_H10_PAD
1555 case (SUPERDOM_DOWN
|BUTTON_REPEAT
):
1556 draw_cursor(); /* Deselect the current tile */
1560 #if CONFIG_KEYPAD == IRIVER_H10_PAD
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
);
1586 percent
= (humanres
.food
*1000)/humanres
.men
;
1589 percent
= (compres
.food
*1000)/compres
.men
;
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
;
1604 humanres
.men
-= menkilled
;
1606 compres
.men
-= 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
);
1615 if(board
[x
][y
].colour
== colour
) {
1617 rb
->splash(HZ
, "You can't attack your own territory");
1620 str_diff
= calc_strength(COLOUR_DARK
, x
, y
) -
1621 calc_strength(COLOUR_LIGHT
, x
, y
);
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
;
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;
1656 rb
->splash(HZ
, "Your troops were unable to overcome"
1657 " the enemy troops");
1659 rb
->splash(HZ
*2, "The computer attempted to "
1660 "attack, but the invasion was"
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);
1677 switch(select_square()) {
1679 if(attack_territory(COLOUR_LIGHT
, cursor
.x
, cursor
.y
)
1683 case PLUGIN_USB_CONNECTED
:
1684 return PLUGIN_USB_CONNECTED
;
1692 tempmenu
= ingame_menu();
1694 case PLUGIN_USB_CONNECTED
:
1695 return PLUGIN_USB_CONNECTED
;
1698 return SUPERDOM_QUIT
;
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)) {
1718 if(!buy_resources(COLOUR_DARK
, type
, x
-1, y
, 0)) {
1721 if(!buy_resources(COLOUR_DARK
, type
, x
+1, y
, 0)) {
1724 if(!buy_resources(COLOUR_DARK
, type
, x
, y
-1, 0)) {
1727 if(!buy_resources(COLOUR_DARK
, type
, x
, y
+1, 0)) {
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
)))
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
) {
1752 if(board
[x
+1][y
].colour
== COLOUR_DARK
) {
1757 if(board
[x
][y
-1].colour
== COLOUR_DARK
) {
1762 if(board
[x
][y
+1].colour
== COLOUR_DARK
) {
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 */
1774 bool offensive
= true;
1775 struct threat threats
[4];
1777 int total_str_diff
= 0;
1778 int numterritory
= 0;
1781 struct threat targets
[2];
1785 compres
.cash
+= compres
.bank
;
1789 if(board
[i
][j
].colour
== COLOUR_DARK
) {
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) {
1796 threats
[numthreats
].x
= i
;
1797 threats
[numthreats
].y
= j
;
1798 threats
[numthreats
].str_diff
= str_diff
;
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 */
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 */
1822 if(has_adjacent(i
,j
) &&
1823 (board
[i
][j
].ind
|| board
[i
][j
].farm
)) {
1827 targets
[k
].str_diff
=
1828 calc_strength(COLOUR_LIGHT
, i
, j
) -
1829 calc_strength(COLOUR_DARK
, i
, j
);
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);
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
,
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
,
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
);
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
,
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
1903 find_adjacent(threats
[i
].x
, threats
[i
].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
);
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
;
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
)) {
1934 if(board
[x
-1][y
].colour
== COLOUR_LIGHT
&&
1935 calc_strength(COLOUR_LIGHT
,x
-1,y
)<=calc_strength(COLOUR_DARK
,x
-1,y
)) {
1940 if(board
[x
][y
+1].colour
== COLOUR_LIGHT
&&
1941 calc_strength(COLOUR_LIGHT
,x
,y
+1)<=calc_strength(COLOUR_DARK
,x
,y
+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)) {
1955 void computer_war(void) {
1956 /* Work out where to attack - prioritise the defence of buildings */
1958 bool found_target
= true;
1961 while(found_target
) {
1962 found_target
= false;
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) {
1979 /* Defence stage done, move on to OFFENCE */
1980 found_target
= true;
1981 while(found_target
) {
1982 found_target
= false;
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) {
2000 /* Spend leftover moves wherever attacking randomly */
2001 found_target
= true;
2002 while(found_target
) {
2003 found_target
= false;
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) {
2022 static int load_game(const char* file
) {
2025 fd
= rb
->open(file
, O_RDONLY
);
2027 DEBUGF("Couldn't open savegame\n");
2030 rb
->read(fd
, buf
, 5);
2031 if(rb
->strcmp(buf
, "SSGv3")) {
2032 rb
->splash(HZ
, "Invalid/incompatible savegame");
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));
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. */
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
)
2096 rb
->lcd_set_backdrop(NULL
);
2097 rb
->lcd_set_foreground(LCD_BLACK
);
2098 rb
->lcd_set_background(LCD_WHITE
);
2105 if(load_game(parameter
) != 0) {
2106 DEBUGF("Loading failed, generating new game\n");
2134 case PLUGIN_USB_CONNECTED
:
2135 return PLUGIN_USB_CONNECTED
;
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.");
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.");
2158 gamestate
= GS_PROD
;
2159 switch(production_menu()) {
2160 case PLUGIN_USB_CONNECTED
:
2161 return PLUGIN_USB_CONNECTED
;
2167 computer_allocate();
2170 humanres
.moves
= superdom_settings
.movesperturn
;
2172 gamestate
= GS_MOVE
;
2173 switch(movement_menu()) {
2174 case PLUGIN_USB_CONNECTED
:
2175 return PLUGIN_USB_CONNECTED
;
2183 if(humanres
.food
> humanres
.men
) {
2184 rb
->snprintf(buf
, sizeof(buf
), "Your men ate %d units of food",
2186 humanres
.food
-= humanres
.men
;
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
);
2195 if(compres
.food
> compres
.men
) {
2196 compres
.food
-= compres
.men
;
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
);
2205 humanres
.moves
= superdom_settings
.movesperturn
;
2208 switch(war_menu()) {
2209 case PLUGIN_USB_CONNECTED
:
2210 return PLUGIN_USB_CONNECTED
;
2216 compres
.moves
= superdom_settings
.movesperturn
;