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"
24 #include "pluginbitmaps/superdom_boarditems.h"
27 extern const fb_data superdom_boarditems
[];
31 #define COLOUR_LIGHT 1
36 #define MY_BITMAP_PART rb->lcd_bitmap_transparent_part
38 #define MY_BITMAP_PART rb->lcd_mono_bitmap_part
41 #if LCD_WIDTH > LCD_HEIGHT
42 #define BOX_WIDTH ((LCD_WIDTH-(MARGIN*2))/10)
43 #define BOX_HEIGHT ((BOX_WIDTH*2)/3)
46 #define BOX_HEIGHT ((LCD_HEIGHT-(MARGIN*2)-15)/10)
47 #define BOX_WIDTH ((BOX_HEIGHT*2)/3)
51 /* NUM_BOX HEIGHT and WIDTH are used for the number pad in the game. The height
52 * calculation includes spacing for the text placed above and below the number
53 * pad (it divides by 6 instead of just 4). The width calculation gives extra
54 * spacing on the sides of the pad too (divides by 5 instead of 3).
56 #define NUM_BOX_HEIGHT (LCD_HEIGHT/6)
57 #define NUM_BOX_WIDTH (LCD_WIDTH/5)
59 #define NUM_MARGIN_X (LCD_WIDTH-3*NUM_BOX_WIDTH)/2
60 #define NUM_MARGIN_Y (LCD_HEIGHT-4*NUM_BOX_HEIGHT)/2
62 /* These parameters define the piece image dimensions, Stride is the total width
65 #define ICON_STRIDE STRIDE(SCREEN_MAIN, BMPWIDTH_superdom_boarditems, BMPHEIGHT_superdom_boarditems)
66 #define ICON_HEIGHT (BMPHEIGHT_superdom_boarditems/6)
67 #define ICON_WIDTH (BMPWIDTH_superdom_boarditems/2)
69 #if (CONFIG_KEYPAD == IPOD_4G_PAD) || (CONFIG_KEYPAD == IPOD_3G_PAD) || \
70 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
71 #define SUPERDOM_OK BUTTON_SELECT
72 #define SUPERDOM_CANCEL BUTTON_MENU
73 #define SUPERDOM_LEFT BUTTON_LEFT
74 #define SUPERDOM_RIGHT BUTTON_RIGHT
77 #elif CONFIG_KEYPAD == IRIVER_H300_PAD || CONFIG_KEYPAD == IRIVER_H100_PAD
78 #define SUPERDOM_OK BUTTON_SELECT
79 #define SUPERDOM_LEFT BUTTON_LEFT
80 #define SUPERDOM_RIGHT BUTTON_RIGHT
81 #define SUPERDOM_UP BUTTON_UP
82 #define SUPERDOM_DOWN BUTTON_DOWN
83 #define SUPERDOM_CANCEL BUTTON_OFF
85 #elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
86 #define SUPERDOM_OK BUTTON_SELECT
87 #define SUPERDOM_LEFT BUTTON_LEFT
88 #define SUPERDOM_RIGHT BUTTON_RIGHT
89 #define SUPERDOM_UP BUTTON_UP
90 #define SUPERDOM_DOWN BUTTON_DOWN
91 #define SUPERDOM_CANCEL BUTTON_REC
93 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
94 #define SUPERDOM_OK BUTTON_RIGHT
95 #define SUPERDOM_UP BUTTON_SCROLL_UP
96 #define SUPERDOM_DOWN BUTTON_SCROLL_DOWN
97 #define SUPERDOM_CANCEL BUTTON_LEFT
99 #elif CONFIG_KEYPAD == GIGABEAT_PAD
100 #define SUPERDOM_OK BUTTON_SELECT
101 #define SUPERDOM_UP BUTTON_UP
102 #define SUPERDOM_DOWN BUTTON_DOWN
103 #define SUPERDOM_LEFT BUTTON_LEFT
104 #define SUPERDOM_RIGHT BUTTON_RIGHT
105 #define SUPERDOM_CANCEL BUTTON_POWER
107 #elif CONFIG_KEYPAD == SANSA_E200_PAD
108 #define SUPERDOM_OK BUTTON_SELECT
109 #define SUPERDOM_UP BUTTON_SCROLL_BACK
110 #define SUPERDOM_DOWN BUTTON_SCROLL_FWD
111 #define SUPERDOM_LEFT BUTTON_LEFT
112 #define SUPERDOM_RIGHT BUTTON_RIGHT
113 #define SUPERDOM_CANCEL BUTTON_POWER
115 #elif CONFIG_KEYPAD == SANSA_FUZE_PAD
116 #define SUPERDOM_OK BUTTON_SELECT
117 #define SUPERDOM_UP BUTTON_SCROLL_BACK
118 #define SUPERDOM_DOWN BUTTON_SCROLL_FWD
119 #define SUPERDOM_LEFT BUTTON_LEFT
120 #define SUPERDOM_RIGHT BUTTON_RIGHT
121 #define SUPERDOM_CANCEL (BUTTON_HOME|BUTTON_REPEAT)
123 #elif CONFIG_KEYPAD == GIGABEAT_S_PAD
124 #define SUPERDOM_OK BUTTON_SELECT
125 #define SUPERDOM_UP BUTTON_UP
126 #define SUPERDOM_DOWN BUTTON_DOWN
127 #define SUPERDOM_LEFT BUTTON_LEFT
128 #define SUPERDOM_RIGHT BUTTON_RIGHT
129 #define SUPERDOM_CANCEL BUTTON_BACK
131 #elif CONFIG_KEYPAD == COWON_D2_PAD
132 #define SUPERDOM_CANCEL BUTTON_POWER
134 #elif CONFIG_KEYPAD == CREATIVEZVM_PAD
135 #define SUPERDOM_OK BUTTON_SELECT
136 #define SUPERDOM_UP BUTTON_UP
137 #define SUPERDOM_DOWN BUTTON_DOWN
138 #define SUPERDOM_LEFT BUTTON_LEFT
139 #define SUPERDOM_RIGHT BUTTON_RIGHT
140 #define SUPERDOM_CANCEL BUTTON_BACK
142 #elif CONFIG_KEYPAD == PHILIPS_SA9200_PAD
143 #define SUPERDOM_OK BUTTON_PLAY
144 #define SUPERDOM_UP BUTTON_UP
145 #define SUPERDOM_DOWN BUTTON_DOWN
146 #define SUPERDOM_LEFT BUTTON_PREV
147 #define SUPERDOM_RIGHT BUTTON_NEXT
148 #define SUPERDOM_CANCEL BUTTON_LEFT
150 #elif (CONFIG_KEYPAD == ONDAVX747_PAD) || (CONFIG_KEYPAD == MROBE500_PAD)
151 #define SUPERDOM_CANCEL BUTTON_POWER
153 #elif CONFIG_KEYPAD == SAMSUNG_YH_PAD
154 #define SUPERDOM_OK BUTTON_PLAY
155 #define SUPERDOM_UP BUTTON_UP
156 #define SUPERDOM_DOWN BUTTON_DOWN
157 #define SUPERDOM_LEFT BUTTON_LEFT
158 #define SUPERDOM_RIGHT BUTTON_RIGHT
159 #define SUPERDOM_CANCEL BUTTON_REW
161 #elif CONFIG_KEYPAD == PBELL_VIBE500_PAD
162 #define SUPERDOM_OK BUTTON_OK
163 #define SUPERDOM_UP BUTTON_UP
164 #define SUPERDOM_DOWN BUTTON_DOWN
165 #define SUPERDOM_LEFT BUTTON_PREV
166 #define SUPERDOM_RIGHT BUTTON_NEXT
167 #define SUPERDOM_CANCEL BUTTON_CANCEL
171 #ifdef HAVE_TOUCHSCREEN
173 #define SUPERDOM_OK BUTTON_CENTER
176 #define SUPERDOM_UP BUTTON_TOPMIDDLE
178 #ifndef SUPERDOM_LEFT
179 #define SUPERDOM_LEFT BUTTON_MIDLEFT
181 #ifndef SUPERDOM_RIGHT
182 #define SUPERDOM_RIGHT BUTTON_MIDRIGHT
184 #ifndef SUPERDOM_DOWN
185 #define SUPERDOM_DOWN BUTTON_BOTTOMMIDDLE
187 #ifndef SUPERDOM_CANCEL
188 #define SUPERDOM_CANCEL BUTTON_TOPLEFT
195 RET_VAL_QUIT_ERR
, /* quit or error */
198 void gen_interest(void);
199 void init_resources(void);
200 int select_square(void);
201 void update_score(void);
202 void gen_resources(void);
203 void draw_cursor(void);
204 void draw_board(void);
207 signed int colour
; /* -1 = Unset */
239 struct resources humanres
;
240 struct resources compres
;
241 enum { GS_PROD
, GS_MOVE
, GS_WAR
};
249 struct tile board
[12][12];
251 void init_board(void) {
253 rb
->srand(*rb
->current_tick
);
254 for(i
=0;i
<12;i
++) { /* Hopefully about 50% each colour */
256 if((i
<1)||(j
<1)||(i
>10)||(j
>10))
257 board
[i
][j
].colour
= -1; /* Unset */
259 board
[i
][j
].colour
= rb
->rand()%2;
260 board
[i
][j
].tank
= false;
261 board
[i
][j
].plane
= false;
262 board
[i
][j
].nuke
= false;
263 board
[i
][j
].ind
= false;
264 board
[i
][j
].farm
= false;
269 while(compres
.farms
< superdom_settings
.compstartfarms
) {
270 i
= rb
->rand()%10 + 1;
271 j
= rb
->rand()%10 + 1;
272 if((board
[i
][j
].colour
== COLOUR_DARK
) && (board
[i
][j
].farm
== false)) {
273 board
[i
][j
].farm
= true;
277 while(compres
.inds
< superdom_settings
.compstartinds
) {
278 i
= rb
->rand()%10 + 1;
279 j
= rb
->rand()%10 + 1;
280 if((board
[i
][j
].colour
== COLOUR_DARK
) && (board
[i
][j
].ind
== false)) {
281 board
[i
][j
].ind
= true;
285 while(humanres
.farms
< superdom_settings
.humanstartfarms
) {
286 i
= rb
->rand()%10 + 1;
287 j
= rb
->rand()%10 + 1;
288 if((board
[i
][j
].colour
== COLOUR_LIGHT
)&&(board
[i
][j
].farm
== false)) {
289 board
[i
][j
].farm
= true;
293 while(humanres
.inds
< superdom_settings
.humanstartinds
) {
294 i
= rb
->rand()%10 + 1;
295 j
= rb
->rand()%10 + 1;
296 if((board
[i
][j
].colour
== COLOUR_LIGHT
) && (board
[i
][j
].ind
== false)) {
297 board
[i
][j
].ind
= true;
303 void draw_board(void) {
305 rb
->lcd_clear_display();
308 if(board
[i
][j
].colour
== COLOUR_DARK
) {
309 rb
->lcd_set_foreground(LCD_DARKGRAY
);
311 rb
->lcd_set_foreground(LCD_LIGHTGRAY
);
313 rb
->lcd_fillrect(MARGIN
+(BOX_WIDTH
*(i
-1)),
314 MARGIN
+(BOX_HEIGHT
*(j
-1)), BOX_WIDTH
,
317 rb
->lcd_set_drawmode(DRMODE_BG
| DRMODE_INVERSEVID
);
319 if(board
[i
][j
].ind
) {
320 MY_BITMAP_PART(superdom_boarditems
,
321 board
[i
][j
].colour
?ICON_WIDTH
:0, 0, ICON_STRIDE
,
322 #if LCD_WIDTH > LCD_HEIGHT
323 MARGIN
+(BOX_WIDTH
*(i
-1))+1,
324 MARGIN
+(BOX_HEIGHT
*(j
-1))+ICON_HEIGHT
+1,
326 MARGIN
+(BOX_WIDTH
*(i
-1))+1+ICON_WIDTH
,
327 MARGIN
+(BOX_HEIGHT
*(j
-1))+1,
329 ICON_WIDTH
, ICON_HEIGHT
);
331 if(board
[i
][j
].farm
) {
332 MY_BITMAP_PART(superdom_boarditems
,
333 board
[i
][j
].colour
?ICON_WIDTH
:0, ICON_HEIGHT
,
334 ICON_STRIDE
, MARGIN
+(BOX_WIDTH
*(i
-1))+1,
335 MARGIN
+(BOX_HEIGHT
*(j
-1))+1,
336 ICON_WIDTH
, ICON_HEIGHT
);
338 if(board
[i
][j
].tank
) {
339 MY_BITMAP_PART(superdom_boarditems
,
340 board
[i
][j
].colour
?ICON_WIDTH
:0, ICON_HEIGHT
*2,
341 ICON_STRIDE
, MARGIN
+(BOX_WIDTH
*(i
-1))+ICON_WIDTH
+1,
342 MARGIN
+(BOX_HEIGHT
*(j
-1))+ICON_HEIGHT
+1,
343 ICON_WIDTH
, ICON_HEIGHT
);
345 if(board
[i
][j
].men
) {
346 MY_BITMAP_PART(superdom_boarditems
,
347 board
[i
][j
].colour
?ICON_WIDTH
:0, ICON_HEIGHT
*3,
348 #if LCD_WIDTH > LCD_HEIGHT
349 ICON_STRIDE
, MARGIN
+(BOX_WIDTH
*(i
-1))+ICON_WIDTH
+1,
350 MARGIN
+(BOX_HEIGHT
*(j
-1))+1,
352 ICON_STRIDE
, MARGIN
+(BOX_WIDTH
*(i
-1))+1,
353 MARGIN
+(BOX_HEIGHT
*(j
-1))+1+ICON_HEIGHT
,
355 ICON_WIDTH
, ICON_HEIGHT
);
357 if(board
[i
][j
].plane
) {
358 MY_BITMAP_PART(superdom_boarditems
,
359 board
[i
][j
].colour
?ICON_WIDTH
:0, ICON_HEIGHT
*4,
360 #if LCD_WIDTH > LCD_HEIGHT
361 ICON_STRIDE
,MARGIN
+(BOX_WIDTH
*(i
-1))+ICON_WIDTH
*2+1,
362 MARGIN
+(BOX_HEIGHT
*(j
-1))+ICON_HEIGHT
+1,
364 ICON_STRIDE
,MARGIN
+(BOX_WIDTH
*(i
-1))+ICON_WIDTH
+1,
365 MARGIN
+(BOX_HEIGHT
*(j
-1))+ICON_HEIGHT
*2+1,
367 ICON_WIDTH
, ICON_HEIGHT
);
369 if(board
[i
][j
].nuke
) {
370 MY_BITMAP_PART(superdom_boarditems
,
371 board
[i
][j
].colour
?ICON_WIDTH
:0, ICON_HEIGHT
*5,
372 #if LCD_WIDTH > LCD_HEIGHT
373 ICON_STRIDE
,MARGIN
+(BOX_WIDTH
*(i
-1))+ICON_WIDTH
*2+1,
374 MARGIN
+(BOX_HEIGHT
*(j
-1))+1,
376 ICON_STRIDE
,MARGIN
+(BOX_WIDTH
*(i
-1))+1,
377 MARGIN
+(BOX_HEIGHT
*(j
-1))+ICON_HEIGHT
*2+1,
379 ICON_WIDTH
, ICON_HEIGHT
);
382 rb
->lcd_set_drawmode(DRMODE_SOLID
);
386 rb
->lcd_set_foreground(LCD_BLACK
);
387 for(i
=0;i
<=10;i
++) { /* Draw Horizontal lines */
388 rb
->lcd_hline(MARGIN
, MARGIN
+(BOX_WIDTH
*10), MARGIN
+(BOX_HEIGHT
*i
));
390 for(i
=0;i
<=10;i
++) { /* Draw Vertical lines */
391 rb
->lcd_vline(MARGIN
+(BOX_WIDTH
*i
), MARGIN
, MARGIN
+(BOX_HEIGHT
*10));
396 int calc_strength(int colour
, int x
, int y
) {
398 for (a
= -1; a
< 2; a
++) {
399 for (b
= -1; b
< 2; b
++) {
400 if ((b
== 0 || a
== 0) &&
401 (board
[x
+ a
][y
+ b
].colour
== colour
)) {
403 if(board
[x
+ a
][y
+ b
].tank
|| board
[x
+ a
][y
+ b
].farm
)
405 if(board
[x
+ a
][y
+ b
].plane
|| board
[x
+ a
][y
+ b
].ind
)
407 if(board
[x
+ a
][y
+ b
].nuke
)
409 if(board
[x
+ a
][y
+ b
].men
)
410 score
+= (board
[x
+ a
][y
+ b
].men
*133/1000);
417 void gen_interest(void) {
418 /* Interest should be around 10% */
419 rb
->srand(*rb
->current_tick
);
420 int interest
= 7+rb
->rand()%6;
421 humanres
.bank
= humanres
.bank
+(interest
*humanres
.bank
/100);
422 compres
.bank
= compres
.bank
+(interest
*compres
.bank
/100);
425 void draw_cursor(void) {
426 rb
->lcd_set_drawmode(DRMODE_COMPLEMENT
);
427 rb
->lcd_fillrect(MARGIN
+((cursor
.x
-1)*BOX_WIDTH
),
428 MARGIN
+((cursor
.y
-1)*BOX_HEIGHT
), BOX_WIDTH
+1, BOX_HEIGHT
+1);
429 rb
->lcd_set_drawmode(DRMODE_SOLID
);
433 void gen_resources(void) {
440 rb
->srand(*rb
->current_tick
);
441 /* Generate Human's resources */
442 for(i
=0;i
<humanres
.inds
;i
++) {
443 inccash
+= (300+rb
->rand()%200);
445 for(i
=0;i
<humanres
.farms
;i
++) {
446 incfood
+= (200+rb
->rand()%200);
449 ratecash
= inccash
/humanres
.inds
;
451 ratefood
= incfood
/humanres
.farms
;
454 rb
->splash(HZ
*2, "Patriotism sweeps the land, all production"
455 " is up this year!");
457 rb
->splash(HZ
*2, "Factories working at maximum efficiency,"
458 " cash production up this year!");
460 } else if(ratecash
> 350) {
462 rb
->splash(HZ
*2, "Record crop harvest this year!");
463 } else if(ratefood
> 250) {
464 rb
->splash(HZ
*2, "Production continues as normal");
466 rb
->splash(HZ
*2, "Spoilage of crops leads to reduced farm"
467 " output this year");
471 rb
->splash(HZ
*2, "Record crop harvest this year!");
472 } else if(ratefood
> 250) {
473 rb
->splash(HZ
*2, "Factory unions introduced. Industrial"
474 " production is down this year.");
476 rb
->splash(HZ
*2, "Internet created. All production is down"
477 " due to time wasted.");
480 humanres
.cash
+= inccash
;
481 humanres
.food
+= incfood
;
483 /* Generate Computer's resources */
486 for(i
=0;i
<compres
.inds
;i
++) {
487 inccash
+= (300+rb
->rand()%200);
489 for(i
=0;i
<compres
.farms
;i
++) {
490 incfood
+= (200+rb
->rand()%200);
492 compres
.cash
+= inccash
;
493 compres
.food
+= incfood
;
496 void update_score(void) {
498 rb
->lcd_setfont(FONT_SYSFIXED
);
499 rb
->lcd_set_drawmode(DRMODE_BG
|DRMODE_INVERSEVID
);
500 rb
->lcd_fillrect(5,LCD_HEIGHT
-20,105,20);
501 rb
->lcd_set_drawmode(DRMODE_SOLID
);
502 strength
= calc_strength(COLOUR_LIGHT
, cursor
.x
, cursor
.y
);
503 rb
->snprintf(buf
, sizeof(buf
), "Your power: %d.%d",
504 strength
/10, strength
%10);
505 rb
->lcd_putsxy(5,LCD_HEIGHT
-20, buf
);
506 strength
= calc_strength(COLOUR_DARK
, cursor
.x
, cursor
.y
);
507 rb
->snprintf(buf
, sizeof(buf
), "Comp power: %d.%d",
508 strength
/10, strength
%10);
509 rb
->lcd_putsxy(5,LCD_HEIGHT
-10, buf
);
510 rb
->lcd_setfont(FONT_UI
);
513 int settings_menu(void) {
516 MENUITEM_STRINGLIST(menu
, "Super Domination Settings", NULL
,
517 "Computer starting farms", "Computer starting factories",
518 "Human starting farms", "Human starting factories",
519 "Starting cash", "Starting food", "Moves per turn");
522 switch(rb
->do_menu(&menu
, &selection
, NULL
, false)) {
524 rb
->set_int("Computer starting farms", "", UNIT_INT
,
525 &superdom_settings
.compstartfarms
, NULL
,
529 rb
->set_int("Computer starting factories", "", UNIT_INT
,
530 &superdom_settings
.compstartinds
, NULL
,
534 rb
->set_int("Human starting farms", "", UNIT_INT
,
535 &superdom_settings
.humanstartfarms
, NULL
,
539 rb
->set_int("Human starting factories", "", UNIT_INT
,
540 &superdom_settings
.humanstartinds
, NULL
,
544 rb
->set_int("Starting cash", "", UNIT_INT
,
545 &superdom_settings
.startcash
, NULL
,
549 rb
->set_int("Starting food", "", UNIT_INT
,
550 &superdom_settings
.startfood
, NULL
,
554 rb
->set_int("Moves per turn", "", UNIT_INT
,
555 &superdom_settings
.movesperturn
, NULL
,
558 case MENU_ATTACHED_USB
:
569 static int superdom_help(void) {
570 static char* help_text
[] = {
571 "Super", "domination", "is", "a", "turn", "based", "strategy", "game,",
572 "where", "the", "aim", "is", "to", "overpower", "the", "computer",
573 "player", "by", "taking", "their", "territory.", "",
574 "Each", "year", "you", "are", "allocated", "an", "amount", "of", "cash",
575 "and", "food,", "depending", "on", "how", "many", "farms", "and",
576 "factories", "you", "control.", "",
577 "Use", "this", "cash", "and", "food", "to", "buy", "and", "feed", "your",
578 "army.", "Each", "tile", "has", "a", "strength,", "calculated", "by",
579 "the", "ownership", "of", "adjacent", "tiles,", "and", "the", "type",
580 "and", "number", "of", "troops", "on", "them.",
583 if (display_text(ARRAYLEN(help_text
), help_text
, NULL
, NULL
, true))
588 int start_menu(void) {
591 MENUITEM_STRINGLIST(menu
, "Super Domination Menu", NULL
,
592 "Play Super Domination", "Settings",
593 "Help", "Playback Control", "Quit");
596 switch(rb
->do_menu(&menu
, &selection
, NULL
, false)) {
598 return RET_VAL_OK
; /* start playing */
601 if(settings_menu()==RET_VAL_USB
)
605 if(superdom_help()==RET_VAL_USB
)
609 if(playback_control(NULL
))
613 return RET_VAL_QUIT_ERR
;
617 return RET_VAL_QUIT_ERR
;
620 int save_game(void) {
622 char savepath
[MAX_PATH
];
624 rb
->snprintf(savepath
, sizeof(savepath
), "/Savegame.ssg");
625 if(rb
->kbd_input(savepath
, MAX_PATH
)) {
626 DEBUGF("Keyboard input failed\n");
630 fd
= rb
->open(savepath
, O_WRONLY
|O_CREAT
, 0666);
631 DEBUGF("savepath: %s\n", savepath
);
633 DEBUGF("Couldn't create/open file\n");
637 rb
->write(fd
, "SSGv3", 5);
638 rb
->write(fd
, &gamestate
, sizeof(gamestate
));
639 rb
->write(fd
, &humanres
.cash
, sizeof(humanres
.cash
));
640 rb
->write(fd
, &humanres
.food
, sizeof(humanres
.food
));
641 rb
->write(fd
, &humanres
.bank
, sizeof(humanres
.bank
));
642 rb
->write(fd
, &humanres
.planes
, sizeof(humanres
.planes
));
643 rb
->write(fd
, &humanres
.tanks
, sizeof(humanres
.tanks
));
644 rb
->write(fd
, &humanres
.men
, sizeof(humanres
.men
));
645 rb
->write(fd
, &humanres
.nukes
, sizeof(humanres
.nukes
));
646 rb
->write(fd
, &humanres
.inds
, sizeof(humanres
.inds
));
647 rb
->write(fd
, &humanres
.farms
, sizeof(humanres
.farms
));
648 rb
->write(fd
, &humanres
.moves
, sizeof(humanres
.moves
));
649 rb
->write(fd
, &compres
.cash
, sizeof(compres
.cash
));
650 rb
->write(fd
, &compres
.food
, sizeof(compres
.food
));
651 rb
->write(fd
, &compres
.bank
, sizeof(compres
.bank
));
652 rb
->write(fd
, &compres
.planes
, sizeof(compres
.planes
));
653 rb
->write(fd
, &compres
.tanks
, sizeof(compres
.tanks
));
654 rb
->write(fd
, &compres
.men
, sizeof(compres
.men
));
655 rb
->write(fd
, &compres
.nukes
, sizeof(compres
.nukes
));
656 rb
->write(fd
, &compres
.inds
, sizeof(compres
.inds
));
657 rb
->write(fd
, &compres
.farms
, sizeof(compres
.farms
));
658 rb
->write(fd
, &compres
.moves
, sizeof(compres
.moves
));
659 rb
->write(fd
, board
, sizeof(board
));
660 rb
->write(fd
, &superdom_settings
.compstartfarms
, sizeof(int));
661 rb
->write(fd
, &superdom_settings
.compstartinds
, sizeof(int));
662 rb
->write(fd
, &superdom_settings
.humanstartfarms
, sizeof(int));
663 rb
->write(fd
, &superdom_settings
.humanstartinds
, sizeof(int));
664 rb
->write(fd
, &superdom_settings
.startcash
, sizeof(int));
665 rb
->write(fd
, &superdom_settings
.startfood
, sizeof(int));
666 rb
->write(fd
, &superdom_settings
.movesperturn
, sizeof(int));
671 int ingame_menu(void) {
672 MENUITEM_STRINGLIST(menu
, "Super Domination Menu", NULL
,
673 "Return to game", "Save Game",
674 "Playback Control", "Quit");
676 switch(rb
->do_menu(&menu
, NULL
, NULL
, false)) {
682 rb
->splash(HZ
, "Game saved");
684 rb
->splash(HZ
, "Error in save");
687 if(playback_control(NULL
))
691 return RET_VAL_QUIT_ERR
;
693 case MENU_ATTACHED_USB
:
703 int get_number(char* param
, int* value
, int max
) {
704 static const char *button_labels
[4][3] = {
712 int button
= 0, ret
= RET_VAL_OK
;
714 rb
->lcd_clear_display();
715 rb
->lcd_getstringsize("CLR", &width
, &height
);
716 if(width
> NUM_BOX_WIDTH
|| height
> NUM_BOX_HEIGHT
)
717 rb
->lcd_setfont(FONT_SYSFIXED
);
718 /* Draw a 3x4 grid */
719 for(i
=0;i
<=3;i
++) { /* Vertical lines */
720 rb
->lcd_vline(NUM_MARGIN_X
+(NUM_BOX_WIDTH
*i
), NUM_MARGIN_Y
,
721 NUM_MARGIN_Y
+(4*NUM_BOX_HEIGHT
));
723 for(i
=0;i
<=4;i
++) { /* Horizontal lines */
724 rb
->lcd_hline(NUM_MARGIN_X
, NUM_MARGIN_X
+(3*NUM_BOX_WIDTH
),
725 NUM_MARGIN_Y
+(NUM_BOX_HEIGHT
*i
));
729 rb
->lcd_getstringsize(button_labels
[i
][j
], &width
, &height
);
731 NUM_MARGIN_X
+(j
*NUM_BOX_WIDTH
)+NUM_BOX_WIDTH
/2-width
/2,
732 NUM_MARGIN_Y
+(i
*NUM_BOX_HEIGHT
)+NUM_BOX_HEIGHT
/2-height
/2,
733 button_labels
[i
][j
]);
736 rb
->snprintf(buf
,sizeof(buf
), "%d", *value
);
737 rb
->lcd_putsxy(NUM_MARGIN_X
+10, NUM_MARGIN_Y
+4*NUM_BOX_HEIGHT
+10, buf
);
738 rb
->lcd_getstringsize(param
, &width
, &height
);
739 if(width
< LCD_WIDTH
)
740 rb
->lcd_putsxy((LCD_WIDTH
-width
)/2, (NUM_MARGIN_Y
-height
)/2, param
);
742 rb
->lcd_puts_scroll(0, (NUM_MARGIN_Y
/height
-1)/2, param
);
743 rb
->lcd_set_drawmode(DRMODE_COMPLEMENT
);
744 rb
->lcd_fillrect(NUM_MARGIN_X
+(NUM_BOX_WIDTH
*x
),
745 NUM_MARGIN_Y
+(NUM_BOX_HEIGHT
*y
),
746 NUM_BOX_WIDTH
+1, NUM_BOX_HEIGHT
+1);
747 rb
->lcd_set_drawmode(DRMODE_SOLID
);
750 button
= rb
->button_get(true);
751 rb
->lcd_set_drawmode(DRMODE_COMPLEMENT
);
752 rb
->lcd_fillrect(NUM_MARGIN_X
+(NUM_BOX_WIDTH
*x
),
753 NUM_MARGIN_Y
+(NUM_BOX_HEIGHT
*y
),
754 NUM_BOX_WIDTH
+1, NUM_BOX_HEIGHT
+1);
755 rb
->lcd_set_drawmode(DRMODE_SOLID
);
760 *value
+= button_labels
[y
][x
][0] - '0';
769 if ((unsigned) *value
> (unsigned) max
)
771 rb
->lcd_set_drawmode(DRMODE_BG
|DRMODE_INVERSEVID
);
772 rb
->lcd_fillrect(0, NUM_MARGIN_Y
+4*NUM_BOX_HEIGHT
+10,
774 rb
->lcd_set_drawmode(DRMODE_SOLID
);
775 rb
->snprintf(buf
,sizeof(buf
), "%d", *value
);
776 rb
->lcd_putsxy(NUM_MARGIN_X
+10,
777 NUM_MARGIN_Y
+4*NUM_BOX_HEIGHT
+10, buf
);
779 case SUPERDOM_CANCEL
:
782 ret
= RET_VAL_QUIT_ERR
;
784 #if CONFIG_KEYPAD != IRIVER_H10_PAD
815 #if CONFIG_KEYPAD == IRIVER_H10_PAD
828 #if CONFIG_KEYPAD == IRIVER_H10_PAD
841 if (rb
->default_event_handler(button
) == SYS_USB_CONNECTED
)
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
);
855 rb
->lcd_setfont(FONT_UI
);
856 rb
->lcd_stop_scroll();
857 if (ret
== RET_VAL_QUIT_ERR
)
858 rb
->splash(HZ
, "Cancelled");
862 bool tile_has_item(int type
, int x
, int y
) {
865 return (board
[x
][y
].men
> 0);
868 return board
[x
][y
].tank
;
871 return board
[x
][y
].plane
;
874 return board
[x
][y
].farm
;
877 return board
[x
][y
].ind
;
880 return board
[x
][y
].nuke
;
886 int buy_resources(int colour
, int type
, int x
, int y
, int nummen
) {
887 const char *itemnames
[][6] = {
893 "the industrial plant",
900 "build an industrial plant",
907 "an industrial plant",
912 bool human
= (colour
== COLOUR_LIGHT
);
915 struct resources
*res
;
935 case 4: /* Factory */
942 if(res
->cash
< price
) {
944 rb
->splash(HZ
, "Not enough money!");
945 return RET_VAL_QUIT_ERR
;
948 rb
->splashf(HZ
, "Where do you want to place %s?", itemnames
[0][type
]);
949 if((temp
= select_square()) != RET_VAL_OK
)
954 if(board
[x
][y
].colour
!= colour
) {
956 rb
->splashf(HZ
, "Can't %s on enemy territory", itemnames
[1][type
]);
957 return RET_VAL_QUIT_ERR
;
959 if(type
!= 0 && tile_has_item(type
, x
, y
)) {
961 rb
->splashf(HZ
, "There is already %s there", itemnames
[2][type
]);
962 return RET_VAL_QUIT_ERR
;
966 board
[x
][y
].men
+= nummen
;
970 board
[x
][y
].tank
= true;
974 board
[x
][y
].plane
= true;
978 board
[x
][y
].farm
= true;
982 board
[x
][y
].ind
= true;
986 board
[x
][y
].nuke
= true;
998 int buy_resources_menu(void) {
999 int selection
= 0,nummen
;
1001 MENUITEM_STRINGLIST(menu
, "Buy Resources", NULL
,
1002 "Buy men ($1)", "Buy tank ($300)", "Buy plane ($600)",
1003 "Buy Farm ($1150)", "Buy Factory ($1300)",
1008 switch(rb
->do_menu(&menu
, &selection
, NULL
, false)) {
1011 if(get_number("How many men would you like?", &nummen
,
1012 humanres
.cash
) == RET_VAL_USB
)
1022 if(buy_resources(COLOUR_LIGHT
, selection
, 0, 0, nummen
)
1029 case MENU_ATTACHED_USB
:
1032 case GO_TO_PREVIOUS
:
1040 int move_unit(int colour
, int type
, int fromx
, int fromy
,
1041 int tox
, int toy
, int nummen
) {
1042 const char *itemnames
[][3] = {
1057 bool human
= (colour
== COLOUR_LIGHT
);
1061 rb
->splashf(HZ
, "Select where you want to move %s from",
1062 itemnames
[0][type
]);
1063 if((temp
= select_square()) != RET_VAL_OK
)
1068 if(board
[fromx
][fromy
].colour
!= colour
) {
1070 rb
->splash(HZ
, "That isn't your territory");
1071 return RET_VAL_QUIT_ERR
;
1073 if(!tile_has_item(type
, fromx
, fromy
)) {
1075 rb
->splashf(HZ
, "You don't have %s there", itemnames
[1][type
]);
1076 return RET_VAL_QUIT_ERR
;
1080 nummen
= board
[fromx
][fromy
].men
;
1081 if((temp
= get_number("How many men do you want to move?", &nummen
,
1082 nummen
)) != RET_VAL_OK
)
1085 if(nummen
> board
[fromx
][fromy
].men
) {
1087 rb
->splash(HZ
, "You don't have that many troops.");
1088 return RET_VAL_QUIT_ERR
;
1092 rb
->splashf(HZ
, "Select where you want to move %s to",
1093 itemnames
[2][type
]);
1094 if((temp
= select_square()) != RET_VAL_OK
)
1099 if((tox
== fromx
&& toy
== fromy
) ||
1100 board
[tox
][toy
].colour
!= colour
||
1101 (type
!= 2 && (abs(tox
- fromx
) > 1 || abs(toy
- fromy
) > 1))) {
1103 rb
->splash(HZ
, "Invalid move");
1104 return RET_VAL_QUIT_ERR
;
1106 if(type
!= 0 && tile_has_item(type
, tox
, toy
)) {
1108 rb
->splashf(HZ
, "There is already %s there", itemnames
[1][type
]);
1109 return RET_VAL_QUIT_ERR
;
1113 board
[fromx
][fromy
].men
-= nummen
;
1114 board
[tox
][toy
].men
+= nummen
;
1117 board
[fromx
][fromy
].tank
= false;
1118 board
[tox
][toy
].tank
= true;
1121 board
[fromx
][fromy
].plane
= false;
1122 board
[tox
][toy
].plane
= true;
1128 int move_unit_menu(void) {
1131 MENUITEM_STRINGLIST(menu
, "Move unit", NULL
,
1132 "Move men", "Move tank", "Move plane");
1133 switch(rb
->do_menu(&menu
, &selection
, NULL
, false)) {
1137 switch(move_unit(COLOUR_LIGHT
, selection
, 0, 0, 0, 0, 0)) {
1146 case MENU_ATTACHED_USB
:
1152 int launch_nuke(int colour
, int nukex
, int nukey
, int targetx
, int targety
) {
1153 bool human
= (colour
== COLOUR_LIGHT
);
1155 struct resources
*res
;
1157 if(board
[nukex
][nukey
].colour
!= colour
) {
1159 rb
->splash(HZ
, "That isn't your territory");
1160 return RET_VAL_QUIT_ERR
;
1162 if(! board
[nukex
][nukey
].nuke
) {
1164 rb
->splashf(HZ
, "You don't have %s there", "a nuke");
1165 return RET_VAL_QUIT_ERR
;
1168 rb
->splash(HZ
, "Select place to target with nuke");
1169 if((temp
= select_square()) != RET_VAL_OK
)
1179 board
[nukex
][nukey
].nuke
= false;
1181 if(board
[targetx
][targety
].colour
== COLOUR_LIGHT
) {
1186 res
->men
-= board
[targetx
][targety
].men
;
1187 res
->tanks
-= board
[targetx
][targety
].tank
;
1188 res
->planes
-= board
[targetx
][targety
].plane
;
1189 res
->nukes
-= board
[targetx
][targety
].nuke
;
1190 res
->farms
-= board
[targetx
][targety
].farm
;
1191 res
->inds
-= board
[targetx
][targety
].ind
;
1192 board
[targetx
][targety
].men
= 0;
1193 board
[targetx
][targety
].tank
= false;
1194 board
[targetx
][targety
].plane
= false;
1195 board
[targetx
][targety
].ind
= false;
1196 board
[targetx
][targety
].nuke
= false;
1197 board
[targetx
][targety
].farm
= false;
1198 /* TODO: Fallout carried by wind */
1203 int movement_menu(void) {
1204 int selection
= 0, temp
;
1206 MENUITEM_STRINGLIST(menu
, "Movement", NULL
,
1207 "Move unit", "Buy additional moves ($100)",
1208 "Launch nuclear missile", "Check map",
1209 "Finish moving", "Game menu");
1212 switch(rb
->do_menu(&menu
, &selection
, NULL
, false)) {
1214 if(humanres
.moves
) {
1215 if(move_unit_menu()==RET_VAL_USB
)
1218 rb
->splash(HZ
, "You have no more moves left."
1219 " You can buy more for $100 each.");
1223 if(humanres
.cash
> 100) {
1225 humanres
.cash
-= 100;
1226 rb
->snprintf(buf
, sizeof(buf
), "You now have %d moves",
1228 rb
->splash(HZ
, buf
);
1232 if(humanres
.nukes
==0) {
1233 rb
->splash(HZ
, "You do not have any nukes to launch");
1235 rb
->splash(HZ
, "Select place to launch nuke from");
1236 switch(select_square()) {
1238 if(launch_nuke(COLOUR_LIGHT
, cursor
.x
, cursor
.y
,
1239 0, 0) == RET_VAL_USB
)
1249 if(select_square() == RET_VAL_USB
)
1256 if((temp
= ingame_menu()) != RET_VAL_OK
)
1259 case MENU_ATTACHED_USB
:
1267 static const char* inventory_data(int selected_item
, void * data
,
1268 char * buffer
, size_t buffer_len
) {
1270 switch(selected_item
) {
1272 rb
->snprintf(buffer
,buffer_len
,"Men: %d", humanres
.men
);
1275 rb
->snprintf(buffer
,buffer_len
,"Tanks: %d", humanres
.tanks
);
1278 rb
->snprintf(buffer
,buffer_len
,"Planes: %d", humanres
.planes
);
1281 rb
->snprintf(buffer
,buffer_len
,"Factories: %d", humanres
.inds
);
1284 rb
->snprintf(buffer
,buffer_len
,"Farms: %d", humanres
.farms
);
1287 rb
->snprintf(buffer
,buffer_len
,"Nukes: %d", humanres
.nukes
);
1290 rb
->snprintf(buffer
,buffer_len
,"Cash: %d", humanres
.cash
);
1293 rb
->snprintf(buffer
,buffer_len
,"Food: %d", humanres
.food
);
1296 rb
->snprintf(buffer
,buffer_len
,"Bank: %d", humanres
.bank
);
1304 int show_inventory(void) {
1305 struct simplelist_info info
;
1306 rb
->simplelist_info_init(&info
, "Inventory", 9, NULL
);
1307 info
.hide_selection
= true;
1308 info
.get_name
= inventory_data
;
1309 if(rb
->simplelist_show_list(&info
)) {
1316 int production_menu(void) {
1317 int selection
= 0, temp
;
1319 MENUITEM_STRINGLIST(menu
, "Production", NULL
,
1320 "Buy resources", "Show inventory", "Check map",
1321 "Invest money", "Withdraw money",
1322 "Finish turn", "Game menu");
1325 switch(rb
->do_menu(&menu
, &selection
, NULL
, false)) {
1327 if(buy_resources_menu() == RET_VAL_USB
)
1331 if(show_inventory() == RET_VAL_USB
)
1335 if(select_square() == RET_VAL_USB
)
1339 temp
= humanres
.cash
;
1340 if(get_number("How much do you want to invest?", &temp
,
1341 humanres
.cash
) == RET_VAL_USB
)
1343 if(temp
> humanres
.cash
) {
1344 rb
->splash(HZ
, "You don't have that much cash to invest");
1346 humanres
.cash
-= temp
;
1347 humanres
.bank
+= temp
;
1351 temp
= humanres
.bank
;
1352 if(get_number("How much do you want to withdraw?", &temp
,
1353 humanres
.bank
) == RET_VAL_USB
)
1355 if(temp
> humanres
.bank
) {
1356 rb
->splash(HZ
, "You don't have that much cash to withdraw");
1358 humanres
.cash
+= temp
;
1359 humanres
.bank
-= temp
;
1366 if((temp
= ingame_menu()) != RET_VAL_OK
)
1369 case MENU_ATTACHED_USB
:
1377 void init_resources(void) {
1378 humanres
.cash
= superdom_settings
.startcash
;
1379 humanres
.food
= superdom_settings
.startfood
;
1381 humanres
.planes
= 0;
1388 compres
.cash
= superdom_settings
.startcash
;
1389 compres
.food
= superdom_settings
.startfood
;
1400 int select_square(void) {
1405 #if LCD_WIDTH >= 220
1406 rb
->lcd_setfont(FONT_SYSFIXED
);
1407 rb
->snprintf(buf
, sizeof(buf
), "Cash: %d", humanres
.cash
);
1408 rb
->lcd_putsxy(125, LCD_HEIGHT
-20, buf
);
1409 rb
->snprintf(buf
, sizeof(buf
), "Food: %d", humanres
.food
);
1410 rb
->lcd_putsxy(125, LCD_HEIGHT
-10, buf
);
1411 rb
->lcd_setfont(FONT_UI
);
1415 button
= rb
->button_get(true);
1417 case SUPERDOM_CANCEL
:
1418 rb
->splash(HZ
, "Cancelled");
1419 return RET_VAL_QUIT_ERR
;
1424 #if CONFIG_KEYPAD != IRIVER_H10_PAD
1426 case (SUPERDOM_LEFT
|BUTTON_REPEAT
):
1427 draw_cursor(); /* Deselect the current tile */
1442 case SUPERDOM_RIGHT
:
1443 case (SUPERDOM_RIGHT
|BUTTON_REPEAT
):
1444 draw_cursor(); /* Deselect the current tile */
1462 case (SUPERDOM_UP
|BUTTON_REPEAT
):
1463 draw_cursor(); /* Deselect the current tile */
1467 #if CONFIG_KEYPAD == IRIVER_H10_PAD
1479 case (SUPERDOM_DOWN
|BUTTON_REPEAT
):
1480 draw_cursor(); /* Deselect the current tile */
1484 #if CONFIG_KEYPAD == IRIVER_H10_PAD
1497 if (rb
->default_event_handler(button
) == SYS_USB_CONNECTED
)
1505 int killmen(int colour
) {
1506 bool human
= (colour
== COLOUR_LIGHT
);
1510 percent
= (humanres
.food
*1000)/humanres
.men
;
1513 percent
= (compres
.food
*1000)/compres
.men
;
1519 if(board
[i
][j
].colour
== colour
) {
1520 int nummen
= ((board
[i
][j
].men
* percent
)/1000);
1521 menkilled
+= board
[i
][j
].men
- nummen
;
1522 board
[i
][j
].men
= nummen
;
1528 humanres
.men
-= menkilled
;
1530 compres
.men
-= menkilled
;
1534 /* return -1 if error, 1 if attack is succeeded, 0 otherwise */
1535 int attack_territory(int colour
, int x
, int y
) {
1536 bool human
= (colour
== COLOUR_LIGHT
);
1539 if(board
[x
][y
].colour
== colour
) {
1541 rb
->splash(HZ
, "You can't attack your own territory");
1544 str_diff
= calc_strength(COLOUR_DARK
, x
, y
) -
1545 calc_strength(COLOUR_LIGHT
, x
, y
);
1547 str_diff
= -str_diff
;
1549 rb
->srand(*rb
->current_tick
);
1550 if(str_diff
> 0 || (str_diff
== 0 && rb
->rand()%2)) {
1551 struct resources
*offres
, *defres
;
1559 defres
->men
-= board
[x
][y
].men
;
1560 defres
->tanks
-= board
[x
][y
].tank
;
1561 defres
->planes
-= board
[x
][y
].plane
;
1562 defres
->nukes
-= board
[x
][y
].nuke
;
1563 defres
->farms
-= board
[x
][y
].farm
;
1564 defres
->inds
-= board
[x
][y
].ind
;
1565 offres
->farms
+= board
[x
][y
].farm
;
1566 offres
->inds
+= board
[x
][y
].ind
;
1567 board
[x
][y
].colour
= colour
;
1568 board
[x
][y
].men
= 0;
1569 board
[x
][y
].tank
= false;
1570 board
[x
][y
].plane
= false;
1571 board
[x
][y
].nuke
= false;
1580 rb
->splash(HZ
, "Your troops were unable to overcome"
1581 " the enemy troops");
1583 rb
->splash(HZ
*2, "The computer attempted to "
1584 "attack, but the invasion was"
1591 int war_menu(void) {
1592 int selection
= 0, temp
;
1594 MENUITEM_STRINGLIST(menu
, "War!", NULL
,
1595 "Select territory to attack",
1596 "Finish turn", "Game menu");
1598 while(humanres
.moves
) {
1599 switch(rb
->do_menu(&menu
, &selection
, NULL
, false)) {
1601 switch(select_square()) {
1603 if(attack_territory(COLOUR_LIGHT
, cursor
.x
, cursor
.y
)
1616 if((temp
= ingame_menu()) != RET_VAL_OK
)
1630 bool place_adjacent(bool tank
, int x
, int y
) {
1631 int type
= (tank
? 1: 2);
1632 if(!buy_resources(COLOUR_DARK
, type
, x
, y
, 0)) {
1635 if(!buy_resources(COLOUR_DARK
, type
, x
-1, y
, 0)) {
1638 if(!buy_resources(COLOUR_DARK
, type
, x
+1, y
, 0)) {
1641 if(!buy_resources(COLOUR_DARK
, type
, x
, y
-1, 0)) {
1644 if(!buy_resources(COLOUR_DARK
, type
, x
, y
+1, 0)) {
1650 bool has_adjacent(int x
, int y
) {
1651 if((board
[x
][y
].colour
== COLOUR_LIGHT
) &&
1652 ((board
[x
-1][y
].colour
== COLOUR_DARK
) ||
1653 (board
[x
+1][y
].colour
== COLOUR_DARK
) ||
1654 (board
[x
][y
+1].colour
== COLOUR_DARK
) ||
1655 (board
[x
][y
-1].colour
== COLOUR_DARK
)))
1661 void find_adjacent(int x
, int y
, int* adj_x
, int* adj_y
) {
1662 /* Finds adjacent squares, returning squares without tanks on them
1663 * in preference to those with them */
1664 if(board
[x
-1][y
].colour
== COLOUR_DARK
) {
1669 if(board
[x
+1][y
].colour
== COLOUR_DARK
) {
1674 if(board
[x
][y
-1].colour
== COLOUR_DARK
) {
1679 if(board
[x
][y
+1].colour
== COLOUR_DARK
) {
1686 void computer_allocate(void) {
1687 /* Firstly, decide whether to go offensive or defensive.
1688 * This is primarily decided by the human player posing a threat to either
1689 * the computer's farms or factories */
1691 bool offensive
= true;
1692 struct threat threats
[4];
1694 int total_str_diff
= 0;
1695 int numterritory
= 0;
1698 struct threat targets
[2];
1702 compres
.cash
+= compres
.bank
;
1706 if(board
[i
][j
].colour
== COLOUR_DARK
) {
1708 str_diff
= calc_strength(COLOUR_LIGHT
,i
,j
) -
1709 calc_strength(COLOUR_DARK
,i
,j
);
1710 if(str_diff
> 0 && (board
[i
][j
].ind
|| board
[i
][j
].farm
)) {
1711 if(numthreats
< 3) {
1713 threats
[numthreats
].x
= i
;
1714 threats
[numthreats
].y
= j
;
1715 threats
[numthreats
].str_diff
= str_diff
;
1724 /* The AI is going to go straight for the throat here and attack
1725 * the player's farms and factories. The amount of cash
1726 * the AI has to spend will determine how many targets there are */
1727 if(compres
.cash
> 1200) {
1728 /* 1200 is a figure I pulled out of nowhere. Adjust as needed */
1733 /* Work out which target(s) to attack. They must have adjacent squares
1734 * owned by the computer. If none are found just place troops in
1735 * random places around the map until we run out of money */
1739 if(has_adjacent(i
,j
) &&
1740 (board
[i
][j
].ind
|| board
[i
][j
].farm
)) {
1744 targets
[k
].str_diff
=
1745 calc_strength(COLOUR_LIGHT
, i
, j
) -
1746 calc_strength(COLOUR_DARK
, i
, j
);
1754 /* No targets found! Randomly pick squares and if they're owned
1755 * by the computer then stick a tank on it. */
1756 rb
->srand(*rb
->current_tick
);
1757 while(compres
.cash
>= 300 && compres
.tanks
< numterritory
) {
1758 i
= rb
->rand()%10 + 1;
1759 j
= rb
->rand()%10 + 1;
1760 if(board
[i
][j
].colour
== COLOUR_DARK
) {
1761 buy_resources(COLOUR_DARK
, 1, i
, j
, 0);
1767 str_diff
= targets
[i
].str_diff
;
1768 while(str_diff
+ 20 > 0 && compres
.cash
> 0) {
1769 /* While we still need them keep placing men */
1770 if(!place_adjacent(true, targets
[i
].x
, targets
[i
].y
)) {
1771 find_adjacent(targets
[i
].x
, targets
[i
].y
,
1773 men_needed
= (str_diff
+ 20)*1000/133;
1774 if(compres
.cash
< men_needed
) {
1775 men_needed
= compres
.cash
;
1777 buy_resources(COLOUR_DARK
, 0, adj
.x
, adj
.y
,
1781 str_diff
= calc_strength(COLOUR_LIGHT
,
1782 targets
[i
].x
, targets
[i
].y
) -
1783 calc_strength(COLOUR_DARK
,
1784 targets
[i
].x
, targets
[i
].y
);
1789 /* Work out what to place on each square to defend it.
1790 * Tanks are preferential because they do not require food,
1791 * but if the budget is tight then we fall back onto troops.
1792 * Conversely if cash is not an issue and there are already tanks in
1793 * place planes will be deployed. We would like a margin of at least
1794 * 20 points to be safe. */
1796 for(i
=0;i
<numthreats
;i
++) {
1797 total_str_diff
+= threats
[i
].str_diff
;
1799 if((total_str_diff
+20)*10 > compres
.cash
) {
1800 /* Not enough cash to accomodate all threats using tanks alone -
1801 * use men as a backup */
1802 for(i
=0;i
<numthreats
;i
++) {
1803 men_needed
= ((threats
[i
].str_diff
+ 20)*1000)/133;
1804 if(compres
.cash
< men_needed
) {
1805 men_needed
= compres
.cash
;
1807 buy_resources(COLOUR_DARK
, 0, threats
[i
].x
, threats
[i
].y
,
1812 /* Enough money to pay their way by planes? */
1813 bool tank
= ((total_str_diff
+20)*15 >= compres
.cash
);
1814 for(i
=0;i
<numthreats
;i
++) {
1815 str_diff
= threats
[i
].str_diff
;
1816 while(str_diff
+ 20 > 0) {
1817 if(!place_adjacent(tank
, threats
[i
].x
, threats
[i
].y
)) {
1818 /* No room for any more planes or tanks, revert to
1820 find_adjacent(threats
[i
].x
, threats
[i
].y
,
1822 men_needed
= (str_diff
+ 20)*1000/133;
1823 if(compres
.cash
< men_needed
) {
1824 men_needed
= compres
.cash
;
1826 buy_resources(COLOUR_DARK
, 0, threats
[i
].x
,
1827 threats
[i
].y
, men_needed
);
1830 str_diff
= calc_strength(COLOUR_LIGHT
,
1831 threats
[i
].x
, threats
[i
].y
) -
1832 calc_strength(COLOUR_DARK
,
1833 threats
[i
].x
, threats
[i
].y
);
1838 compres
.bank
+= compres
.cash
;
1842 int find_adj_target(int x
, int y
, struct cursor
* adj
) {
1843 /* Find a square next to a computer's farm or factory owned by the player
1844 * that is vulnerable. Return 1 on success, 0 otherwise */
1845 if(board
[x
+1][y
].colour
== COLOUR_LIGHT
&&
1846 calc_strength(COLOUR_LIGHT
,x
+1,y
)<=calc_strength(COLOUR_DARK
,x
+1,y
)) {
1851 if(board
[x
-1][y
].colour
== COLOUR_LIGHT
&&
1852 calc_strength(COLOUR_LIGHT
,x
-1,y
)<=calc_strength(COLOUR_DARK
,x
-1,y
)) {
1857 if(board
[x
][y
+1].colour
== COLOUR_LIGHT
&&
1858 calc_strength(COLOUR_LIGHT
,x
,y
+1)<=calc_strength(COLOUR_DARK
,x
,y
+1)) {
1863 if(board
[x
][y
-1].colour
== COLOUR_LIGHT
&&
1864 calc_strength(COLOUR_LIGHT
,x
,y
-1)<=calc_strength(COLOUR_DARK
,x
,y
-1)) {
1872 void computer_war(void) {
1873 /* Work out where to attack - prioritise the defence of buildings */
1875 bool found_target
= true;
1878 while(found_target
) {
1879 found_target
= false;
1882 if((board
[i
][j
].colour
== COLOUR_DARK
) &&
1883 (board
[i
][j
].farm
|| board
[i
][j
].ind
) &&
1884 find_adj_target(i
, j
, &adj
)) {
1885 found_target
= true;
1886 if(attack_territory(COLOUR_DARK
, adj
.x
, adj
.y
) >= 0) {
1896 /* Defence stage done, move on to OFFENCE */
1897 found_target
= true;
1898 while(found_target
) {
1899 found_target
= false;
1902 if(board
[i
][j
].colour
== COLOUR_LIGHT
&&
1903 (board
[i
][j
].ind
|| board
[i
][j
].farm
) &&
1904 (calc_strength(COLOUR_DARK
, i
, j
) >=
1905 calc_strength(COLOUR_LIGHT
, i
, j
))) {
1906 found_target
= true;
1907 if(attack_territory(COLOUR_DARK
, i
, j
) >= 0) {
1917 /* Spend leftover moves wherever attacking randomly */
1918 found_target
= true;
1919 while(found_target
) {
1920 found_target
= false;
1923 if(board
[i
][j
].colour
== COLOUR_LIGHT
&&
1924 (calc_strength(COLOUR_DARK
, i
, j
) >=
1925 calc_strength(COLOUR_LIGHT
, i
, j
))) {
1926 found_target
= true;
1927 if(attack_territory(COLOUR_DARK
, i
, j
) >= 0) {
1939 static int load_game(const char* file
) {
1942 fd
= rb
->open(file
, O_RDONLY
);
1944 DEBUGF("Couldn't open savegame\n");
1947 rb
->read(fd
, buf
, 5);
1948 if(rb
->strcmp(buf
, "SSGv3")) {
1949 rb
->splash(HZ
, "Invalid/incompatible savegame");
1952 rb
->read(fd
, &gamestate
, sizeof(gamestate
));
1953 rb
->read(fd
, &humanres
.cash
, sizeof(humanres
.cash
));
1954 rb
->read(fd
, &humanres
.food
, sizeof(humanres
.food
));
1955 rb
->read(fd
, &humanres
.bank
, sizeof(humanres
.bank
));
1956 rb
->read(fd
, &humanres
.planes
, sizeof(humanres
.planes
));
1957 rb
->read(fd
, &humanres
.tanks
, sizeof(humanres
.tanks
));
1958 rb
->read(fd
, &humanres
.men
, sizeof(humanres
.men
));
1959 rb
->read(fd
, &humanres
.nukes
, sizeof(humanres
.nukes
));
1960 rb
->read(fd
, &humanres
.inds
, sizeof(humanres
.inds
));
1961 rb
->read(fd
, &humanres
.farms
, sizeof(humanres
.farms
));
1962 rb
->read(fd
, &humanres
.moves
, sizeof(humanres
.moves
));
1963 rb
->read(fd
, &compres
.cash
, sizeof(humanres
.cash
));
1964 rb
->read(fd
, &compres
.food
, sizeof(humanres
.food
));
1965 rb
->read(fd
, &compres
.bank
, sizeof(humanres
.bank
));
1966 rb
->read(fd
, &compres
.planes
, sizeof(humanres
.planes
));
1967 rb
->read(fd
, &compres
.tanks
, sizeof(humanres
.tanks
));
1968 rb
->read(fd
, &compres
.men
, sizeof(humanres
.men
));
1969 rb
->read(fd
, &compres
.nukes
, sizeof(humanres
.nukes
));
1970 rb
->read(fd
, &compres
.inds
, sizeof(humanres
.inds
));
1971 rb
->read(fd
, &compres
.farms
, sizeof(humanres
.farms
));
1972 rb
->read(fd
, &compres
.moves
, sizeof(humanres
.moves
));
1973 rb
->read(fd
, board
, sizeof(board
));
1974 rb
->read(fd
, &superdom_settings
.compstartfarms
, sizeof(int));
1975 rb
->read(fd
, &superdom_settings
.compstartinds
, sizeof(int));
1976 rb
->read(fd
, &superdom_settings
.humanstartfarms
, sizeof(int));
1977 rb
->read(fd
, &superdom_settings
.humanstartinds
, sizeof(int));
1978 rb
->read(fd
, &superdom_settings
.startcash
, sizeof(int));
1979 rb
->read(fd
, &superdom_settings
.startfood
, sizeof(int));
1980 rb
->read(fd
, &superdom_settings
.movesperturn
, sizeof(int));
1985 void default_settings(void) {
1986 superdom_settings
.compstartfarms
= 1;
1987 superdom_settings
.compstartinds
= 1;
1988 superdom_settings
.humanstartfarms
= 2;
1989 superdom_settings
.humanstartinds
= 2;
1990 superdom_settings
.startcash
= 0;
1991 superdom_settings
.startfood
= 0;
1992 superdom_settings
.movesperturn
= 2;
1995 int average_strength(int colour
) {
1996 /* This function calculates the average strength of the given player,
1997 * used to determine when the computer wins or loses. */
2002 if(board
[i
][j
].colour
!= -1) {
2003 totalpower
+= calc_strength(colour
, i
, j
);
2007 return totalpower
/100;
2010 enum plugin_status
plugin_start(const void* parameter
)
2013 rb
->lcd_set_backdrop(NULL
);
2014 rb
->lcd_set_foreground(LCD_BLACK
);
2015 rb
->lcd_set_background(LCD_WHITE
);
2022 if(load_game(parameter
) != 0) {
2023 DEBUGF("Loading failed, generating new game\n");
2042 switch(start_menu()) {
2043 case RET_VAL_OK
: /* start playing */
2045 case RET_VAL_QUIT_ERR
: /* quit */
2049 return PLUGIN_USB_CONNECTED
;
2058 int avg_str_diff
= (average_strength(COLOUR_LIGHT
) -
2059 average_strength(COLOUR_DARK
));
2060 if(avg_str_diff
> 15) {
2061 rb
->splash(HZ
*4, "The computer has surrendered. You win.");
2064 if(-avg_str_diff
> 15) {
2065 rb
->splash(HZ
*4, "Your army have suffered terrible morale from"
2066 " the bleak prospects of winning. You lose.");
2072 gamestate
= GS_PROD
;
2073 switch(production_menu()) {
2075 return PLUGIN_USB_CONNECTED
;
2077 case RET_VAL_QUIT_ERR
:
2081 computer_allocate();
2084 humanres
.moves
= superdom_settings
.movesperturn
;
2086 gamestate
= GS_MOVE
;
2087 switch(movement_menu()) {
2089 return PLUGIN_USB_CONNECTED
;
2091 case RET_VAL_QUIT_ERR
:
2097 if(humanres
.food
> humanres
.men
) {
2098 rb
->snprintf(buf
, sizeof(buf
), "Your men ate %d units of food",
2100 humanres
.food
-= humanres
.men
;
2102 rb
->snprintf(buf
, sizeof(buf
), "There was not enough food"
2103 " to feed all your men, %d men have died of starvation",
2104 killmen(COLOUR_LIGHT
));
2106 rb
->splash(HZ
*2, buf
);
2109 if(compres
.food
> compres
.men
) {
2110 compres
.food
-= compres
.men
;
2112 rb
->snprintf(buf
, sizeof(buf
), "The computer does not have"
2113 " enough food to feed its men. %d have died of starvation",
2114 killmen(COLOUR_DARK
));
2115 rb
->splash(HZ
, buf
);
2119 humanres
.moves
= superdom_settings
.movesperturn
;
2122 switch(war_menu()) {
2124 return PLUGIN_USB_CONNECTED
;
2126 case RET_VAL_QUIT_ERR
:
2130 compres
.moves
= superdom_settings
.movesperturn
;