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 STRIDE BMPWIDTH_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 == COWOND2_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 == ONDAVX747_PAD) || (CONFIG_KEYPAD == MROBE500_PAD)
143 #define SUPERDOM_CANCEL BUTTON_POWER
145 #elif CONFIG_KEYPAD == SAMSUNG_YH_PAD
146 #define SUPERDOM_OK BUTTON_PLAY
147 #define SUPERDOM_UP BUTTON_UP
148 #define SUPERDOM_DOWN BUTTON_DOWN
149 #define SUPERDOM_LEFT BUTTON_LEFT
150 #define SUPERDOM_RIGHT BUTTON_RIGHT
151 #define SUPERDOM_CANCEL BUTTON_REW
155 #ifdef HAVE_TOUCHSCREEN
157 #define SUPERDOM_OK BUTTON_CENTER
160 #define SUPERDOM_UP BUTTON_TOPMIDDLE
162 #ifndef SUPERDOM_LEFT
163 #define SUPERDOM_LEFT BUTTON_MIDLEFT
165 #ifndef SUPERDOM_RIGHT
166 #define SUPERDOM_RIGHT BUTTON_MIDRIGHT
168 #ifndef SUPERDOM_DOWN
169 #define SUPERDOM_DOWN BUTTON_BOTTOMMIDDLE
171 #ifndef SUPERDOM_CANCEL
172 #define SUPERDOM_CANCEL BUTTON_TOPLEFT
179 RET_VAL_QUIT_ERR
, /* quit or error */
182 void gen_interest(void);
183 void init_resources(void);
184 int select_square(void);
185 void update_score(void);
186 void gen_resources(void);
187 void draw_cursor(void);
188 void draw_board(void);
191 signed int colour
; /* -1 = Unset */
223 struct resources humanres
;
224 struct resources compres
;
225 enum { GS_PROD
, GS_MOVE
, GS_WAR
} gamestate
;
232 struct tile board
[12][12];
234 void init_board(void) {
236 rb
->srand(*rb
->current_tick
);
237 for(i
=0;i
<12;i
++) { /* Hopefully about 50% each colour */
239 if((i
<1)||(j
<1)||(i
>10)||(j
>10))
240 board
[i
][j
].colour
= -1; /* Unset */
242 board
[i
][j
].colour
= rb
->rand()%2;
243 board
[i
][j
].tank
= false;
244 board
[i
][j
].plane
= false;
245 board
[i
][j
].nuke
= false;
246 board
[i
][j
].ind
= false;
247 board
[i
][j
].farm
= false;
252 while(compres
.farms
< superdom_settings
.compstartfarms
) {
253 i
= rb
->rand()%10 + 1;
254 j
= rb
->rand()%10 + 1;
255 if((board
[i
][j
].colour
== COLOUR_DARK
) && (board
[i
][j
].farm
== false)) {
256 board
[i
][j
].farm
= true;
260 while(compres
.inds
< superdom_settings
.compstartinds
) {
261 i
= rb
->rand()%10 + 1;
262 j
= rb
->rand()%10 + 1;
263 if((board
[i
][j
].colour
== COLOUR_DARK
) && (board
[i
][j
].ind
== false)) {
264 board
[i
][j
].ind
= true;
268 while(humanres
.farms
<superdom_settings
.humanstartfarms
) {
269 i
= rb
->rand()%10 + 1;
270 j
= rb
->rand()%10 + 1;
271 if((board
[i
][j
].colour
== COLOUR_LIGHT
)&&(board
[i
][j
].farm
== false)) {
272 board
[i
][j
].farm
= true;
276 while(humanres
.inds
<superdom_settings
.humanstartfarms
) {
277 i
= rb
->rand()%10 + 1;
278 j
= rb
->rand()%10 + 1;
279 if((board
[i
][j
].colour
== COLOUR_LIGHT
) && (board
[i
][j
].ind
== false)) {
280 board
[i
][j
].ind
= true;
286 void draw_board(void) {
288 rb
->lcd_clear_display();
291 if(board
[i
][j
].colour
== COLOUR_DARK
) {
292 rb
->lcd_set_foreground(LCD_DARKGRAY
);
294 rb
->lcd_set_foreground(LCD_LIGHTGRAY
);
296 rb
->lcd_fillrect(MARGIN
+(BOX_WIDTH
*(i
-1)),
297 MARGIN
+(BOX_HEIGHT
*(j
-1)), BOX_WIDTH
,
300 rb
->lcd_set_drawmode(DRMODE_BG
| DRMODE_INVERSEVID
);
302 if(board
[i
][j
].ind
) {
303 MY_BITMAP_PART(superdom_boarditems
,
304 board
[i
][j
].colour
?ICON_WIDTH
:0, 0, STRIDE
,
305 #if LCD_WIDTH > LCD_HEIGHT
306 MARGIN
+(BOX_WIDTH
*(i
-1))+1,
307 MARGIN
+(BOX_HEIGHT
*(j
-1))+ICON_HEIGHT
+1,
309 MARGIN
+(BOX_WIDTH
*(i
-1))+1+ICON_WIDTH
,
310 MARGIN
+(BOX_HEIGHT
*(j
-1))+1,
312 ICON_WIDTH
, ICON_HEIGHT
);
314 if(board
[i
][j
].farm
) {
315 MY_BITMAP_PART(superdom_boarditems
,
316 board
[i
][j
].colour
?ICON_WIDTH
:0, ICON_HEIGHT
,
317 STRIDE
, MARGIN
+(BOX_WIDTH
*(i
-1))+1,
318 MARGIN
+(BOX_HEIGHT
*(j
-1))+1,
319 ICON_WIDTH
, ICON_HEIGHT
);
321 if(board
[i
][j
].tank
) {
322 MY_BITMAP_PART(superdom_boarditems
,
323 board
[i
][j
].colour
?ICON_WIDTH
:0, ICON_HEIGHT
*2,
324 STRIDE
, MARGIN
+(BOX_WIDTH
*(i
-1))+ICON_WIDTH
+1,
325 MARGIN
+(BOX_HEIGHT
*(j
-1))+ICON_HEIGHT
+1,
326 ICON_WIDTH
, ICON_HEIGHT
);
328 if(board
[i
][j
].men
) {
329 MY_BITMAP_PART(superdom_boarditems
,
330 board
[i
][j
].colour
?ICON_WIDTH
:0, ICON_HEIGHT
*3,
331 #if LCD_WIDTH > LCD_HEIGHT
332 STRIDE
, MARGIN
+(BOX_WIDTH
*(i
-1))+ICON_WIDTH
+1,
333 MARGIN
+(BOX_HEIGHT
*(j
-1))+1,
335 STRIDE
, MARGIN
+(BOX_WIDTH
*(i
-1))+1,
336 MARGIN
+(BOX_HEIGHT
*(j
-1))+1+ICON_HEIGHT
,
338 ICON_WIDTH
, ICON_HEIGHT
);
340 if(board
[i
][j
].plane
) {
341 MY_BITMAP_PART(superdom_boarditems
,
342 board
[i
][j
].colour
?ICON_WIDTH
:0, ICON_HEIGHT
*4,
343 #if LCD_WIDTH > LCD_HEIGHT
344 STRIDE
,MARGIN
+(BOX_WIDTH
*(i
-1))+ICON_WIDTH
*2+1,
345 MARGIN
+(BOX_HEIGHT
*(j
-1))+ICON_HEIGHT
+1,
347 STRIDE
,MARGIN
+(BOX_WIDTH
*(i
-1))+ICON_WIDTH
+1,
348 MARGIN
+(BOX_HEIGHT
*(j
-1))+ICON_HEIGHT
*2+1,
350 ICON_WIDTH
, ICON_HEIGHT
);
352 if(board
[i
][j
].nuke
) {
353 MY_BITMAP_PART(superdom_boarditems
,
354 board
[i
][j
].colour
?ICON_WIDTH
:0, ICON_HEIGHT
*5,
355 #if LCD_WIDTH > LCD_HEIGHT
356 STRIDE
,MARGIN
+(BOX_WIDTH
*(i
-1))+ICON_WIDTH
*2+1,
357 MARGIN
+(BOX_HEIGHT
*(j
-1))+1,
359 STRIDE
,MARGIN
+(BOX_WIDTH
*(i
-1))+1,
360 MARGIN
+(BOX_HEIGHT
*(j
-1))+ICON_HEIGHT
*2+1,
362 ICON_WIDTH
, ICON_HEIGHT
);
365 rb
->lcd_set_drawmode(DRMODE_SOLID
);
369 rb
->lcd_set_foreground(LCD_BLACK
);
370 for(i
=0;i
<=10;i
++) { /* Draw Horizontal lines */
371 rb
->lcd_hline(MARGIN
, MARGIN
+(BOX_WIDTH
*10), MARGIN
+(BOX_HEIGHT
*i
));
373 for(i
=0;i
<=10;i
++) { /* Draw Vertical lines */
374 rb
->lcd_vline(MARGIN
+(BOX_WIDTH
*i
), MARGIN
, MARGIN
+(BOX_HEIGHT
*10));
379 int calc_strength(int colour
, int x
, int y
) {
381 for (a
= -1; a
< 2; a
++) {
382 for (b
= -1; b
< 2; b
++) {
383 if ((b
== 0 || a
== 0) &&
384 (board
[x
+ a
][y
+ b
].colour
== colour
)) {
386 if(board
[x
+ a
][y
+ b
].tank
|| board
[x
+ a
][y
+ b
].farm
)
388 if(board
[x
+ a
][y
+ b
].plane
|| board
[x
+ a
][y
+ b
].ind
)
390 if(board
[x
+ a
][y
+ b
].nuke
)
392 if(board
[x
+ a
][y
+ b
].men
)
393 score
+= (board
[x
+ a
][y
+ b
].men
*133/1000);
400 void gen_interest(void) {
401 /* Interest should be around 10% */
402 rb
->srand(*rb
->current_tick
);
403 int interest
= 7+rb
->rand()%6;
404 humanres
.bank
= humanres
.bank
+(interest
*humanres
.bank
/100);
405 compres
.bank
= compres
.bank
+(interest
*compres
.bank
/100);
408 void draw_cursor(void) {
409 rb
->lcd_set_drawmode(DRMODE_COMPLEMENT
);
410 rb
->lcd_fillrect(MARGIN
+((cursor
.x
-1)*BOX_WIDTH
),
411 MARGIN
+((cursor
.y
-1)*BOX_HEIGHT
), BOX_WIDTH
+1, BOX_HEIGHT
+1);
412 rb
->lcd_set_drawmode(DRMODE_SOLID
);
416 void gen_resources(void) {
423 rb
->srand(*rb
->current_tick
);
424 /* Generate Human's resources */
425 for(i
=0;i
<humanres
.inds
;i
++) {
426 inccash
+= (300+rb
->rand()%200);
428 for(i
=0;i
<humanres
.farms
;i
++) {
429 incfood
+= (200+rb
->rand()%200);
432 ratecash
= inccash
/humanres
.inds
;
434 ratefood
= incfood
/humanres
.farms
;
437 rb
->splash(HZ
*2, "Patriotism sweeps the land, all production"
438 " is up this year!");
440 rb
->splash(HZ
*2, "Factories working at maximum efficiency,"
441 " cash production up this year!");
443 } else if(ratecash
> 350) {
445 rb
->splash(HZ
*2, "Record crop harvest this year!");
446 } else if(ratefood
> 250) {
447 rb
->splash(HZ
*2, "Production continues as normal");
449 rb
->splash(HZ
*2, "Spoilage of crops leads to reduced farm"
450 " output this year");
454 rb
->splash(HZ
*2, "Record crop harvest this year!");
455 } else if(ratefood
> 250) {
456 rb
->splash(HZ
*2, "Factory unions introduced. Industrial"
457 " production is down this year.");
459 rb
->splash(HZ
*2, "Internet created. All production is down"
460 " due to time wasted.");
463 humanres
.cash
+= inccash
;
464 humanres
.food
+= incfood
;
466 /* Generate Computer's resources */
469 for(i
=0;i
<compres
.inds
;i
++) {
470 inccash
+= (300+rb
->rand()%200);
472 for(i
=0;i
<compres
.farms
;i
++) {
473 incfood
+= (200+rb
->rand()%200);
475 compres
.cash
+= inccash
;
476 compres
.food
+= incfood
;
479 void update_score(void) {
481 rb
->lcd_setfont(FONT_SYSFIXED
);
482 rb
->lcd_set_drawmode(DRMODE_BG
|DRMODE_INVERSEVID
);
483 rb
->lcd_fillrect(5,LCD_HEIGHT
-20,105,20);
484 rb
->lcd_set_drawmode(DRMODE_SOLID
);
485 strength
= calc_strength(COLOUR_LIGHT
, cursor
.x
, cursor
.y
);
486 rb
->snprintf(buf
, sizeof(buf
), "Your power: %d.%d",
487 strength
/10, strength
%10);
488 rb
->lcd_putsxy(5,LCD_HEIGHT
-20, buf
);
489 strength
= calc_strength(COLOUR_DARK
, cursor
.x
, cursor
.y
);
490 rb
->snprintf(buf
, sizeof(buf
), "Comp power: %d.%d",
491 strength
/10, strength
%10);
492 rb
->lcd_putsxy(5,LCD_HEIGHT
-10, buf
);
493 rb
->lcd_setfont(FONT_UI
);
496 int settings_menu(void) {
499 MENUITEM_STRINGLIST(menu
, "Super Domination Settings", NULL
,
500 "Computer starting farms", "Computer starting factories",
501 "Human starting farms", "Human starting factories",
502 "Starting cash", "Starting food", "Moves per turn");
505 switch(rb
->do_menu(&menu
, &selection
, NULL
, false)) {
507 rb
->set_int("Computer starting farms", "", UNIT_INT
,
508 &superdom_settings
.compstartfarms
, NULL
,
512 rb
->set_int("Computer starting factories", "", UNIT_INT
,
513 &superdom_settings
.compstartinds
, NULL
,
517 rb
->set_int("Human starting farms", "", UNIT_INT
,
518 &superdom_settings
.humanstartfarms
, NULL
,
522 rb
->set_int("Human starting factories", "", UNIT_INT
,
523 &superdom_settings
.humanstartinds
, NULL
,
527 rb
->set_int("Starting cash", "", UNIT_INT
,
528 &superdom_settings
.startcash
, NULL
,
532 rb
->set_int("Starting food", "", UNIT_INT
,
533 &superdom_settings
.startfood
, NULL
,
537 rb
->set_int("Moves per turn", "", UNIT_INT
,
538 &superdom_settings
.movesperturn
, NULL
,
541 case MENU_ATTACHED_USB
:
552 static int superdom_help(void) {
554 #define WORDS (sizeof help_text / sizeof (char*))
555 static char* help_text
[] = {
556 "Super", "domination", "is", "a", "turn", "based", "strategy", "game,",
557 "where", "the", "aim", "is", "to", "overpower", "the", "computer",
558 "player", "by", "taking", "their", "territory.", "",
559 "Each", "year", "you", "are", "allocated", "an", "amount", "of", "cash",
560 "and", "food,", "depending", "on", "how", "many", "farms", "and",
561 "factories", "you", "control.", "",
562 "Use", "this", "cash", "and", "food", "to", "buy", "and", "feed", "your",
563 "army.", "Each", "tile", "has", "a", "strength,", "calculated", "by",
564 "the", "ownership", "of", "adjacent", "tiles,", "and", "the", "type",
565 "and", "number", "of", "troops", "on", "them.",
568 if (display_text(WORDS
, help_text
, NULL
, NULL
))
571 button
= rb
->button_get(true);
572 if ( rb
->default_event_handler( button
) == SYS_USB_CONNECTED
)
574 } while( ( button
== BUTTON_NONE
)
575 || ( button
& (BUTTON_REL
|BUTTON_REPEAT
) ) );
580 int start_menu(void) {
583 MENUITEM_STRINGLIST(menu
, "Super Domination Menu", NULL
,
584 "Play Super Domination", "Settings",
585 "Help", "Playback Control", "Quit");
588 switch(rb
->do_menu(&menu
, &selection
, NULL
, false)) {
590 return RET_VAL_OK
; /* start playing */
593 if(settings_menu()==RET_VAL_USB
)
597 if(superdom_help()==RET_VAL_USB
)
601 if(playback_control(NULL
))
605 return RET_VAL_QUIT_ERR
;
609 return RET_VAL_QUIT_ERR
;
612 int save_game(void) {
614 char savepath
[MAX_PATH
];
616 rb
->snprintf(savepath
, sizeof(savepath
), "/Savegame.ssg");
617 if(rb
->kbd_input(savepath
, MAX_PATH
)) {
618 DEBUGF("Keyboard input failed\n");
622 fd
= rb
->open(savepath
, O_WRONLY
|O_CREAT
);
623 DEBUGF("savepath: %s\n", savepath
);
625 DEBUGF("Couldn't create/open file\n");
629 rb
->write(fd
, "SSGv3", 5);
630 rb
->write(fd
, &gamestate
, sizeof(gamestate
));
631 rb
->write(fd
, &humanres
.cash
, sizeof(humanres
.cash
));
632 rb
->write(fd
, &humanres
.food
, sizeof(humanres
.food
));
633 rb
->write(fd
, &humanres
.bank
, sizeof(humanres
.bank
));
634 rb
->write(fd
, &humanres
.planes
, sizeof(humanres
.planes
));
635 rb
->write(fd
, &humanres
.tanks
, sizeof(humanres
.tanks
));
636 rb
->write(fd
, &humanres
.men
, sizeof(humanres
.men
));
637 rb
->write(fd
, &humanres
.nukes
, sizeof(humanres
.nukes
));
638 rb
->write(fd
, &humanres
.inds
, sizeof(humanres
.inds
));
639 rb
->write(fd
, &humanres
.farms
, sizeof(humanres
.farms
));
640 rb
->write(fd
, &humanres
.moves
, sizeof(humanres
.moves
));
641 rb
->write(fd
, &compres
.cash
, sizeof(compres
.cash
));
642 rb
->write(fd
, &compres
.food
, sizeof(compres
.food
));
643 rb
->write(fd
, &compres
.bank
, sizeof(compres
.bank
));
644 rb
->write(fd
, &compres
.planes
, sizeof(compres
.planes
));
645 rb
->write(fd
, &compres
.tanks
, sizeof(compres
.tanks
));
646 rb
->write(fd
, &compres
.men
, sizeof(compres
.men
));
647 rb
->write(fd
, &compres
.nukes
, sizeof(compres
.nukes
));
648 rb
->write(fd
, &compres
.inds
, sizeof(compres
.inds
));
649 rb
->write(fd
, &compres
.farms
, sizeof(compres
.farms
));
650 rb
->write(fd
, &compres
.moves
, sizeof(compres
.moves
));
651 rb
->write(fd
, board
, sizeof(board
));
652 rb
->write(fd
, &superdom_settings
.compstartfarms
, sizeof(int));
653 rb
->write(fd
, &superdom_settings
.compstartinds
, sizeof(int));
654 rb
->write(fd
, &superdom_settings
.humanstartfarms
, sizeof(int));
655 rb
->write(fd
, &superdom_settings
.humanstartfarms
, sizeof(int));
656 rb
->write(fd
, &superdom_settings
.startcash
, sizeof(int));
657 rb
->write(fd
, &superdom_settings
.startfood
, sizeof(int));
658 rb
->write(fd
, &superdom_settings
.movesperturn
, sizeof(int));
663 int ingame_menu(void) {
664 MENUITEM_STRINGLIST(menu
, "Super Domination Menu", NULL
,
665 "Return to game", "Save Game",
666 "Playback Control", "Quit");
668 switch(rb
->do_menu(&menu
, NULL
, NULL
, false)) {
674 rb
->splash(HZ
, "Game saved");
676 rb
->splash(HZ
, "Error in save");
679 if(playback_control(NULL
))
683 return RET_VAL_QUIT_ERR
;
685 case MENU_ATTACHED_USB
:
695 int get_number(char* param
, int* value
) {
696 static const char *button_labels
[4][3] = {
705 rb
->lcd_clear_display();
706 rb
->lcd_getstringsize("CLR", &width
, &height
);
707 if(width
> NUM_BOX_WIDTH
|| height
> NUM_BOX_HEIGHT
)
708 rb
->lcd_setfont(FONT_SYSFIXED
);
709 /* Draw a 3x4 grid */
710 for(i
=0;i
<=3;i
++) { /* Vertical lines */
711 rb
->lcd_vline(NUM_MARGIN_X
+(NUM_BOX_WIDTH
*i
), NUM_MARGIN_Y
,
712 NUM_MARGIN_Y
+(4*NUM_BOX_HEIGHT
));
714 for(i
=0;i
<=4;i
++) { /* Horizontal lines */
715 rb
->lcd_hline(NUM_MARGIN_X
, NUM_MARGIN_X
+(3*NUM_BOX_WIDTH
),
716 NUM_MARGIN_Y
+(NUM_BOX_HEIGHT
*i
));
720 rb
->lcd_getstringsize(button_labels
[i
][j
], &width
, &height
);
722 NUM_MARGIN_X
+(j
*NUM_BOX_WIDTH
)+NUM_BOX_WIDTH
/2-width
/2,
723 NUM_MARGIN_Y
+(i
*NUM_BOX_HEIGHT
)+NUM_BOX_HEIGHT
/2-height
/2,
724 button_labels
[i
][j
]);
727 rb
->snprintf(buf
,sizeof(buf
), "%d", *value
);
728 rb
->lcd_putsxy(NUM_MARGIN_X
+10, NUM_MARGIN_Y
+4*NUM_BOX_HEIGHT
+10, buf
);
729 rb
->lcd_getstringsize(param
, &width
, &height
);
730 if(width
< LCD_WIDTH
)
731 rb
->lcd_putsxy((LCD_WIDTH
-width
)/2, (NUM_MARGIN_Y
-height
)/2, param
);
733 rb
->lcd_puts_scroll(0, (NUM_MARGIN_Y
/height
-1)/2, param
);
734 rb
->lcd_set_drawmode(DRMODE_COMPLEMENT
);
735 rb
->lcd_fillrect(NUM_MARGIN_X
+(NUM_BOX_WIDTH
*x
),
736 NUM_MARGIN_Y
+(NUM_BOX_HEIGHT
*y
),
737 NUM_BOX_WIDTH
+1, NUM_BOX_HEIGHT
+1);
738 rb
->lcd_set_drawmode(DRMODE_SOLID
);
741 button
= rb
->button_get(true);
742 rb
->lcd_set_drawmode(DRMODE_COMPLEMENT
);
743 rb
->lcd_fillrect(NUM_MARGIN_X
+(NUM_BOX_WIDTH
*x
),
744 NUM_MARGIN_Y
+(NUM_BOX_HEIGHT
*y
),
745 NUM_BOX_WIDTH
+1, NUM_BOX_HEIGHT
+1);
746 rb
->lcd_set_drawmode(DRMODE_SOLID
);
751 *value
+= button_labels
[y
][x
][0] - '0';
757 rb
->lcd_setfont(FONT_UI
);
760 rb
->lcd_set_drawmode(DRMODE_BG
|DRMODE_INVERSEVID
);
761 rb
->lcd_fillrect(0, NUM_MARGIN_Y
+4*NUM_BOX_HEIGHT
+10,
763 rb
->lcd_set_drawmode(DRMODE_SOLID
);
764 rb
->snprintf(buf
,sizeof(buf
), "%d", *value
);
765 rb
->lcd_putsxy(NUM_MARGIN_X
+10,
766 NUM_MARGIN_Y
+4*NUM_BOX_HEIGHT
+10, buf
);
768 case SUPERDOM_CANCEL
:
770 rb
->lcd_setfont(FONT_UI
);
771 rb
->splash(HZ
, "Cancelled");
772 return RET_VAL_QUIT_ERR
;
774 #if CONFIG_KEYPAD != IRIVER_H10_PAD
805 #if CONFIG_KEYPAD == IRIVER_H10_PAD
818 #if CONFIG_KEYPAD == IRIVER_H10_PAD
831 if (rb
->default_event_handler(button
) == SYS_USB_CONNECTED
)
833 rb
->lcd_setfont(FONT_UI
);
838 rb
->lcd_set_drawmode(DRMODE_COMPLEMENT
);
839 rb
->lcd_fillrect(NUM_MARGIN_X
+(NUM_BOX_WIDTH
*x
),
840 NUM_MARGIN_Y
+(NUM_BOX_HEIGHT
*y
),
841 NUM_BOX_WIDTH
+1, NUM_BOX_HEIGHT
+1);
842 rb
->lcd_set_drawmode(DRMODE_SOLID
);
845 rb
->lcd_setfont(FONT_UI
);
849 bool tile_has_item(int type
, int x
, int y
) {
852 return (board
[x
][y
].men
> 0);
855 return board
[x
][y
].tank
;
858 return board
[x
][y
].plane
;
861 return board
[x
][y
].farm
;
864 return board
[x
][y
].ind
;
867 return board
[x
][y
].nuke
;
873 int buy_resources(int colour
, int type
, int x
, int y
, int nummen
) {
874 const char *itemnames
[][6] = {
880 "the industrial plant",
887 "build an industrial plant",
894 "an industrial plant",
899 bool human
= (colour
== COLOUR_LIGHT
);
902 struct resources
*res
;
922 case 4: /* Factory */
929 if(res
->cash
< price
) {
931 rb
->splash(HZ
, "Not enough money!");
932 return RET_VAL_QUIT_ERR
;
935 rb
->splashf(HZ
, "Where do you want to place %s?", itemnames
[0][type
]);
936 if((temp
= select_square()) != RET_VAL_OK
)
941 if(board
[x
][y
].colour
!= colour
) {
943 rb
->splashf(HZ
, "Can't %s on enemy territory", itemnames
[1][type
]);
944 return RET_VAL_QUIT_ERR
;
946 if(type
!= 0 && tile_has_item(type
, x
, y
)) {
948 rb
->splashf(HZ
, "There is already %s there", itemnames
[2][type
]);
949 return RET_VAL_QUIT_ERR
;
953 board
[x
][y
].men
+= nummen
;
957 board
[x
][y
].tank
= true;
961 board
[x
][y
].plane
= true;
965 board
[x
][y
].farm
= true;
969 board
[x
][y
].ind
= true;
973 board
[x
][y
].nuke
= true;
985 int buy_resources_menu(void) {
986 int selection
= 0,nummen
;
988 MENUITEM_STRINGLIST(menu
, "Buy Resources", NULL
,
989 "Buy men ($1)", "Buy tank ($300)", "Buy plane ($600)",
990 "Buy Farm ($1150)", "Buy Factory ($1300)",
995 switch(rb
->do_menu(&menu
, &selection
, NULL
, false)) {
998 if(get_number("How many men would you like?", &nummen
)
1009 if(buy_resources(COLOUR_LIGHT
, selection
, 0, 0, nummen
)
1016 case MENU_ATTACHED_USB
:
1019 case GO_TO_PREVIOUS
:
1027 int move_unit(int colour
, int type
, int fromx
, int fromy
,
1028 int tox
, int toy
, int nummen
) {
1029 const char *itemnames
[][3] = {
1044 bool human
= (colour
== COLOUR_LIGHT
);
1048 rb
->splashf(HZ
, "Select where you want to move %s from",
1049 itemnames
[0][type
]);
1050 if((temp
= select_square()) != RET_VAL_OK
)
1055 if(board
[fromx
][fromy
].colour
!= colour
) {
1057 rb
->splash(HZ
, "That isn't your territory");
1058 return RET_VAL_QUIT_ERR
;
1060 if(!tile_has_item(type
, fromx
, fromy
)) {
1062 rb
->splashf(HZ
, "You don't have %s there", itemnames
[1][type
]);
1063 return RET_VAL_QUIT_ERR
;
1067 nummen
= board
[fromx
][fromy
].men
;
1068 if((temp
= get_number("How many men do you want to move?", &nummen
))
1072 if(nummen
> board
[fromx
][fromy
].men
) {
1074 rb
->splash(HZ
, "You don't have that many troops.");
1075 return RET_VAL_QUIT_ERR
;
1079 rb
->splashf(HZ
, "Select where you want to move %s to",
1080 itemnames
[2][type
]);
1081 if((temp
= select_square()) != RET_VAL_OK
)
1086 if((tox
== fromx
&& toy
== fromy
) ||
1087 board
[tox
][toy
].colour
!= colour
||
1088 (type
!= 2 && (abs(tox
- fromx
) > 1 || abs(toy
- fromy
) > 1))) {
1090 rb
->splash(HZ
, "Invalid move");
1091 return RET_VAL_QUIT_ERR
;
1093 if(type
!= 0 && tile_has_item(type
, tox
, toy
)) {
1095 rb
->splashf(HZ
, "There is already %s there", itemnames
[1][type
]);
1096 return RET_VAL_QUIT_ERR
;
1100 board
[fromx
][fromy
].men
-= nummen
;
1101 board
[tox
][toy
].men
+= nummen
;
1104 board
[fromx
][fromy
].tank
= false;
1105 board
[tox
][toy
].tank
= true;
1108 board
[fromx
][fromy
].plane
= false;
1109 board
[tox
][toy
].plane
= true;
1115 int move_unit_menu(void) {
1118 MENUITEM_STRINGLIST(menu
, "Move unit", NULL
,
1119 "Move men", "Move tank", "Move plane");
1120 switch(rb
->do_menu(&menu
, &selection
, NULL
, false)) {
1124 switch(move_unit(COLOUR_LIGHT
, selection
, 0, 0, 0, 0, 0)) {
1133 case MENU_ATTACHED_USB
:
1139 int launch_nuke(int colour
, int nukex
, int nukey
, int targetx
, int targety
) {
1140 bool human
= (colour
== COLOUR_LIGHT
);
1142 struct resources
*res
;
1144 if(board
[nukex
][nukey
].colour
!= colour
) {
1146 rb
->splash(HZ
, "That isn't your territory");
1147 return RET_VAL_QUIT_ERR
;
1149 if(! board
[nukex
][nukey
].nuke
) {
1151 rb
->splashf(HZ
, "You don't have %s there", "a nuke");
1152 return RET_VAL_QUIT_ERR
;
1155 rb
->splash(HZ
, "Select place to target with nuke");
1156 if((temp
= select_square()) != RET_VAL_OK
)
1166 board
[nukex
][nukey
].nuke
= false;
1168 if(board
[targetx
][targety
].colour
== COLOUR_LIGHT
) {
1173 res
->men
-= board
[targetx
][targety
].men
;
1174 res
->tanks
-= board
[targetx
][targety
].tank
;
1175 res
->planes
-= board
[targetx
][targety
].plane
;
1176 res
->nukes
-= board
[targetx
][targety
].nuke
;
1177 res
->farms
-= board
[targetx
][targety
].farm
;
1178 res
->inds
-= board
[targetx
][targety
].ind
;
1179 board
[targetx
][targety
].men
= 0;
1180 board
[targetx
][targety
].tank
= false;
1181 board
[targetx
][targety
].plane
= false;
1182 board
[targetx
][targety
].ind
= false;
1183 board
[targetx
][targety
].nuke
= false;
1184 board
[targetx
][targety
].farm
= false;
1185 /* TODO: Fallout carried by wind */
1190 int movement_menu(void) {
1191 int selection
= 0, temp
;
1193 MENUITEM_STRINGLIST(menu
, "Movement", NULL
,
1194 "Move unit", "Buy additional moves ($100)",
1195 "Launch nuclear missile", "Check map",
1196 "Finish moving", "Game menu");
1199 switch(rb
->do_menu(&menu
, &selection
, NULL
, false)) {
1201 if(humanres
.moves
) {
1202 if(move_unit_menu()==RET_VAL_USB
)
1205 rb
->splash(HZ
, "You have no more moves left."
1206 " You can buy more for $100 each.");
1210 if(humanres
.cash
> 100) {
1212 humanres
.cash
-= 100;
1213 rb
->snprintf(buf
, sizeof(buf
), "You now have %d moves",
1215 rb
->splash(HZ
, buf
);
1219 if(humanres
.nukes
==0) {
1220 rb
->splash(HZ
, "You do not have any nukes to launch");
1222 rb
->splash(HZ
, "Select place to launch nuke from");
1223 switch(select_square()) {
1225 if(launch_nuke(COLOUR_LIGHT
, cursor
.x
, cursor
.y
,
1226 0, 0) == RET_VAL_USB
)
1236 if(select_square() == RET_VAL_USB
)
1243 if((temp
= ingame_menu()) != RET_VAL_OK
)
1246 case MENU_ATTACHED_USB
:
1254 static const char* inventory_data(int selected_item
, void * data
,
1255 char * buffer
, size_t buffer_len
) {
1257 switch(selected_item
) {
1259 rb
->snprintf(buffer
,buffer_len
,"Men: %d", humanres
.men
);
1262 rb
->snprintf(buffer
,buffer_len
,"Tanks: %d", humanres
.tanks
);
1265 rb
->snprintf(buffer
,buffer_len
,"Planes: %d", humanres
.planes
);
1268 rb
->snprintf(buffer
,buffer_len
,"Factories: %d", humanres
.inds
);
1271 rb
->snprintf(buffer
,buffer_len
,"Farms: %d", humanres
.farms
);
1274 rb
->snprintf(buffer
,buffer_len
,"Nukes: %d", humanres
.nukes
);
1277 rb
->snprintf(buffer
,buffer_len
,"Cash: %d", humanres
.cash
);
1280 rb
->snprintf(buffer
,buffer_len
,"Food: %d", humanres
.food
);
1283 rb
->snprintf(buffer
,buffer_len
,"Bank: %d", humanres
.bank
);
1291 int show_inventory(void) {
1292 struct simplelist_info info
;
1293 rb
->simplelist_info_init(&info
, "Inventory", 9, NULL
);
1294 info
.hide_selection
= true;
1295 info
.get_name
= inventory_data
;
1296 if(rb
->simplelist_show_list(&info
)) {
1303 int production_menu(void) {
1304 int selection
= 0, temp
;
1306 MENUITEM_STRINGLIST(menu
, "Production", NULL
,
1307 "Buy resources", "Show inventory", "Check map",
1308 "Invest money", "Withdraw money",
1309 "Finish turn", "Game menu");
1312 switch(rb
->do_menu(&menu
, &selection
, NULL
, false)) {
1314 if(buy_resources_menu() == RET_VAL_USB
)
1318 if(show_inventory() == RET_VAL_USB
)
1322 if(select_square() == RET_VAL_USB
)
1326 temp
= humanres
.cash
;
1327 if(get_number("How much do you want to invest?", &temp
)
1330 if(temp
> humanres
.cash
) {
1331 rb
->splash(HZ
, "You don't have that much cash to invest");
1333 humanres
.cash
-= temp
;
1334 humanres
.bank
+= temp
;
1338 temp
= humanres
.bank
;
1339 if(get_number("How much do you want to withdraw?", &temp
)
1342 if(temp
> humanres
.bank
) {
1343 rb
->splash(HZ
, "You don't have that much cash to withdraw");
1345 humanres
.cash
+= temp
;
1346 humanres
.bank
-= temp
;
1353 if((temp
= ingame_menu()) != RET_VAL_OK
)
1356 case MENU_ATTACHED_USB
:
1364 void init_resources(void) {
1365 humanres
.cash
= superdom_settings
.startcash
;
1366 humanres
.food
= superdom_settings
.startfood
;
1368 humanres
.planes
= 0;
1375 compres
.cash
= superdom_settings
.startcash
;
1376 compres
.food
= superdom_settings
.startfood
;
1387 int select_square(void) {
1392 #if LCD_WIDTH >= 220
1393 rb
->lcd_setfont(FONT_SYSFIXED
);
1394 rb
->snprintf(buf
, sizeof(buf
), "Cash: %d", humanres
.cash
);
1395 rb
->lcd_putsxy(125, LCD_HEIGHT
-20, buf
);
1396 rb
->snprintf(buf
, sizeof(buf
), "Food: %d", humanres
.food
);
1397 rb
->lcd_putsxy(125, LCD_HEIGHT
-10, buf
);
1398 rb
->lcd_setfont(FONT_UI
);
1402 button
= rb
->button_get(true);
1404 case SUPERDOM_CANCEL
:
1405 rb
->splash(HZ
, "Cancelled");
1406 return RET_VAL_QUIT_ERR
;
1411 #if CONFIG_KEYPAD != IRIVER_H10_PAD
1413 case (SUPERDOM_LEFT
|BUTTON_REPEAT
):
1414 draw_cursor(); /* Deselect the current tile */
1429 case SUPERDOM_RIGHT
:
1430 case (SUPERDOM_RIGHT
|BUTTON_REPEAT
):
1431 draw_cursor(); /* Deselect the current tile */
1449 case (SUPERDOM_UP
|BUTTON_REPEAT
):
1450 draw_cursor(); /* Deselect the current tile */
1454 #if CONFIG_KEYPAD == IRIVER_H10_PAD
1466 case (SUPERDOM_DOWN
|BUTTON_REPEAT
):
1467 draw_cursor(); /* Deselect the current tile */
1471 #if CONFIG_KEYPAD == IRIVER_H10_PAD
1484 if (rb
->default_event_handler(button
) == SYS_USB_CONNECTED
)
1492 int killmen(int colour
) {
1493 bool human
= (colour
== COLOUR_LIGHT
);
1497 percent
= (humanres
.food
*1000)/humanres
.men
;
1500 percent
= (compres
.food
*1000)/compres
.men
;
1506 if(board
[i
][j
].colour
== colour
) {
1507 int nummen
= ((board
[i
][j
].men
* percent
)/1000);
1508 menkilled
+= board
[i
][j
].men
- nummen
;
1509 board
[i
][j
].men
= nummen
;
1515 humanres
.men
-= menkilled
;
1517 compres
.men
-= menkilled
;
1521 /* return -1 if error, 1 if attack is succeeded, 0 otherwise */
1522 int attack_territory(int colour
, int x
, int y
) {
1523 bool human
= (colour
== COLOUR_LIGHT
);
1526 if(board
[x
][y
].colour
== colour
) {
1528 rb
->splash(HZ
, "You can't attack your own territory");
1531 str_diff
= calc_strength(COLOUR_DARK
, x
, y
) -
1532 calc_strength(COLOUR_LIGHT
, x
, y
);
1534 str_diff
= -str_diff
;
1536 rb
->srand(*rb
->current_tick
);
1537 if(str_diff
> 0 || (str_diff
== 0 && rb
->rand()%2)) {
1538 struct resources
*offres
, *defres
;
1546 defres
->men
-= board
[x
][y
].men
;
1547 defres
->tanks
-= board
[x
][y
].tank
;
1548 defres
->planes
-= board
[x
][y
].plane
;
1549 defres
->nukes
-= board
[x
][y
].nuke
;
1550 defres
->farms
-= board
[x
][y
].farm
;
1551 defres
->inds
-= board
[x
][y
].ind
;
1552 offres
->farms
+= board
[x
][y
].farm
;
1553 offres
->inds
+= board
[x
][y
].ind
;
1554 board
[x
][y
].colour
= colour
;
1555 board
[x
][y
].men
= 0;
1556 board
[x
][y
].tank
= false;
1557 board
[x
][y
].plane
= false;
1558 board
[x
][y
].nuke
= false;
1567 rb
->splash(HZ
, "Your troops were unable to overcome"
1568 " the enemy troops");
1570 rb
->splash(HZ
*2, "The computer attempted to "
1571 "attack, but the invasion was"
1578 int war_menu(void) {
1579 int selection
= 0, temp
;
1581 MENUITEM_STRINGLIST(menu
, "War!", NULL
,
1582 "Select territory to attack",
1583 "Finish turn", "Game menu");
1585 while(humanres
.moves
) {
1586 switch(rb
->do_menu(&menu
, &selection
, NULL
, false)) {
1588 switch(select_square()) {
1590 if(attack_territory(COLOUR_LIGHT
, cursor
.x
, cursor
.y
)
1603 if((temp
= ingame_menu()) != RET_VAL_OK
)
1617 bool place_adjacent(bool tank
, int x
, int y
) {
1618 int type
= (tank
? 1: 2);
1619 if(!buy_resources(COLOUR_DARK
, type
, x
, y
, 0)) {
1622 if(!buy_resources(COLOUR_DARK
, type
, x
-1, y
, 0)) {
1625 if(!buy_resources(COLOUR_DARK
, type
, x
+1, y
, 0)) {
1628 if(!buy_resources(COLOUR_DARK
, type
, x
, y
-1, 0)) {
1631 if(!buy_resources(COLOUR_DARK
, type
, x
, y
+1, 0)) {
1637 bool has_adjacent(int x
, int y
) {
1638 if((board
[x
][y
].colour
== COLOUR_LIGHT
) &&
1639 ((board
[x
-1][y
].colour
== COLOUR_DARK
) ||
1640 (board
[x
+1][y
].colour
== COLOUR_DARK
) ||
1641 (board
[x
][y
+1].colour
== COLOUR_DARK
) ||
1642 (board
[x
][y
-1].colour
== COLOUR_DARK
)))
1648 void find_adjacent(int x
, int y
, int* adj_x
, int* adj_y
) {
1649 /* Finds adjacent squares, returning squares without tanks on them
1650 * in preference to those with them */
1651 if(board
[x
-1][y
].colour
== COLOUR_DARK
) {
1656 if(board
[x
+1][y
].colour
== COLOUR_DARK
) {
1661 if(board
[x
][y
-1].colour
== COLOUR_DARK
) {
1666 if(board
[x
][y
+1].colour
== COLOUR_DARK
) {
1673 void computer_allocate(void) {
1674 /* Firstly, decide whether to go offensive or defensive.
1675 * This is primarily decided by the human player posing a threat to either
1676 * the computer's farms or factories */
1678 bool offensive
= true;
1679 struct threat threats
[4];
1681 int total_str_diff
= 0;
1682 int numterritory
= 0;
1685 struct threat targets
[2];
1689 compres
.cash
+= compres
.bank
;
1693 if(board
[i
][j
].colour
== COLOUR_DARK
) {
1695 str_diff
= calc_strength(COLOUR_LIGHT
,i
,j
) -
1696 calc_strength(COLOUR_DARK
,i
,j
);
1697 if(str_diff
> 0 && (board
[i
][j
].ind
|| board
[i
][j
].farm
)) {
1698 if(numthreats
< 3) {
1700 threats
[numthreats
].x
= i
;
1701 threats
[numthreats
].y
= j
;
1702 threats
[numthreats
].str_diff
= str_diff
;
1711 /* The AI is going to go straight for the throat here and attack
1712 * the player's farms and factories. The amount of cash
1713 * the AI has to spend will determine how many targets there are */
1714 if(compres
.cash
> 1200) {
1715 /* 1200 is a figure I pulled out of nowhere. Adjust as needed */
1720 /* Work out which target(s) to attack. They must have adjacent squares
1721 * owned by the computer. If none are found just place troops in
1722 * random places around the map until we run out of money */
1726 if(has_adjacent(i
,j
) &&
1727 (board
[i
][j
].ind
|| board
[i
][j
].farm
)) {
1731 targets
[k
].str_diff
=
1732 calc_strength(COLOUR_LIGHT
, i
, j
) -
1733 calc_strength(COLOUR_DARK
, i
, j
);
1741 /* No targets found! Randomly pick squares and if they're owned
1742 * by the computer then stick a tank on it. */
1743 rb
->srand(*rb
->current_tick
);
1744 while(compres
.cash
>= 300 && compres
.tanks
< numterritory
) {
1745 i
= rb
->rand()%10 + 1;
1746 j
= rb
->rand()%10 + 1;
1747 if(board
[i
][j
].colour
== COLOUR_DARK
) {
1748 buy_resources(COLOUR_DARK
, 1, i
, j
, 0);
1754 str_diff
= targets
[i
].str_diff
;
1755 while(str_diff
+ 20 > 0 && compres
.cash
> 0) {
1756 /* While we still need them keep placing men */
1757 if(!place_adjacent(true, targets
[i
].x
, targets
[i
].y
)) {
1758 find_adjacent(targets
[i
].x
, targets
[i
].y
,
1760 men_needed
= (str_diff
+ 20)*1000/133;
1761 if(compres
.cash
< men_needed
) {
1762 men_needed
= compres
.cash
;
1764 buy_resources(COLOUR_DARK
, 0, adj
.x
, adj
.y
,
1768 str_diff
= calc_strength(COLOUR_LIGHT
,
1769 targets
[i
].x
, targets
[i
].y
) -
1770 calc_strength(COLOUR_DARK
,
1771 targets
[i
].x
, targets
[i
].y
);
1776 /* Work out what to place on each square to defend it.
1777 * Tanks are preferential because they do not require food,
1778 * but if the budget is tight then we fall back onto troops.
1779 * Conversely if cash is not an issue and there are already tanks in
1780 * place planes will be deployed. We would like a margin of at least
1781 * 20 points to be safe. */
1783 for(i
=0;i
<numthreats
;i
++) {
1784 total_str_diff
+= threats
[i
].str_diff
;
1786 if((total_str_diff
+20)*10 > compres
.cash
) {
1787 /* Not enough cash to accomodate all threats using tanks alone -
1788 * use men as a backup */
1789 for(i
=0;i
<numthreats
;i
++) {
1790 men_needed
= ((threats
[i
].str_diff
+ 20)*1000)/133;
1791 if(compres
.cash
< men_needed
) {
1792 men_needed
= compres
.cash
;
1794 buy_resources(COLOUR_DARK
, 0, threats
[i
].x
, threats
[i
].y
,
1799 /* Enough money to pay their way by planes? */
1800 bool tank
= ((total_str_diff
+20)*15 >= compres
.cash
);
1801 for(i
=0;i
<numthreats
;i
++) {
1802 str_diff
= threats
[i
].str_diff
;
1803 while(str_diff
+ 20 > 0) {
1804 if(!place_adjacent(tank
, threats
[i
].x
, threats
[i
].y
)) {
1805 /* No room for any more planes or tanks, revert to
1807 find_adjacent(threats
[i
].x
, threats
[i
].y
,
1809 men_needed
= (str_diff
+ 20)*1000/133;
1810 if(compres
.cash
< men_needed
) {
1811 men_needed
= compres
.cash
;
1813 buy_resources(COLOUR_DARK
, 0, threats
[i
].x
,
1814 threats
[i
].y
, men_needed
);
1817 str_diff
= calc_strength(COLOUR_LIGHT
,
1818 threats
[i
].x
, threats
[i
].y
) -
1819 calc_strength(COLOUR_DARK
,
1820 threats
[i
].x
, threats
[i
].y
);
1825 compres
.bank
+= compres
.cash
;
1829 int find_adj_target(int x
, int y
, struct cursor
* adj
) {
1830 /* Find a square next to a computer's farm or factory owned by the player
1831 * that is vulnerable. Return 1 on success, 0 otherwise */
1832 if(board
[x
+1][y
].colour
== COLOUR_LIGHT
&&
1833 calc_strength(COLOUR_LIGHT
,x
+1,y
)<=calc_strength(COLOUR_DARK
,x
+1,y
)) {
1838 if(board
[x
-1][y
].colour
== COLOUR_LIGHT
&&
1839 calc_strength(COLOUR_LIGHT
,x
-1,y
)<=calc_strength(COLOUR_DARK
,x
-1,y
)) {
1844 if(board
[x
][y
+1].colour
== COLOUR_LIGHT
&&
1845 calc_strength(COLOUR_LIGHT
,x
,y
+1)<=calc_strength(COLOUR_DARK
,x
,y
+1)) {
1850 if(board
[x
][y
-1].colour
== COLOUR_LIGHT
&&
1851 calc_strength(COLOUR_LIGHT
,x
,y
-1)<=calc_strength(COLOUR_DARK
,x
,y
-1)) {
1859 void computer_war(void) {
1860 /* Work out where to attack - prioritise the defence of buildings */
1862 bool found_target
= true;
1865 while(found_target
) {
1866 found_target
= false;
1869 if((board
[i
][j
].colour
== COLOUR_DARK
) &&
1870 (board
[i
][j
].farm
|| board
[i
][j
].ind
) &&
1871 find_adj_target(i
, j
, &adj
)) {
1872 found_target
= true;
1873 if(attack_territory(COLOUR_DARK
, adj
.x
, adj
.y
) >= 0) {
1883 /* Defence stage done, move on to OFFENCE */
1884 found_target
= true;
1885 while(found_target
) {
1886 found_target
= false;
1889 if(board
[i
][j
].colour
== COLOUR_LIGHT
&&
1890 (board
[i
][j
].ind
|| board
[i
][j
].farm
) &&
1891 (calc_strength(COLOUR_DARK
, i
, j
) >=
1892 calc_strength(COLOUR_LIGHT
, i
, j
))) {
1893 found_target
= true;
1894 if(attack_territory(COLOUR_DARK
, i
, j
) >= 0) {
1904 /* Spend leftover moves wherever attacking randomly */
1905 found_target
= true;
1906 while(found_target
) {
1907 found_target
= false;
1910 if(board
[i
][j
].colour
== COLOUR_LIGHT
&&
1911 (calc_strength(COLOUR_DARK
, i
, j
) >=
1912 calc_strength(COLOUR_LIGHT
, i
, j
))) {
1913 found_target
= true;
1914 if(attack_territory(COLOUR_DARK
, i
, j
) >= 0) {
1926 static int load_game(const char* file
) {
1929 fd
= rb
->open(file
, O_RDONLY
);
1931 DEBUGF("Couldn't open savegame\n");
1934 rb
->read(fd
, buf
, 5);
1935 if(rb
->strcmp(buf
, "SSGv3")) {
1936 rb
->splash(HZ
, "Invalid/incompatible savegame");
1939 rb
->read(fd
, &gamestate
, sizeof(gamestate
));
1940 rb
->read(fd
, &humanres
.cash
, sizeof(humanres
.cash
));
1941 rb
->read(fd
, &humanres
.food
, sizeof(humanres
.food
));
1942 rb
->read(fd
, &humanres
.bank
, sizeof(humanres
.bank
));
1943 rb
->read(fd
, &humanres
.planes
, sizeof(humanres
.planes
));
1944 rb
->read(fd
, &humanres
.tanks
, sizeof(humanres
.tanks
));
1945 rb
->read(fd
, &humanres
.men
, sizeof(humanres
.men
));
1946 rb
->read(fd
, &humanres
.nukes
, sizeof(humanres
.nukes
));
1947 rb
->read(fd
, &humanres
.inds
, sizeof(humanres
.inds
));
1948 rb
->read(fd
, &humanres
.farms
, sizeof(humanres
.farms
));
1949 rb
->read(fd
, &humanres
.moves
, sizeof(humanres
.moves
));
1950 rb
->read(fd
, &compres
.cash
, sizeof(humanres
.cash
));
1951 rb
->read(fd
, &compres
.food
, sizeof(humanres
.food
));
1952 rb
->read(fd
, &compres
.bank
, sizeof(humanres
.bank
));
1953 rb
->read(fd
, &compres
.planes
, sizeof(humanres
.planes
));
1954 rb
->read(fd
, &compres
.tanks
, sizeof(humanres
.tanks
));
1955 rb
->read(fd
, &compres
.men
, sizeof(humanres
.men
));
1956 rb
->read(fd
, &compres
.nukes
, sizeof(humanres
.nukes
));
1957 rb
->read(fd
, &compres
.inds
, sizeof(humanres
.inds
));
1958 rb
->read(fd
, &compres
.farms
, sizeof(humanres
.farms
));
1959 rb
->read(fd
, &compres
.moves
, sizeof(humanres
.moves
));
1960 rb
->read(fd
, board
, sizeof(board
));
1961 rb
->read(fd
, &superdom_settings
.compstartfarms
, sizeof(int));
1962 rb
->read(fd
, &superdom_settings
.compstartinds
, sizeof(int));
1963 rb
->read(fd
, &superdom_settings
.humanstartfarms
, sizeof(int));
1964 rb
->read(fd
, &superdom_settings
.humanstartfarms
, sizeof(int));
1965 rb
->read(fd
, &superdom_settings
.startcash
, sizeof(int));
1966 rb
->read(fd
, &superdom_settings
.startfood
, sizeof(int));
1967 rb
->read(fd
, &superdom_settings
.movesperturn
, sizeof(int));
1972 void default_settings(void) {
1973 superdom_settings
.compstartfarms
= 1;
1974 superdom_settings
.compstartinds
= 1;
1975 superdom_settings
.humanstartfarms
= 2;
1976 superdom_settings
.humanstartinds
= 2;
1977 superdom_settings
.startcash
= 0;
1978 superdom_settings
.startfood
= 0;
1979 superdom_settings
.movesperturn
= 2;
1982 int average_strength(int colour
) {
1983 /* This function calculates the average strength of the given player,
1984 * used to determine when the computer wins or loses. */
1989 if(board
[i
][j
].colour
!= -1) {
1990 totalpower
+= calc_strength(colour
, i
, j
);
1994 return totalpower
/100;
1997 enum plugin_status
plugin_start(const void* parameter
)
2000 rb
->lcd_set_backdrop(NULL
);
2001 rb
->lcd_set_foreground(LCD_BLACK
);
2002 rb
->lcd_set_background(LCD_WHITE
);
2009 if(load_game(parameter
) != 0) {
2010 DEBUGF("Loading failed, generating new game\n");
2029 switch(start_menu()) {
2030 case RET_VAL_OK
: /* start playing */
2032 case RET_VAL_QUIT_ERR
: /* quit */
2036 return PLUGIN_USB_CONNECTED
;
2045 int avg_str_diff
= (average_strength(COLOUR_LIGHT
) -
2046 average_strength(COLOUR_DARK
));
2047 if(avg_str_diff
> 15) {
2048 rb
->splash(HZ
*4, "The computer has surrendered. You win.");
2051 if(-avg_str_diff
> 15) {
2052 rb
->splash(HZ
*4, "Your army have suffered terrible morale from"
2053 " the bleak prospects of winning. You lose.");
2059 gamestate
= GS_PROD
;
2060 switch(production_menu()) {
2062 return PLUGIN_USB_CONNECTED
;
2064 case RET_VAL_QUIT_ERR
:
2068 computer_allocate();
2071 humanres
.moves
= superdom_settings
.movesperturn
;
2073 gamestate
= GS_MOVE
;
2074 switch(movement_menu()) {
2076 return PLUGIN_USB_CONNECTED
;
2078 case RET_VAL_QUIT_ERR
:
2084 if(humanres
.food
> humanres
.men
) {
2085 rb
->snprintf(buf
, sizeof(buf
), "Your men ate %d units of food",
2087 humanres
.food
-= humanres
.men
;
2089 rb
->snprintf(buf
, sizeof(buf
), "There was not enough food"
2090 " to feed all your men, %d men have died of starvation",
2091 killmen(COLOUR_LIGHT
));
2093 rb
->splash(HZ
*2, buf
);
2096 if(compres
.food
> compres
.men
) {
2097 compres
.food
-= compres
.men
;
2099 rb
->snprintf(buf
, sizeof(buf
), "The computer does not have"
2100 " enough food to feed its men. %d have died of starvation",
2101 killmen(COLOUR_DARK
));
2102 rb
->splash(HZ
, buf
);
2106 humanres
.moves
= superdom_settings
.movesperturn
;
2109 switch(war_menu()) {
2111 return PLUGIN_USB_CONNECTED
;
2113 case RET_VAL_QUIT_ERR
:
2117 compres
.moves
= superdom_settings
.movesperturn
;