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"
23 #include "lib/display_text.h"
26 extern const fb_data superdom_boarditems
[];
30 #define COLOUR_LIGHT 1
35 #define MY_BITMAP_PART rb->lcd_bitmap_transparent_part
37 #define MY_BITMAP_PART rb->lcd_mono_bitmap_part
40 #if LCD_WIDTH > LCD_HEIGHT
41 #define BOX_WIDTH ((LCD_WIDTH-(MARGIN*2))/10)
42 #define BOX_HEIGHT ((BOX_WIDTH*2)/3)
45 #define BOX_HEIGHT ((LCD_HEIGHT-(MARGIN*2)-15)/10)
46 #define BOX_WIDTH ((BOX_HEIGHT*2)/3)
50 #if LCD_WIDTH == 220 && LCD_HEIGHT == 176
51 #define NUM_BOX_HEIGHT 25
52 #define NUM_BOX_WIDTH 30
57 #elif (LCD_WIDTH == 160 && LCD_HEIGHT == 128) || \
58 (LCD_WIDTH == 176 && LCD_HEIGHT == 132) || \
59 (LCD_WIDTH == 176 && LCD_HEIGHT == 220)
60 #define NUM_BOX_HEIGHT 20
61 #define NUM_BOX_WIDTH 24
66 #elif (LCD_WIDTH == 320 && LCD_HEIGHT == 240)
67 #define NUM_BOX_HEIGHT 25
68 #define NUM_BOX_WIDTH 30
70 #define ICON_HEIGHT 10
73 #elif (LCD_WIDTH == 240 && (LCD_HEIGHT == 320 || LCD_HEIGHT == 400))
74 #define NUM_BOX_HEIGHT 25
75 #define NUM_BOX_WIDTH 30
82 #define NUM_MARGIN_X (LCD_WIDTH-3*NUM_BOX_WIDTH)/2
83 #define NUM_MARGIN_Y (LCD_HEIGHT-4*NUM_BOX_HEIGHT)/2
85 #if (CONFIG_KEYPAD == IPOD_4G_PAD) || (CONFIG_KEYPAD == IPOD_3G_PAD) || \
86 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
87 #define SUPERDOM_OK BUTTON_SELECT
88 #define SUPERDOM_CANCEL BUTTON_MENU
89 #define SUPERDOM_LEFT BUTTON_LEFT
90 #define SUPERDOM_RIGHT BUTTON_RIGHT
93 #elif CONFIG_KEYPAD == IRIVER_H300_PAD || CONFIG_KEYPAD == IRIVER_H100_PAD
94 #define SUPERDOM_OK BUTTON_SELECT
95 #define SUPERDOM_LEFT BUTTON_LEFT
96 #define SUPERDOM_RIGHT BUTTON_RIGHT
97 #define SUPERDOM_UP BUTTON_UP
98 #define SUPERDOM_DOWN BUTTON_DOWN
99 #define SUPERDOM_CANCEL BUTTON_OFF
101 #elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
102 #define SUPERDOM_OK BUTTON_SELECT
103 #define SUPERDOM_LEFT BUTTON_LEFT
104 #define SUPERDOM_RIGHT BUTTON_RIGHT
105 #define SUPERDOM_UP BUTTON_UP
106 #define SUPERDOM_DOWN BUTTON_DOWN
107 #define SUPERDOM_CANCEL BUTTON_REC
109 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
110 #define SUPERDOM_OK BUTTON_RIGHT
111 #define SUPERDOM_UP BUTTON_SCROLL_UP
112 #define SUPERDOM_DOWN BUTTON_SCROLL_DOWN
113 #define SUPERDOM_CANCEL BUTTON_LEFT
115 #elif CONFIG_KEYPAD == GIGABEAT_PAD
116 #define SUPERDOM_OK BUTTON_SELECT
117 #define SUPERDOM_UP BUTTON_UP
118 #define SUPERDOM_DOWN BUTTON_DOWN
119 #define SUPERDOM_LEFT BUTTON_LEFT
120 #define SUPERDOM_RIGHT BUTTON_RIGHT
121 #define SUPERDOM_CANCEL BUTTON_POWER
123 #elif CONFIG_KEYPAD == SANSA_E200_PAD
124 #define SUPERDOM_OK BUTTON_SELECT
125 #define SUPERDOM_UP BUTTON_SCROLL_BACK
126 #define SUPERDOM_DOWN BUTTON_SCROLL_FWD
127 #define SUPERDOM_LEFT BUTTON_LEFT
128 #define SUPERDOM_RIGHT BUTTON_RIGHT
129 #define SUPERDOM_CANCEL BUTTON_POWER
131 #elif CONFIG_KEYPAD == SANSA_FUZE_PAD
132 #define SUPERDOM_OK BUTTON_SELECT
133 #define SUPERDOM_UP BUTTON_SCROLL_BACK
134 #define SUPERDOM_DOWN BUTTON_SCROLL_FWD
135 #define SUPERDOM_LEFT BUTTON_LEFT
136 #define SUPERDOM_RIGHT BUTTON_RIGHT
137 #define SUPERDOM_CANCEL (BUTTON_HOME|BUTTON_REPEAT)
139 #elif CONFIG_KEYPAD == GIGABEAT_S_PAD
140 #define SUPERDOM_OK BUTTON_SELECT
141 #define SUPERDOM_UP BUTTON_UP
142 #define SUPERDOM_DOWN BUTTON_DOWN
143 #define SUPERDOM_LEFT BUTTON_LEFT
144 #define SUPERDOM_RIGHT BUTTON_RIGHT
145 #define SUPERDOM_CANCEL BUTTON_BACK
147 #elif CONFIG_KEYPAD == COWOND2_PAD
148 #define SUPERDOM_CANCEL BUTTON_POWER
150 #elif CONFIG_KEYPAD == CREATIVEZVM_PAD
151 #define SUPERDOM_OK BUTTON_SELECT
152 #define SUPERDOM_UP BUTTON_UP
153 #define SUPERDOM_DOWN BUTTON_DOWN
154 #define SUPERDOM_LEFT BUTTON_LEFT
155 #define SUPERDOM_RIGHT BUTTON_RIGHT
156 #define SUPERDOM_CANCEL BUTTON_BACK
158 #elif CONFIG_KEYPAD == ONDAVX747_PAD
159 #define SUPERDOM_CANCEL BUTTON_POWER
163 #ifdef HAVE_TOUCHSCREEN
165 #define SUPERDOM_OK BUTTON_CENTER
168 #define SUPERDOM_UP BUTTON_TOPMIDDLE
170 #ifndef SUPERDOM_LEFT
171 #define SUPERDOM_LEFT BUTTON_MIDLEFT
173 #ifndef SUPERDOM_RIGHT
174 #define SUPERDOM_RIGHT BUTTON_MIDRIGHT
176 #ifndef SUPERDOM_DOWN
177 #define SUPERDOM_DOWN BUTTON_BOTTOMMIDDLE
179 #ifndef SUPERDOM_CANCEL
180 #define SUPERDOM_CANCEL BUTTON_TOPLEFT
184 #define SUPERDOM_QUIT 23
186 void gen_interest(void);
187 int production_menu(void);
188 void init_resources(void);
189 int select_square(void);
190 void update_score(void);
191 void gen_resources(void);
192 void draw_cursor(void);
193 int calc_strength(int colour
, int x
, int y
);
194 void draw_board(void);
197 signed int colour
; /* -1 = Unset */
229 struct resources humanres
;
230 struct resources compres
;
231 enum { GS_PROD
, GS_MOVE
, GS_WAR
} gamestate
;
238 struct tile board
[12][12];
240 void init_board(void) {
242 rb
->srand(*rb
->current_tick
);
243 for(i
=0;i
<12;i
++) { /* Hopefully about 50% each colour */
245 if((i
<1)||(j
<1)||(i
>10)||(j
>10))
246 board
[i
][j
].colour
= -1; /* Unset */
248 board
[i
][j
].colour
= rb
->rand()%2;
249 board
[i
][j
].tank
= false;
250 board
[i
][j
].plane
= false;
251 board
[i
][j
].nuke
= false;
252 board
[i
][j
].ind
= false;
253 board
[i
][j
].farm
= false;
258 while(compres
.farms
< superdom_settings
.compstartfarms
) {
259 i
= rb
->rand()%10 + 1;
260 j
= rb
->rand()%10 + 1;
261 if((board
[i
][j
].colour
== COLOUR_DARK
) && (board
[i
][j
].farm
== false)) {
262 board
[i
][j
].farm
= true;
266 while(compres
.inds
< superdom_settings
.compstartinds
) {
267 i
= rb
->rand()%10 + 1;
268 j
= rb
->rand()%10 + 1;
269 if((board
[i
][j
].colour
== COLOUR_DARK
) && (board
[i
][j
].ind
== false)) {
270 board
[i
][j
].ind
= true;
274 while(humanres
.farms
<superdom_settings
.humanstartfarms
) {
275 i
= rb
->rand()%10 + 1;
276 j
= rb
->rand()%10 + 1;
277 if((board
[i
][j
].colour
== COLOUR_LIGHT
)&&(board
[i
][j
].farm
== false)) {
278 board
[i
][j
].farm
= true;
282 while(humanres
.inds
<superdom_settings
.humanstartfarms
) {
283 i
= rb
->rand()%10 + 1;
284 j
= rb
->rand()%10 + 1;
285 if((board
[i
][j
].colour
== COLOUR_LIGHT
) && (board
[i
][j
].ind
== false)) {
286 board
[i
][j
].ind
= true;
292 void draw_board(void) {
294 rb
->lcd_clear_display();
297 if(board
[i
][j
].colour
== COLOUR_DARK
) {
298 rb
->lcd_set_foreground(LCD_DARKGRAY
);
300 rb
->lcd_set_foreground(LCD_LIGHTGRAY
);
302 rb
->lcd_fillrect(MARGIN
+(BOX_WIDTH
*(i
-1)),
303 MARGIN
+(BOX_HEIGHT
*(j
-1)), BOX_WIDTH
,
306 rb
->lcd_set_drawmode(DRMODE_BG
| DRMODE_INVERSEVID
);
308 if(board
[i
][j
].ind
) {
309 MY_BITMAP_PART(superdom_boarditems
,
310 board
[i
][j
].colour
?ICON_WIDTH
:0, 0, STRIDE
,
311 #if LCD_WIDTH > LCD_HEIGHT
312 MARGIN
+(BOX_WIDTH
*(i
-1))+1,
313 MARGIN
+(BOX_HEIGHT
*(j
-1))+ICON_HEIGHT
+1,
315 MARGIN
+(BOX_WIDTH
*(i
-1))+1+ICON_WIDTH
,
316 MARGIN
+(BOX_HEIGHT
*(j
-1))+1,
318 ICON_WIDTH
, ICON_HEIGHT
);
320 if(board
[i
][j
].farm
) {
321 MY_BITMAP_PART(superdom_boarditems
,
322 board
[i
][j
].colour
?ICON_WIDTH
:0, ICON_HEIGHT
,
323 STRIDE
, MARGIN
+(BOX_WIDTH
*(i
-1))+1,
324 MARGIN
+(BOX_HEIGHT
*(j
-1))+1,
325 ICON_WIDTH
, ICON_HEIGHT
);
327 if(board
[i
][j
].tank
) {
328 MY_BITMAP_PART(superdom_boarditems
,
329 board
[i
][j
].colour
?ICON_WIDTH
:0, ICON_HEIGHT
*2,
330 STRIDE
, MARGIN
+(BOX_WIDTH
*(i
-1))+ICON_WIDTH
+1,
331 MARGIN
+(BOX_HEIGHT
*(j
-1))+ICON_HEIGHT
+1,
332 ICON_WIDTH
, ICON_HEIGHT
);
334 if(board
[i
][j
].men
) {
335 MY_BITMAP_PART(superdom_boarditems
,
336 board
[i
][j
].colour
?ICON_WIDTH
:0, ICON_HEIGHT
*3,
337 #if LCD_WIDTH > LCD_HEIGHT
338 STRIDE
, MARGIN
+(BOX_WIDTH
*(i
-1))+ICON_WIDTH
+1,
339 MARGIN
+(BOX_HEIGHT
*(j
-1))+1,
341 STRIDE
, MARGIN
+(BOX_WIDTH
*(i
-1))+1,
342 MARGIN
+(BOX_HEIGHT
*(j
-1))+1+ICON_HEIGHT
,
344 ICON_WIDTH
, ICON_HEIGHT
);
346 if(board
[i
][j
].plane
) {
347 MY_BITMAP_PART(superdom_boarditems
,
348 board
[i
][j
].colour
?ICON_WIDTH
:0, ICON_HEIGHT
*4,
349 #if LCD_WIDTH > LCD_HEIGHT
350 STRIDE
,MARGIN
+(BOX_WIDTH
*(i
-1))+ICON_WIDTH
*2+1,
351 MARGIN
+(BOX_HEIGHT
*(j
-1))+ICON_HEIGHT
+1,
353 STRIDE
,MARGIN
+(BOX_WIDTH
*(i
-1))+ICON_WIDTH
+1,
354 MARGIN
+(BOX_HEIGHT
*(j
-1))+ICON_HEIGHT
*2+1,
356 ICON_WIDTH
, ICON_HEIGHT
);
358 if(board
[i
][j
].nuke
) {
359 MY_BITMAP_PART(superdom_boarditems
,
360 board
[i
][j
].colour
?ICON_WIDTH
:0, ICON_HEIGHT
*5,
361 #if LCD_WIDTH > LCD_HEIGHT
362 STRIDE
,MARGIN
+(BOX_WIDTH
*(i
-1))+ICON_WIDTH
*2+1,
363 MARGIN
+(BOX_HEIGHT
*(j
-1))+1,
365 STRIDE
,MARGIN
+(BOX_WIDTH
*(i
-1))+1,
366 MARGIN
+(BOX_HEIGHT
*(j
-1))+ICON_HEIGHT
*2+1,
368 ICON_WIDTH
, ICON_HEIGHT
);
371 rb
->lcd_set_drawmode(DRMODE_SOLID
);
375 rb
->lcd_set_foreground(LCD_BLACK
);
376 for(i
=0;i
<=10;i
++) { /* Draw Horizontal lines */
377 rb
->lcd_hline(MARGIN
, MARGIN
+(BOX_WIDTH
*10), MARGIN
+(BOX_HEIGHT
*i
));
379 for(i
=0;i
<=10;i
++) { /* Draw Vertical lines */
380 rb
->lcd_vline(MARGIN
+(BOX_WIDTH
*i
), MARGIN
, MARGIN
+(BOX_HEIGHT
*10));
385 int calc_strength(int colour
, int x
, int y
) {
387 for (a
= -1; a
< 2; a
++) {
388 for (b
= -1; b
< 2; b
++) {
389 if ((b
== 0 || a
== 0) &&
390 (board
[x
+ a
][y
+ b
].colour
== colour
)) {
392 if(board
[x
+ a
][y
+ b
].tank
|| board
[x
+ a
][y
+ b
].farm
)
394 if(board
[x
+ a
][y
+ b
].plane
|| board
[x
+ a
][y
+ b
].ind
)
396 if(board
[x
+ a
][y
+ b
].nuke
)
398 if(board
[x
+ a
][y
+ b
].men
)
399 score
+= (board
[x
+ a
][y
+ b
].men
*133/1000);
406 void gen_interest(void) {
407 /* Interest should be around 10% */
408 rb
->srand(*rb
->current_tick
);
409 int interest
= 7+rb
->rand()%6;
410 humanres
.bank
= humanres
.bank
+(interest
*humanres
.bank
/100);
411 compres
.bank
= compres
.bank
+(interest
*compres
.bank
/100);
414 void draw_cursor(void) {
415 rb
->lcd_set_drawmode(DRMODE_COMPLEMENT
);
416 rb
->lcd_fillrect(MARGIN
+((cursor
.x
-1)*BOX_WIDTH
),
417 MARGIN
+((cursor
.y
-1)*BOX_HEIGHT
), BOX_WIDTH
+1, BOX_HEIGHT
+1);
418 rb
->lcd_set_drawmode(DRMODE_SOLID
);
422 void gen_resources(void) {
429 rb
->srand(*rb
->current_tick
);
430 /* Generate Human's resources */
431 for(i
=0;i
<humanres
.inds
;i
++) {
432 inccash
+= (300+rb
->rand()%200);
434 for(i
=0;i
<humanres
.farms
;i
++) {
435 incfood
+= (200+rb
->rand()%200);
438 ratecash
= inccash
/humanres
.inds
;
440 ratefood
= incfood
/humanres
.farms
;
443 rb
->splash(HZ
*2, "Patriotism sweeps the land, all production"
444 " is up this year!");
446 rb
->splash(HZ
*2, "Factories working at maximum efficiency,"
447 " cash production up this year!");
449 } else if(ratecash
> 350) {
451 rb
->splash(HZ
*2, "Record crop harvest this year!");
452 } else if(ratefood
> 250) {
453 rb
->splash(HZ
*2, "Production continues as normal");
455 rb
->splash(HZ
*2, "Spoilage of crops leads to reduced farm"
456 " output this year");
460 rb
->splash(HZ
*2, "Record crop harvest this year!");
461 } else if(ratefood
> 250) {
462 rb
->splash(HZ
*2, "Factory unions introduced. Industrial"
463 " production is down this year.");
465 rb
->splash(HZ
*2, "Internet created. All production is down"
466 " due to time wasted.");
469 humanres
.cash
+= inccash
;
470 humanres
.food
+= incfood
;
472 /* Generate Computer's resources */
475 for(i
=0;i
<compres
.inds
;i
++) {
476 inccash
+= (300+rb
->rand()%200);
478 for(i
=0;i
<compres
.farms
;i
++) {
479 incfood
+= (200+rb
->rand()%200);
481 compres
.cash
+= inccash
;
482 compres
.food
+= incfood
;
485 void update_score(void) {
487 rb
->lcd_setfont(FONT_SYSFIXED
);
488 rb
->lcd_set_drawmode(DRMODE_BG
|DRMODE_INVERSEVID
);
489 rb
->lcd_fillrect(5,LCD_HEIGHT
-20,105,20);
490 rb
->lcd_set_drawmode(DRMODE_SOLID
);
491 strength
= calc_strength(COLOUR_LIGHT
, cursor
.x
, cursor
.y
);
492 rb
->snprintf(buf
, sizeof(buf
), "Your power: %d.%d",
493 strength
/10, strength
%10);
494 rb
->lcd_putsxy(5,LCD_HEIGHT
-20, buf
);
495 strength
= calc_strength(COLOUR_DARK
, cursor
.x
, cursor
.y
);
496 rb
->snprintf(buf
, sizeof(buf
), "Comp power: %d.%d",
497 strength
/10, strength
%10);
498 rb
->lcd_putsxy(5,LCD_HEIGHT
-10, buf
);
499 rb
->lcd_setfont(FONT_UI
);
502 int settings_menu_function(void) {
505 MENUITEM_STRINGLIST(settings_menu
,"Super Domination Settings",NULL
,
506 "Computer starting farms","Computer starting factories",
507 "Human starting farms","Human starting factories",
508 "Starting cash","Starting food","Moves per turn");
511 selection
=rb
->do_menu(&settings_menu
,&selection
, NULL
, false);
514 rb
->set_int("Computer starting farms", "", UNIT_INT
,
515 &superdom_settings
.compstartfarms
, NULL
,
519 rb
->set_int("Computer starting factories", "", UNIT_INT
,
520 &superdom_settings
.compstartinds
, NULL
,
524 rb
->set_int("Human starting farms", "", UNIT_INT
,
525 &superdom_settings
.humanstartfarms
, NULL
,
529 rb
->set_int("Human starting factories", "", UNIT_INT
,
530 &superdom_settings
.humanstartinds
, NULL
,
534 rb
->set_int("Starting cash", "", UNIT_INT
,
535 &superdom_settings
.startcash
, NULL
,
539 rb
->set_int("Starting food", "", UNIT_INT
,
540 &superdom_settings
.startfood
, NULL
,
544 rb
->set_int("Moves per turn", "", UNIT_INT
,
545 &superdom_settings
.movesperturn
, NULL
,
548 case MENU_ATTACHED_USB
:
549 return PLUGIN_USB_CONNECTED
;
559 static int do_help(void) {
561 #define WORDS (sizeof help_text / sizeof (char*))
562 static char* help_text
[] = {
563 "Super", "domination", "is", "a", "turn", "based", "strategy", "game,",
564 "where", "the", "aim", "is", "to", "overpower", "the", "computer",
565 "player", "by", "taking", "their", "territory.", "",
566 "Each", "year", "you", "are", "allocated", "an", "amount", "of", "cash",
567 "and", "food,", "depending", "on", "how", "many", "farms", "and",
568 "factories", "you", "control.", "",
569 "Use", "this", "cash", "and", "food", "to", "buy", "and", "feed", "your",
570 "army.", "Each", "tile", "has", "a", "strength,", "calculated", "by",
571 "the", "ownership", "of", "adjacent", "tiles,", "and", "the", "type",
572 "and", "number", "of", "troops", "on", "them.",
575 if (display_text(WORDS
, help_text
, NULL
, NULL
))
576 return PLUGIN_USB_CONNECTED
;
578 button
= rb
->button_get(true);
579 if ( rb
->default_event_handler( button
) == SYS_USB_CONNECTED
)
580 return PLUGIN_USB_CONNECTED
;
581 } while( ( button
== BUTTON_NONE
)
582 || ( button
& (BUTTON_REL
|BUTTON_REPEAT
) ) );
590 MENUITEM_STRINGLIST(main_menu
,"Super Domination Menu",NULL
,
591 "Play Super Domination","Settings","Help","Quit");
594 selection
=rb
->do_menu(&main_menu
,&selection
, NULL
, false);
597 return 0; /* start playing */
600 if(settings_menu_function()==PLUGIN_USB_CONNECTED
)
601 return PLUGIN_USB_CONNECTED
;
604 if(do_help()==PLUGIN_USB_CONNECTED
)
605 return PLUGIN_USB_CONNECTED
;
608 return 2; /* quit program */
616 int save_game(void) {
618 char savepath
[MAX_PATH
];
620 rb
->snprintf(savepath
, sizeof(savepath
), "/Savegame.ssg");
621 if(rb
->kbd_input(savepath
, MAX_PATH
)) {
622 DEBUGF("Keyboard input failed\n");
626 fd
= rb
->open(savepath
, O_WRONLY
|O_CREAT
);
627 DEBUGF("savepath: %s\n", savepath
);
629 DEBUGF("Couldn't create/open file\n");
633 rb
->write(fd
, "SSGv3", 5);
634 rb
->write(fd
, &gamestate
, sizeof(gamestate
));
635 rb
->write(fd
, &humanres
.cash
, sizeof(humanres
.cash
));
636 rb
->write(fd
, &humanres
.food
, sizeof(humanres
.food
));
637 rb
->write(fd
, &humanres
.bank
, sizeof(humanres
.bank
));
638 rb
->write(fd
, &humanres
.planes
, sizeof(humanres
.planes
));
639 rb
->write(fd
, &humanres
.tanks
, sizeof(humanres
.tanks
));
640 rb
->write(fd
, &humanres
.men
, sizeof(humanres
.men
));
641 rb
->write(fd
, &humanres
.nukes
, sizeof(humanres
.nukes
));
642 rb
->write(fd
, &humanres
.inds
, sizeof(humanres
.inds
));
643 rb
->write(fd
, &humanres
.farms
, sizeof(humanres
.farms
));
644 rb
->write(fd
, &humanres
.moves
, sizeof(humanres
.moves
));
645 rb
->write(fd
, &compres
.cash
, sizeof(compres
.cash
));
646 rb
->write(fd
, &compres
.food
, sizeof(compres
.food
));
647 rb
->write(fd
, &compres
.bank
, sizeof(compres
.bank
));
648 rb
->write(fd
, &compres
.planes
, sizeof(compres
.planes
));
649 rb
->write(fd
, &compres
.tanks
, sizeof(compres
.tanks
));
650 rb
->write(fd
, &compres
.men
, sizeof(compres
.men
));
651 rb
->write(fd
, &compres
.nukes
, sizeof(compres
.nukes
));
652 rb
->write(fd
, &compres
.inds
, sizeof(compres
.inds
));
653 rb
->write(fd
, &compres
.farms
, sizeof(compres
.farms
));
654 rb
->write(fd
, &compres
.moves
, sizeof(compres
.moves
));
655 rb
->write(fd
, board
, sizeof(board
));
656 rb
->write(fd
, &superdom_settings
.compstartfarms
, sizeof(int));
657 rb
->write(fd
, &superdom_settings
.compstartinds
, sizeof(int));
658 rb
->write(fd
, &superdom_settings
.humanstartfarms
, sizeof(int));
659 rb
->write(fd
, &superdom_settings
.humanstartfarms
, sizeof(int));
660 rb
->write(fd
, &superdom_settings
.startcash
, sizeof(int));
661 rb
->write(fd
, &superdom_settings
.startfood
, sizeof(int));
662 rb
->write(fd
, &superdom_settings
.movesperturn
, sizeof(int));
667 int ingame_menu(void) {
670 MENUITEM_STRINGLIST(ingame_menu
,"Super Domination Menu",NULL
,
671 "Return to game","Save Game","Playback Control", "Quit");
673 selection
=rb
->do_menu(&ingame_menu
,&selection
, NULL
, false);
680 rb
->splash(HZ
, "Game saved");
682 rb
->splash(HZ
, "Error in save");
685 playback_control(NULL
);
688 return SUPERDOM_QUIT
;
690 case MENU_ATTACHED_USB
:
691 return PLUGIN_USB_CONNECTED
;
700 int get_number(char* param
, int* value
) {
701 //int numbers[3][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
715 rb
->lcd_clear_display();
716 /* Draw a 3x4 grid */
717 for(i
=0;i
<=3;i
++) { /* Vertical lines */
718 rb
->lcd_vline(NUM_MARGIN_X
+(NUM_BOX_WIDTH
*i
), NUM_MARGIN_Y
,
719 NUM_MARGIN_Y
+(4*NUM_BOX_HEIGHT
));
721 for(i
=0;i
<=4;i
++) { /* Horizontal lines */
722 rb
->lcd_hline(NUM_MARGIN_X
, NUM_MARGIN_X
+(3*NUM_BOX_WIDTH
),
723 NUM_MARGIN_Y
+(NUM_BOX_HEIGHT
*i
));
727 rb
->snprintf(buf
, sizeof(buf
), "%d", numbers
[i
][j
]);
728 rb
->lcd_putsxy(NUM_MARGIN_X
+(j
*NUM_BOX_WIDTH
)+10,
729 NUM_MARGIN_Y
+(i
*NUM_BOX_HEIGHT
)+8, buf
);
732 rb
->lcd_putsxy(NUM_MARGIN_X
+5, NUM_MARGIN_Y
+(3*NUM_BOX_HEIGHT
)+8, "CLR");
733 rb
->lcd_putsxy(NUM_MARGIN_X
+NUM_BOX_WIDTH
+10,
734 NUM_MARGIN_Y
+(3*NUM_BOX_HEIGHT
)+8, "0");
735 rb
->lcd_putsxy(NUM_MARGIN_X
+2*NUM_BOX_WIDTH
+8,
736 NUM_MARGIN_Y
+(3*NUM_BOX_HEIGHT
)+8, "OK");
737 rb
->snprintf(buf
,sizeof(buf
), "%d", *value
);
738 rb
->lcd_putsxy(NUM_MARGIN_X
+10, NUM_MARGIN_Y
+4*NUM_BOX_HEIGHT
+10, buf
);
739 rb
->lcd_getstringsize(param
, &width
, &height
);
740 rb
->lcd_putsxy((LCD_WIDTH
-width
)/2, (NUM_MARGIN_Y
-height
)/2, param
);
741 rb
->lcd_set_drawmode(DRMODE_COMPLEMENT
);
742 rb
->lcd_fillrect(NUM_MARGIN_X
+(NUM_BOX_WIDTH
*x
),
743 NUM_MARGIN_Y
+(NUM_BOX_HEIGHT
*y
), NUM_BOX_WIDTH
+1,
745 rb
->lcd_set_drawmode(DRMODE_SOLID
);
748 button
= rb
->button_get(true);
753 *value
+= numbers
[y
][x
];
761 rb
->lcd_set_drawmode(DRMODE_BG
|DRMODE_INVERSEVID
);
762 rb
->lcd_fillrect(0, NUM_MARGIN_Y
+4*NUM_BOX_HEIGHT
+10,
764 rb
->lcd_set_drawmode(DRMODE_SOLID
);
765 rb
->snprintf(buf
,sizeof(buf
), "%d", *value
);
766 rb
->lcd_putsxy(NUM_MARGIN_X
+10,
767 NUM_MARGIN_Y
+4*NUM_BOX_HEIGHT
+10, buf
);
769 case SUPERDOM_CANCEL
:
771 rb
->splash(HZ
, "Cancelled");
774 #if CONFIG_KEYPAD != IRIVER_H10_PAD
776 rb
->lcd_set_drawmode(DRMODE_COMPLEMENT
);
777 rb
->lcd_fillrect(NUM_MARGIN_X
+(NUM_BOX_WIDTH
*x
),
778 NUM_MARGIN_Y
+(NUM_BOX_HEIGHT
*y
),
779 NUM_BOX_WIDTH
+1, NUM_BOX_HEIGHT
+1);
780 rb
->lcd_set_drawmode(DRMODE_SOLID
);
792 rb
->lcd_set_drawmode(DRMODE_COMPLEMENT
);
793 rb
->lcd_fillrect(NUM_MARGIN_X
+(NUM_BOX_WIDTH
*x
),
794 NUM_MARGIN_Y
+(NUM_BOX_HEIGHT
*y
),
795 NUM_BOX_WIDTH
+1, NUM_BOX_HEIGHT
+1);
796 rb
->lcd_set_drawmode(DRMODE_SOLID
);
799 rb
->lcd_set_drawmode(DRMODE_COMPLEMENT
);
800 rb
->lcd_fillrect(NUM_MARGIN_X
+(NUM_BOX_WIDTH
*x
),
801 NUM_MARGIN_Y
+(NUM_BOX_HEIGHT
*y
),
802 NUM_BOX_WIDTH
+1, NUM_BOX_HEIGHT
+1);
803 rb
->lcd_set_drawmode(DRMODE_SOLID
);
815 rb
->lcd_set_drawmode(DRMODE_COMPLEMENT
);
816 rb
->lcd_fillrect(NUM_MARGIN_X
+(NUM_BOX_WIDTH
*x
),
817 NUM_MARGIN_Y
+(NUM_BOX_HEIGHT
*y
),
818 NUM_BOX_WIDTH
+1, NUM_BOX_HEIGHT
+1);
819 rb
->lcd_set_drawmode(DRMODE_SOLID
);
824 rb
->lcd_set_drawmode(DRMODE_COMPLEMENT
);
825 rb
->lcd_fillrect(NUM_MARGIN_X
+(NUM_BOX_WIDTH
*x
),
826 NUM_MARGIN_Y
+(NUM_BOX_HEIGHT
*y
),
827 NUM_BOX_WIDTH
+1, NUM_BOX_HEIGHT
+1);
828 rb
->lcd_set_drawmode(DRMODE_SOLID
);
830 #if CONFIG_KEYPAD == IRIVER_H10_PAD
840 rb
->lcd_set_drawmode(DRMODE_COMPLEMENT
);
841 rb
->lcd_fillrect(NUM_MARGIN_X
+(NUM_BOX_WIDTH
*x
),
842 NUM_MARGIN_Y
+(NUM_BOX_HEIGHT
*y
),
843 NUM_BOX_WIDTH
+1, NUM_BOX_HEIGHT
+1);
844 rb
->lcd_set_drawmode(DRMODE_SOLID
);
847 rb
->lcd_set_drawmode(DRMODE_COMPLEMENT
);
848 rb
->lcd_fillrect(NUM_MARGIN_X
+(NUM_BOX_WIDTH
*x
),
849 NUM_MARGIN_Y
+(NUM_BOX_HEIGHT
*y
),
850 NUM_BOX_WIDTH
+1, NUM_BOX_HEIGHT
+1);
851 rb
->lcd_set_drawmode(DRMODE_SOLID
);
853 #if CONFIG_KEYPAD == IRIVER_H10_PAD
863 rb
->lcd_set_drawmode(DRMODE_COMPLEMENT
);
864 rb
->lcd_fillrect(NUM_MARGIN_X
+(NUM_BOX_WIDTH
*x
),
865 NUM_MARGIN_Y
+(NUM_BOX_HEIGHT
*y
),
866 NUM_BOX_WIDTH
+1, NUM_BOX_HEIGHT
+1);
867 rb
->lcd_set_drawmode(DRMODE_SOLID
);
871 if (rb
->default_event_handler(button
) == SYS_USB_CONNECTED
)
873 return PLUGIN_USB_CONNECTED
;
882 bool tile_has_item(int type
, int x
, int y
) {
885 return (board
[x
][y
].men
> 0);
888 return board
[x
][y
].tank
;
891 return board
[x
][y
].plane
;
894 return board
[x
][y
].farm
;
897 return board
[x
][y
].ind
;
900 return board
[x
][y
].nuke
;
906 int buy_resources(int colour
, int type
, int x
, int y
, int nummen
) {
907 const char *itemnames
[][6] = {
913 "the industrial plant",
920 "build an industrial plant",
927 "an industrial plant",
932 bool human
= (colour
== COLOUR_LIGHT
);
934 struct resources
*res
;
954 case 4: /* Factory */
961 if(res
->cash
< price
) {
963 rb
->splash(HZ
, "Not enough money!");
967 rb
->splashf(HZ
, "Where do you want to place %s?", itemnames
[0][type
]);
968 switch(select_square()) {
972 case PLUGIN_USB_CONNECTED
:
973 return PLUGIN_USB_CONNECTED
;
979 if(board
[x
][y
].colour
!= colour
) {
981 rb
->splashf(HZ
, "Can't %s on enemy territory", itemnames
[1][type
]);
984 if(type
!= 0 && tile_has_item(type
, x
, y
)) {
986 rb
->splashf(HZ
, "There is already %s there", itemnames
[2][type
]);
991 board
[x
][y
].men
+= nummen
;
995 board
[x
][y
].tank
= true;
999 board
[x
][y
].plane
= true;
1003 board
[x
][y
].farm
= true;
1007 board
[x
][y
].ind
= true;
1011 board
[x
][y
].nuke
= true;
1023 int buy_resources_menu(void) {
1024 int selection
,nummen
;
1026 MENUITEM_STRINGLIST(res_menu
, "Buy Resources", NULL
, "Buy men ($1)",
1027 "Buy tank ($300)", "Buy plane ($600)", "Buy Farm ($1150)",
1028 "Buy Factory ($1300)", "Buy Nuke ($2000)",
1032 selection
=rb
->do_menu(&res_menu
,&selection
, NULL
, false);
1036 if(get_number("How many men would you like?", &nummen
)
1037 == PLUGIN_USB_CONNECTED
)
1038 return PLUGIN_USB_CONNECTED
;
1047 if(buy_resources(COLOUR_LIGHT
, selection
, 0, 0, nummen
)
1048 == PLUGIN_USB_CONNECTED
)
1049 return PLUGIN_USB_CONNECTED
;
1054 case MENU_ATTACHED_USB
:
1055 return PLUGIN_USB_CONNECTED
;
1057 case GO_TO_PREVIOUS
:
1065 int move_unit(int colour
, int type
, int fromx
, int fromy
,
1066 int tox
, int toy
, int nummen
) {
1067 const char *itemnames
[][3] = {
1082 bool human
= (colour
== COLOUR_LIGHT
);
1085 rb
->splashf(HZ
, "Select where you want to move %s from",
1086 itemnames
[0][type
]);
1087 switch(select_square()) {
1091 case PLUGIN_USB_CONNECTED
:
1092 return PLUGIN_USB_CONNECTED
;
1098 if(board
[fromx
][fromy
].colour
!= colour
) {
1100 rb
->splash(HZ
, "That isn't your territory");
1103 if(!tile_has_item(type
, fromx
, fromy
)) {
1105 rb
->splashf(HZ
, "You don't have %s there", itemnames
[1][type
]);
1110 nummen
= board
[fromx
][fromy
].men
;
1111 switch(get_number("How many men do you want to move?", &nummen
)) {
1115 case PLUGIN_USB_CONNECTED
:
1116 return PLUGIN_USB_CONNECTED
;
1120 if(nummen
> board
[fromx
][fromy
].men
) {
1122 rb
->splash(HZ
, "You don't have that many troops.");
1127 rb
->splashf(HZ
, "Select where you want to move %s to",
1128 itemnames
[2][type
]);
1129 switch(select_square()) {
1133 case PLUGIN_USB_CONNECTED
:
1134 return PLUGIN_USB_CONNECTED
;
1140 if((tox
== fromx
&& toy
== fromy
) ||
1141 board
[tox
][toy
].colour
!= colour
||
1142 (type
!= 2 && (abs(tox
- fromx
) > 1 || abs(toy
- fromy
) > 1))) {
1144 rb
->splash(HZ
, "Invalid move");
1147 if(type
!= 0 && tile_has_item(type
, tox
, toy
)) {
1149 rb
->splashf(HZ
, "There is already %s there", itemnames
[1][type
]);
1154 board
[fromx
][fromy
].men
-= nummen
;
1155 board
[tox
][toy
].men
+= nummen
;
1158 board
[fromx
][fromy
].tank
= false;
1159 board
[tox
][toy
].tank
= true;
1162 board
[fromx
][fromy
].plane
= false;
1163 board
[tox
][toy
].plane
= true;
1169 int move_unit_menu(void) {
1172 MENUITEM_STRINGLIST(move_unit_menu
, "Move unit", NULL
, "Move men",
1173 "Move tank", "Move plane");
1174 selection
=rb
->do_menu(&move_unit_menu
,&selection
, NULL
, false);
1179 switch(move_unit(COLOUR_LIGHT
, selection
, 0, 0, 0, 0, 0)) {
1183 case PLUGIN_USB_CONNECTED
:
1184 return PLUGIN_USB_CONNECTED
;
1188 case MENU_ATTACHED_USB
:
1189 return PLUGIN_USB_CONNECTED
;
1194 int launch_nuke(int colour
, int nukex
, int nukey
, int targetx
, int targety
) {
1195 bool human
= (colour
== COLOUR_LIGHT
);
1196 struct resources
*res
;
1198 if(board
[nukex
][nukey
].colour
!= colour
) {
1200 rb
->splash(HZ
, "That isn't your territory");
1203 if(! board
[nukex
][nukey
].nuke
) {
1205 rb
->splashf(HZ
, "You don't have %s there", "a nuke");
1209 rb
->splash(HZ
, "Select place to target with nuke");
1210 switch(select_square()) {
1214 case PLUGIN_USB_CONNECTED
:
1215 return PLUGIN_USB_CONNECTED
;
1226 board
[nukex
][nukey
].nuke
= false;
1228 if(board
[targetx
][targety
].colour
== COLOUR_LIGHT
) {
1233 res
->men
-= board
[targetx
][targety
].men
;
1234 res
->tanks
-= board
[targetx
][targety
].tank
;
1235 res
->planes
-= board
[targetx
][targety
].plane
;
1236 res
->nukes
-= board
[targetx
][targety
].nuke
;
1237 res
->farms
-= board
[targetx
][targety
].farm
;
1238 res
->inds
-= board
[targetx
][targety
].ind
;
1239 board
[targetx
][targety
].men
= 0;
1240 board
[targetx
][targety
].tank
= false;
1241 board
[targetx
][targety
].plane
= false;
1242 board
[targetx
][targety
].ind
= false;
1243 board
[targetx
][targety
].nuke
= false;
1244 board
[targetx
][targety
].farm
= false;
1245 /* TODO: Fallout carried by wind */
1250 int movement_menu(void) {
1251 int selection
, tempmenu
;
1253 MENUITEM_STRINGLIST(move_menu
, "Movement", NULL
, "Move unit",
1254 "Buy additional moves ($100)", "Launch nuclear missile",
1255 "Check map", "Finish moving", "Game menu");
1258 selection
=rb
->do_menu(&move_menu
,&selection
, NULL
, false);
1261 if(humanres
.moves
) {
1262 if(move_unit_menu()==PLUGIN_USB_CONNECTED
)
1263 return PLUGIN_USB_CONNECTED
;
1265 rb
->splash(HZ
, "You have no more moves left."
1266 " You can buy more for $100 each.");
1270 if(humanres
.cash
> 100) {
1272 humanres
.cash
-= 100;
1273 rb
->snprintf(buf
, sizeof(buf
), "You now have %d moves",
1275 rb
->splash(HZ
, buf
);
1279 if(humanres
.nukes
==0) {
1280 rb
->splash(HZ
, "You do not have any nukes to launch");
1282 rb
->splash(HZ
, "Select place to launch nuke from");
1283 switch(select_square()) {
1285 if(launch_nuke(COLOUR_LIGHT
, cursor
.x
, cursor
.y
,
1286 0, 0) == PLUGIN_USB_CONNECTED
)
1287 return PLUGIN_USB_CONNECTED
;
1289 case PLUGIN_USB_CONNECTED
:
1290 return PLUGIN_USB_CONNECTED
;
1296 if(select_square() == PLUGIN_USB_CONNECTED
)
1297 return PLUGIN_USB_CONNECTED
;
1303 tempmenu
= ingame_menu();
1305 case PLUGIN_USB_CONNECTED
:
1306 return PLUGIN_USB_CONNECTED
;
1309 return SUPERDOM_QUIT
;
1313 case MENU_ATTACHED_USB
:
1314 return PLUGIN_USB_CONNECTED
;
1321 int show_inventory(void) {
1322 char men
[20], tanks
[20], planes
[20], inds
[20], farms
[20], nukes
[20],
1323 cash
[20], food
[20], bank
[20];
1324 rb
->snprintf(men
, sizeof(men
), "Men: %d", humanres
.men
);
1325 rb
->snprintf(tanks
, sizeof(tanks
), "Tanks: %d", humanres
.tanks
);
1326 rb
->snprintf(planes
, sizeof(planes
), "Planes: %d", humanres
.planes
);
1327 rb
->snprintf(inds
, sizeof(inds
), "Factories: %d", humanres
.inds
);
1328 rb
->snprintf(farms
, sizeof(farms
), "Farms: %d", humanres
.farms
);
1329 rb
->snprintf(nukes
, sizeof(nukes
), "Nukes: %d", humanres
.nukes
);
1330 rb
->snprintf(cash
, sizeof(cash
), "Cash: %d", humanres
.cash
);
1331 rb
->snprintf(food
, sizeof(food
), "Food: %d", humanres
.food
);
1332 rb
->snprintf(bank
, sizeof(bank
), "Bank: %d", humanres
.bank
);
1333 rb
->lcd_clear_display();
1334 rb
->lcd_puts(1, 0, "Inventory");
1335 rb
->lcd_puts(2, 1, men
);
1336 rb
->lcd_puts(2, 2, tanks
);
1337 rb
->lcd_puts(2, 3, planes
);
1338 rb
->lcd_puts(2, 4, inds
);
1339 rb
->lcd_puts(2, 5, farms
);
1340 rb
->lcd_puts(2, 6, nukes
);
1341 rb
->lcd_puts(2, 7, cash
);
1342 rb
->lcd_puts(2, 8, food
);
1343 rb
->lcd_puts(2, 9, bank
);
1345 if(rb
->default_event_handler(rb
->button_get(true)) == SYS_USB_CONNECTED
) {
1346 return PLUGIN_USB_CONNECTED
;
1352 int production_menu(void) {
1353 int selection
, tempbank
, tempmenu
;
1355 MENUITEM_STRINGLIST(prod_menu
, "Production", NULL
, "Buy resources",
1356 "Show inventory", "Check map", "Invest money",
1357 "Withdraw money", "Finish turn", "Game menu");
1360 selection
=rb
->do_menu(&prod_menu
,&selection
, NULL
, false);
1363 if(buy_resources_menu() == PLUGIN_USB_CONNECTED
)
1364 return PLUGIN_USB_CONNECTED
;
1367 if(show_inventory() == PLUGIN_USB_CONNECTED
)
1368 return PLUGIN_USB_CONNECTED
;
1371 if(select_square() == PLUGIN_USB_CONNECTED
)
1372 return PLUGIN_USB_CONNECTED
;
1375 tempbank
= humanres
.cash
;
1376 if(get_number("How much do you want to invest?", &tempbank
)
1377 == PLUGIN_USB_CONNECTED
)
1378 return PLUGIN_USB_CONNECTED
;
1379 if(tempbank
>humanres
.cash
) {
1380 rb
->splash(HZ
, "You don't have that much cash to invest");
1382 humanres
.cash
-= tempbank
;
1383 humanres
.bank
+= tempbank
;
1388 if(get_number("How much do you want to withdraw?", &tempbank
)
1389 == PLUGIN_USB_CONNECTED
)
1390 return PLUGIN_USB_CONNECTED
;
1391 if(tempbank
>humanres
.bank
) {
1392 rb
->splash(HZ
, "You don't have that much cash to withdraw");
1394 humanres
.cash
+= tempbank
;
1395 humanres
.bank
-= tempbank
;
1402 tempmenu
= ingame_menu();
1404 case PLUGIN_USB_CONNECTED
:
1405 return PLUGIN_USB_CONNECTED
;
1408 return SUPERDOM_QUIT
;
1412 case MENU_ATTACHED_USB
:
1413 return PLUGIN_USB_CONNECTED
;
1420 void init_resources(void) {
1421 humanres
.cash
= superdom_settings
.startcash
;
1422 humanres
.food
= superdom_settings
.startfood
;
1424 humanres
.planes
= 0;
1431 compres
.cash
= superdom_settings
.startcash
;
1432 compres
.food
= superdom_settings
.startfood
;
1443 int select_square(void) {
1448 #if LCD_WIDTH >= 220
1449 rb
->lcd_setfont(FONT_SYSFIXED
);
1450 rb
->snprintf(buf
, sizeof(buf
), "Cash: %d", humanres
.cash
);
1451 rb
->lcd_putsxy(125, LCD_HEIGHT
-20, buf
);
1452 rb
->snprintf(buf
, sizeof(buf
), "Food: %d", humanres
.food
);
1453 rb
->lcd_putsxy(125, LCD_HEIGHT
-10, buf
);
1454 rb
->lcd_setfont(FONT_UI
);
1458 button
= rb
->button_get(true);
1460 case SUPERDOM_CANCEL
:
1461 rb
->splash(HZ
, "Cancelled");
1467 #if CONFIG_KEYPAD != IRIVER_H10_PAD
1469 case (SUPERDOM_LEFT
|BUTTON_REPEAT
):
1470 draw_cursor(); /* Deselect the current tile */
1485 case SUPERDOM_RIGHT
:
1486 case (SUPERDOM_RIGHT
|BUTTON_REPEAT
):
1487 draw_cursor(); /* Deselect the current tile */
1505 case (SUPERDOM_UP
|BUTTON_REPEAT
):
1506 draw_cursor(); /* Deselect the current tile */
1510 #if CONFIG_KEYPAD == IRIVER_H10_PAD
1522 case (SUPERDOM_DOWN
|BUTTON_REPEAT
):
1523 draw_cursor(); /* Deselect the current tile */
1527 #if CONFIG_KEYPAD == IRIVER_H10_PAD
1540 if (rb
->default_event_handler(button
) == SYS_USB_CONNECTED
)
1542 return PLUGIN_USB_CONNECTED
;
1548 int killmen(int colour
) {
1549 bool human
= (colour
== COLOUR_LIGHT
);
1553 percent
= (humanres
.food
*1000)/humanres
.men
;
1556 percent
= (compres
.food
*1000)/compres
.men
;
1562 if(board
[i
][j
].colour
== colour
) {
1563 int nummen
= ((board
[i
][j
].men
* percent
)/1000);
1564 menkilled
+= board
[i
][j
].men
- nummen
;
1565 board
[i
][j
].men
= nummen
;
1571 humanres
.men
-= menkilled
;
1573 compres
.men
-= menkilled
;
1577 /* return -1 if error, 1 if attack is succeeded, 0 otherwise */
1578 int attack_territory(int colour
, int x
, int y
) {
1579 bool human
= (colour
== COLOUR_LIGHT
);
1582 if(board
[x
][y
].colour
== colour
) {
1584 rb
->splash(HZ
, "You can't attack your own territory");
1587 str_diff
= calc_strength(COLOUR_DARK
, x
, y
) -
1588 calc_strength(COLOUR_LIGHT
, x
, y
);
1590 str_diff
= -str_diff
;
1592 rb
->srand(*rb
->current_tick
);
1593 if(str_diff
> 0 || (str_diff
== 0 && rb
->rand()%2)) {
1594 struct resources
*offres
, *defres
;
1602 defres
->men
-= board
[x
][y
].men
;
1603 defres
->tanks
-= board
[x
][y
].tank
;
1604 defres
->planes
-= board
[x
][y
].plane
;
1605 defres
->nukes
-= board
[x
][y
].nuke
;
1606 defres
->farms
-= board
[x
][y
].farm
;
1607 defres
->inds
-= board
[x
][y
].ind
;
1608 offres
->farms
+= board
[x
][y
].farm
;
1609 offres
->inds
+= board
[x
][y
].ind
;
1610 board
[x
][y
].colour
= colour
;
1611 board
[x
][y
].men
= 0;
1612 board
[x
][y
].tank
= false;
1613 board
[x
][y
].plane
= false;
1614 board
[x
][y
].nuke
= false;
1623 rb
->splash(HZ
, "Your troops were unable to overcome"
1624 " the enemy troops");
1626 rb
->splash(HZ
*2, "The computer attempted to "
1627 "attack, but the invasion was"
1634 int war_menu(void) {
1635 int selection
, tempmenu
;
1637 MENUITEM_STRINGLIST(wartime_menu
, "War!", NULL
,
1638 "Select territory to attack", "Finish turn", "Game menu");
1640 while(humanres
.moves
) {
1641 selection
=rb
->do_menu(&wartime_menu
,&selection
, NULL
, false);
1644 switch(select_square()) {
1646 if(attack_territory(COLOUR_LIGHT
, cursor
.x
, cursor
.y
)
1650 case PLUGIN_USB_CONNECTED
:
1651 return PLUGIN_USB_CONNECTED
;
1659 tempmenu
= ingame_menu();
1661 case PLUGIN_USB_CONNECTED
:
1662 return PLUGIN_USB_CONNECTED
;
1665 return SUPERDOM_QUIT
;
1680 bool place_adjacent(bool tank
, int x
, int y
) {
1681 int type
= (tank
? 1: 2);
1682 if(!buy_resources(COLOUR_DARK
, type
, x
, y
, 0)) {
1685 if(!buy_resources(COLOUR_DARK
, type
, x
-1, y
, 0)) {
1688 if(!buy_resources(COLOUR_DARK
, type
, x
+1, y
, 0)) {
1691 if(!buy_resources(COLOUR_DARK
, type
, x
, y
-1, 0)) {
1694 if(!buy_resources(COLOUR_DARK
, type
, x
, y
+1, 0)) {
1700 bool has_adjacent(int x
, int y
) {
1701 if((board
[x
][y
].colour
== COLOUR_LIGHT
) &&
1702 ((board
[x
-1][y
].colour
== COLOUR_DARK
) ||
1703 (board
[x
+1][y
].colour
== COLOUR_DARK
) ||
1704 (board
[x
][y
+1].colour
== COLOUR_DARK
) ||
1705 (board
[x
][y
-1].colour
== COLOUR_DARK
)))
1711 void find_adjacent(int x
, int y
, int* adj_x
, int* adj_y
) {
1712 /* Finds adjacent squares, returning squares without tanks on them
1713 * in preference to those with them */
1714 if(board
[x
-1][y
].colour
== COLOUR_DARK
) {
1719 if(board
[x
+1][y
].colour
== COLOUR_DARK
) {
1724 if(board
[x
][y
-1].colour
== COLOUR_DARK
) {
1729 if(board
[x
][y
+1].colour
== COLOUR_DARK
) {
1736 void computer_allocate(void) {
1737 /* Firstly, decide whether to go offensive or defensive.
1738 * This is primarily decided by the human player posing a threat to either
1739 * the computer's farms or factories */
1741 bool offensive
= true;
1742 struct threat threats
[4];
1744 int total_str_diff
= 0;
1745 int numterritory
= 0;
1748 struct threat targets
[2];
1752 compres
.cash
+= compres
.bank
;
1756 if(board
[i
][j
].colour
== COLOUR_DARK
) {
1758 str_diff
= calc_strength(COLOUR_LIGHT
,i
,j
) -
1759 calc_strength(COLOUR_DARK
,i
,j
);
1760 if(str_diff
> 0 && (board
[i
][j
].ind
|| board
[i
][j
].farm
)) {
1761 if(numthreats
< 3) {
1763 threats
[numthreats
].x
= i
;
1764 threats
[numthreats
].y
= j
;
1765 threats
[numthreats
].str_diff
= str_diff
;
1774 /* The AI is going to go straight for the throat here and attack
1775 * the player's farms and factories. The amount of cash
1776 * the AI has to spend will determine how many targets there are */
1777 if(compres
.cash
> 1200) {
1778 /* 1200 is a figure I pulled out of nowhere. Adjust as needed */
1783 /* Work out which target(s) to attack. They must have adjacent squares
1784 * owned by the computer. If none are found just place troops in
1785 * random places around the map until we run out of money */
1789 if(has_adjacent(i
,j
) &&
1790 (board
[i
][j
].ind
|| board
[i
][j
].farm
)) {
1794 targets
[k
].str_diff
=
1795 calc_strength(COLOUR_LIGHT
, i
, j
) -
1796 calc_strength(COLOUR_DARK
, i
, j
);
1804 /* No targets found! Randomly pick squares and if they're owned
1805 * by the computer then stick a tank on it. */
1806 rb
->srand(*rb
->current_tick
);
1807 while(compres
.cash
>= 300 && compres
.tanks
< numterritory
) {
1808 i
= rb
->rand()%10 + 1;
1809 j
= rb
->rand()%10 + 1;
1810 if(board
[i
][j
].colour
== COLOUR_DARK
) {
1811 buy_resources(COLOUR_DARK
, 1, i
, j
, 0);
1817 str_diff
= targets
[i
].str_diff
;
1818 while(str_diff
+ 20 > 0 && compres
.cash
> 0) {
1819 /* While we still need them keep placing men */
1820 if(!place_adjacent(true, targets
[i
].x
, targets
[i
].y
)) {
1821 find_adjacent(targets
[i
].x
, targets
[i
].y
,
1823 men_needed
= (str_diff
+ 20)*1000/133;
1824 if(compres
.cash
< men_needed
) {
1825 men_needed
= compres
.cash
;
1827 buy_resources(COLOUR_DARK
, 0, adj
.x
, adj
.y
,
1831 str_diff
= calc_strength(COLOUR_LIGHT
,
1832 targets
[i
].x
, targets
[i
].y
) -
1833 calc_strength(COLOUR_DARK
,
1834 targets
[i
].x
, targets
[i
].y
);
1839 /* Work out what to place on each square to defend it.
1840 * Tanks are preferential because they do not require food,
1841 * but if the budget is tight then we fall back onto troops.
1842 * Conversely if cash is not an issue and there are already tanks in
1843 * place planes will be deployed. We would like a margin of at least
1844 * 20 points to be safe. */
1846 for(i
=0;i
<numthreats
;i
++) {
1847 total_str_diff
+= threats
[i
].str_diff
;
1849 if((total_str_diff
+20)*10 > compres
.cash
) {
1850 /* Not enough cash to accomodate all threats using tanks alone -
1851 * use men as a backup */
1852 for(i
=0;i
<numthreats
;i
++) {
1853 men_needed
= ((threats
[i
].str_diff
+ 20)*1000)/133;
1854 if(compres
.cash
< men_needed
) {
1855 men_needed
= compres
.cash
;
1857 buy_resources(COLOUR_DARK
, 0, threats
[i
].x
, threats
[i
].y
,
1862 /* Enough money to pay their way by planes? */
1863 bool tank
= ((total_str_diff
+20)*15 >= compres
.cash
);
1864 for(i
=0;i
<numthreats
;i
++) {
1865 str_diff
= threats
[i
].str_diff
;
1866 while(str_diff
+ 20 > 0) {
1867 if(!place_adjacent(tank
, threats
[i
].x
, threats
[i
].y
)) {
1868 /* No room for any more planes or tanks, revert to
1870 find_adjacent(threats
[i
].x
, threats
[i
].y
,
1872 men_needed
= (str_diff
+ 20)*1000/133;
1873 if(compres
.cash
< men_needed
) {
1874 men_needed
= compres
.cash
;
1876 buy_resources(COLOUR_DARK
, 0, threats
[i
].x
,
1877 threats
[i
].y
, men_needed
);
1880 str_diff
= calc_strength(COLOUR_LIGHT
,
1881 threats
[i
].x
, threats
[i
].y
) -
1882 calc_strength(COLOUR_DARK
,
1883 threats
[i
].x
, threats
[i
].y
);
1888 compres
.bank
+= compres
.cash
;
1892 int find_adj_target(int x
, int y
, struct cursor
* adj
) {
1893 /* Find a square next to a computer's farm or factory owned by the player
1894 * that is vulnerable. Return 1 on success, 0 otherwise */
1895 if(board
[x
+1][y
].colour
== COLOUR_LIGHT
&&
1896 calc_strength(COLOUR_LIGHT
,x
+1,y
)<=calc_strength(COLOUR_DARK
,x
+1,y
)) {
1901 if(board
[x
-1][y
].colour
== COLOUR_LIGHT
&&
1902 calc_strength(COLOUR_LIGHT
,x
-1,y
)<=calc_strength(COLOUR_DARK
,x
-1,y
)) {
1907 if(board
[x
][y
+1].colour
== COLOUR_LIGHT
&&
1908 calc_strength(COLOUR_LIGHT
,x
,y
+1)<=calc_strength(COLOUR_DARK
,x
,y
+1)) {
1913 if(board
[x
][y
-1].colour
== COLOUR_LIGHT
&&
1914 calc_strength(COLOUR_LIGHT
,x
,y
-1)<=calc_strength(COLOUR_DARK
,x
,y
-1)) {
1922 void computer_war(void) {
1923 /* Work out where to attack - prioritise the defence of buildings */
1925 bool found_target
= true;
1928 while(found_target
) {
1929 found_target
= false;
1932 if((board
[i
][j
].colour
== COLOUR_DARK
) &&
1933 (board
[i
][j
].farm
|| board
[i
][j
].ind
) &&
1934 find_adj_target(i
, j
, &adj
)) {
1935 found_target
= true;
1936 if(attack_territory(COLOUR_DARK
, adj
.x
, adj
.y
) >= 0) {
1946 /* Defence stage done, move on to OFFENCE */
1947 found_target
= true;
1948 while(found_target
) {
1949 found_target
= false;
1952 if(board
[i
][j
].colour
== COLOUR_LIGHT
&&
1953 (board
[i
][j
].ind
|| board
[i
][j
].farm
) &&
1954 (calc_strength(COLOUR_DARK
, i
, j
) >=
1955 calc_strength(COLOUR_LIGHT
, i
, j
))) {
1956 found_target
= true;
1957 if(attack_territory(COLOUR_DARK
, i
, j
) >= 0) {
1967 /* Spend leftover moves wherever attacking randomly */
1968 found_target
= true;
1969 while(found_target
) {
1970 found_target
= false;
1973 if(board
[i
][j
].colour
== COLOUR_LIGHT
&&
1974 (calc_strength(COLOUR_DARK
, i
, j
) >=
1975 calc_strength(COLOUR_LIGHT
, i
, j
))) {
1976 found_target
= true;
1977 if(attack_territory(COLOUR_DARK
, i
, j
) >= 0) {
1989 static int load_game(const char* file
) {
1992 fd
= rb
->open(file
, O_RDONLY
);
1994 DEBUGF("Couldn't open savegame\n");
1997 rb
->read(fd
, buf
, 5);
1998 if(rb
->strcmp(buf
, "SSGv3")) {
1999 rb
->splash(HZ
, "Invalid/incompatible savegame");
2002 rb
->read(fd
, &gamestate
, sizeof(gamestate
));
2003 rb
->read(fd
, &humanres
.cash
, sizeof(humanres
.cash
));
2004 rb
->read(fd
, &humanres
.food
, sizeof(humanres
.food
));
2005 rb
->read(fd
, &humanres
.bank
, sizeof(humanres
.bank
));
2006 rb
->read(fd
, &humanres
.planes
, sizeof(humanres
.planes
));
2007 rb
->read(fd
, &humanres
.tanks
, sizeof(humanres
.tanks
));
2008 rb
->read(fd
, &humanres
.men
, sizeof(humanres
.men
));
2009 rb
->read(fd
, &humanres
.nukes
, sizeof(humanres
.nukes
));
2010 rb
->read(fd
, &humanres
.inds
, sizeof(humanres
.inds
));
2011 rb
->read(fd
, &humanres
.farms
, sizeof(humanres
.farms
));
2012 rb
->read(fd
, &humanres
.moves
, sizeof(humanres
.moves
));
2013 rb
->read(fd
, &compres
.cash
, sizeof(humanres
.cash
));
2014 rb
->read(fd
, &compres
.food
, sizeof(humanres
.food
));
2015 rb
->read(fd
, &compres
.bank
, sizeof(humanres
.bank
));
2016 rb
->read(fd
, &compres
.planes
, sizeof(humanres
.planes
));
2017 rb
->read(fd
, &compres
.tanks
, sizeof(humanres
.tanks
));
2018 rb
->read(fd
, &compres
.men
, sizeof(humanres
.men
));
2019 rb
->read(fd
, &compres
.nukes
, sizeof(humanres
.nukes
));
2020 rb
->read(fd
, &compres
.inds
, sizeof(humanres
.inds
));
2021 rb
->read(fd
, &compres
.farms
, sizeof(humanres
.farms
));
2022 rb
->read(fd
, &compres
.moves
, sizeof(humanres
.moves
));
2023 rb
->read(fd
, board
, sizeof(board
));
2024 rb
->read(fd
, &superdom_settings
.compstartfarms
, sizeof(int));
2025 rb
->read(fd
, &superdom_settings
.compstartinds
, sizeof(int));
2026 rb
->read(fd
, &superdom_settings
.humanstartfarms
, sizeof(int));
2027 rb
->read(fd
, &superdom_settings
.humanstartfarms
, sizeof(int));
2028 rb
->read(fd
, &superdom_settings
.startcash
, sizeof(int));
2029 rb
->read(fd
, &superdom_settings
.startfood
, sizeof(int));
2030 rb
->read(fd
, &superdom_settings
.movesperturn
, sizeof(int));
2035 void default_settings(void) {
2036 superdom_settings
.compstartfarms
= 1;
2037 superdom_settings
.compstartinds
= 1;
2038 superdom_settings
.humanstartfarms
= 2;
2039 superdom_settings
.humanstartinds
= 2;
2040 superdom_settings
.startcash
= 0;
2041 superdom_settings
.startfood
= 0;
2042 superdom_settings
.movesperturn
= 2;
2045 int average_strength(int colour
) {
2046 /* This function calculates the average strength of the given player,
2047 * used to determine when the computer wins or loses. */
2052 if(board
[i
][j
].colour
!= -1) {
2053 totalpower
+= calc_strength(colour
, i
, j
);
2057 return totalpower
/100;
2060 enum plugin_status
plugin_start(const void* parameter
)
2063 rb
->lcd_set_backdrop(NULL
);
2064 rb
->lcd_set_foreground(LCD_BLACK
);
2065 rb
->lcd_set_background(LCD_WHITE
);
2072 if(load_game(parameter
) != 0) {
2073 DEBUGF("Loading failed, generating new game\n");
2101 case PLUGIN_USB_CONNECTED
:
2102 return PLUGIN_USB_CONNECTED
;
2111 int avg_str_diff
= (average_strength(COLOUR_LIGHT
) -
2112 average_strength(COLOUR_DARK
));
2113 if(avg_str_diff
> 15) {
2114 rb
->splash(HZ
*4, "The computer has surrendered. You win.");
2117 if(-avg_str_diff
> 15) {
2118 rb
->splash(HZ
*4, "Your army have suffered terrible morale from"
2119 " the bleak prospects of winning. You lose.");
2125 gamestate
= GS_PROD
;
2126 switch(production_menu()) {
2127 case PLUGIN_USB_CONNECTED
:
2128 return PLUGIN_USB_CONNECTED
;
2134 computer_allocate();
2137 humanres
.moves
= superdom_settings
.movesperturn
;
2139 gamestate
= GS_MOVE
;
2140 switch(movement_menu()) {
2141 case PLUGIN_USB_CONNECTED
:
2142 return PLUGIN_USB_CONNECTED
;
2150 if(humanres
.food
> humanres
.men
) {
2151 rb
->snprintf(buf
, sizeof(buf
), "Your men ate %d units of food",
2153 humanres
.food
-= humanres
.men
;
2155 rb
->snprintf(buf
, sizeof(buf
), "There was not enough food"
2156 " to feed all your men, %d men have died of starvation",
2157 killmen(COLOUR_LIGHT
));
2159 rb
->splash(HZ
*2, buf
);
2162 if(compres
.food
> compres
.men
) {
2163 compres
.food
-= compres
.men
;
2165 rb
->snprintf(buf
, sizeof(buf
), "The computer does not have"
2166 " enough food to feed its men. %d have died of starvation",
2167 killmen(COLOUR_DARK
));
2168 rb
->splash(HZ
, buf
);
2172 humanres
.moves
= superdom_settings
.movesperturn
;
2175 switch(war_menu()) {
2176 case PLUGIN_USB_CONNECTED
:
2177 return PLUGIN_USB_CONNECTED
;
2183 compres
.moves
= superdom_settings
.movesperturn
;