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
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
187 RET_VAL_QUIT_ERR
, /* quit or error */
190 void gen_interest(void);
191 void init_resources(void);
192 int select_square(void);
193 void update_score(void);
194 void gen_resources(void);
195 void draw_cursor(void);
196 void draw_board(void);
199 signed int colour
; /* -1 = Unset */
231 struct resources humanres
;
232 struct resources compres
;
233 enum { GS_PROD
, GS_MOVE
, GS_WAR
} gamestate
;
240 struct tile board
[12][12];
242 void init_board(void) {
244 rb
->srand(*rb
->current_tick
);
245 for(i
=0;i
<12;i
++) { /* Hopefully about 50% each colour */
247 if((i
<1)||(j
<1)||(i
>10)||(j
>10))
248 board
[i
][j
].colour
= -1; /* Unset */
250 board
[i
][j
].colour
= rb
->rand()%2;
251 board
[i
][j
].tank
= false;
252 board
[i
][j
].plane
= false;
253 board
[i
][j
].nuke
= false;
254 board
[i
][j
].ind
= false;
255 board
[i
][j
].farm
= false;
260 while(compres
.farms
< superdom_settings
.compstartfarms
) {
261 i
= rb
->rand()%10 + 1;
262 j
= rb
->rand()%10 + 1;
263 if((board
[i
][j
].colour
== COLOUR_DARK
) && (board
[i
][j
].farm
== false)) {
264 board
[i
][j
].farm
= true;
268 while(compres
.inds
< superdom_settings
.compstartinds
) {
269 i
= rb
->rand()%10 + 1;
270 j
= rb
->rand()%10 + 1;
271 if((board
[i
][j
].colour
== COLOUR_DARK
) && (board
[i
][j
].ind
== false)) {
272 board
[i
][j
].ind
= true;
276 while(humanres
.farms
< 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
].farm
== false)) {
280 board
[i
][j
].farm
= true;
284 while(humanres
.inds
< superdom_settings
.humanstartinds
) {
285 i
= rb
->rand()%10 + 1;
286 j
= rb
->rand()%10 + 1;
287 if((board
[i
][j
].colour
== COLOUR_LIGHT
) && (board
[i
][j
].ind
== false)) {
288 board
[i
][j
].ind
= true;
294 void draw_board(void) {
296 rb
->lcd_clear_display();
299 if(board
[i
][j
].colour
== COLOUR_DARK
) {
300 rb
->lcd_set_foreground(LCD_DARKGRAY
);
302 rb
->lcd_set_foreground(LCD_LIGHTGRAY
);
304 rb
->lcd_fillrect(MARGIN
+(BOX_WIDTH
*(i
-1)),
305 MARGIN
+(BOX_HEIGHT
*(j
-1)), BOX_WIDTH
,
308 rb
->lcd_set_drawmode(DRMODE_BG
| DRMODE_INVERSEVID
);
310 if(board
[i
][j
].ind
) {
311 MY_BITMAP_PART(superdom_boarditems
,
312 board
[i
][j
].colour
?ICON_WIDTH
:0, 0, ICON_STRIDE
,
313 #if LCD_WIDTH > LCD_HEIGHT
314 MARGIN
+(BOX_WIDTH
*(i
-1))+1,
315 MARGIN
+(BOX_HEIGHT
*(j
-1))+ICON_HEIGHT
+1,
317 MARGIN
+(BOX_WIDTH
*(i
-1))+1+ICON_WIDTH
,
318 MARGIN
+(BOX_HEIGHT
*(j
-1))+1,
320 ICON_WIDTH
, ICON_HEIGHT
);
322 if(board
[i
][j
].farm
) {
323 MY_BITMAP_PART(superdom_boarditems
,
324 board
[i
][j
].colour
?ICON_WIDTH
:0, ICON_HEIGHT
,
325 ICON_STRIDE
, MARGIN
+(BOX_WIDTH
*(i
-1))+1,
326 MARGIN
+(BOX_HEIGHT
*(j
-1))+1,
327 ICON_WIDTH
, ICON_HEIGHT
);
329 if(board
[i
][j
].tank
) {
330 MY_BITMAP_PART(superdom_boarditems
,
331 board
[i
][j
].colour
?ICON_WIDTH
:0, ICON_HEIGHT
*2,
332 ICON_STRIDE
, MARGIN
+(BOX_WIDTH
*(i
-1))+ICON_WIDTH
+1,
333 MARGIN
+(BOX_HEIGHT
*(j
-1))+ICON_HEIGHT
+1,
334 ICON_WIDTH
, ICON_HEIGHT
);
336 if(board
[i
][j
].men
) {
337 MY_BITMAP_PART(superdom_boarditems
,
338 board
[i
][j
].colour
?ICON_WIDTH
:0, ICON_HEIGHT
*3,
339 #if LCD_WIDTH > LCD_HEIGHT
340 ICON_STRIDE
, MARGIN
+(BOX_WIDTH
*(i
-1))+ICON_WIDTH
+1,
341 MARGIN
+(BOX_HEIGHT
*(j
-1))+1,
343 ICON_STRIDE
, MARGIN
+(BOX_WIDTH
*(i
-1))+1,
344 MARGIN
+(BOX_HEIGHT
*(j
-1))+1+ICON_HEIGHT
,
346 ICON_WIDTH
, ICON_HEIGHT
);
348 if(board
[i
][j
].plane
) {
349 MY_BITMAP_PART(superdom_boarditems
,
350 board
[i
][j
].colour
?ICON_WIDTH
:0, ICON_HEIGHT
*4,
351 #if LCD_WIDTH > LCD_HEIGHT
352 ICON_STRIDE
,MARGIN
+(BOX_WIDTH
*(i
-1))+ICON_WIDTH
*2+1,
353 MARGIN
+(BOX_HEIGHT
*(j
-1))+ICON_HEIGHT
+1,
355 ICON_STRIDE
,MARGIN
+(BOX_WIDTH
*(i
-1))+ICON_WIDTH
+1,
356 MARGIN
+(BOX_HEIGHT
*(j
-1))+ICON_HEIGHT
*2+1,
358 ICON_WIDTH
, ICON_HEIGHT
);
360 if(board
[i
][j
].nuke
) {
361 MY_BITMAP_PART(superdom_boarditems
,
362 board
[i
][j
].colour
?ICON_WIDTH
:0, ICON_HEIGHT
*5,
363 #if LCD_WIDTH > LCD_HEIGHT
364 ICON_STRIDE
,MARGIN
+(BOX_WIDTH
*(i
-1))+ICON_WIDTH
*2+1,
365 MARGIN
+(BOX_HEIGHT
*(j
-1))+1,
367 ICON_STRIDE
,MARGIN
+(BOX_WIDTH
*(i
-1))+1,
368 MARGIN
+(BOX_HEIGHT
*(j
-1))+ICON_HEIGHT
*2+1,
370 ICON_WIDTH
, ICON_HEIGHT
);
373 rb
->lcd_set_drawmode(DRMODE_SOLID
);
377 rb
->lcd_set_foreground(LCD_BLACK
);
378 for(i
=0;i
<=10;i
++) { /* Draw Horizontal lines */
379 rb
->lcd_hline(MARGIN
, MARGIN
+(BOX_WIDTH
*10), MARGIN
+(BOX_HEIGHT
*i
));
381 for(i
=0;i
<=10;i
++) { /* Draw Vertical lines */
382 rb
->lcd_vline(MARGIN
+(BOX_WIDTH
*i
), MARGIN
, MARGIN
+(BOX_HEIGHT
*10));
387 int calc_strength(int colour
, int x
, int y
) {
389 for (a
= -1; a
< 2; a
++) {
390 for (b
= -1; b
< 2; b
++) {
391 if ((b
== 0 || a
== 0) &&
392 (board
[x
+ a
][y
+ b
].colour
== colour
)) {
394 if(board
[x
+ a
][y
+ b
].tank
|| board
[x
+ a
][y
+ b
].farm
)
396 if(board
[x
+ a
][y
+ b
].plane
|| board
[x
+ a
][y
+ b
].ind
)
398 if(board
[x
+ a
][y
+ b
].nuke
)
400 if(board
[x
+ a
][y
+ b
].men
)
401 score
+= (board
[x
+ a
][y
+ b
].men
*133/1000);
408 void gen_interest(void) {
409 /* Interest should be around 10% */
410 rb
->srand(*rb
->current_tick
);
411 int interest
= 7+rb
->rand()%6;
412 humanres
.bank
= humanres
.bank
+(interest
*humanres
.bank
/100);
413 compres
.bank
= compres
.bank
+(interest
*compres
.bank
/100);
416 void draw_cursor(void) {
417 rb
->lcd_set_drawmode(DRMODE_COMPLEMENT
);
418 rb
->lcd_fillrect(MARGIN
+((cursor
.x
-1)*BOX_WIDTH
),
419 MARGIN
+((cursor
.y
-1)*BOX_HEIGHT
), BOX_WIDTH
+1, BOX_HEIGHT
+1);
420 rb
->lcd_set_drawmode(DRMODE_SOLID
);
424 void gen_resources(void) {
431 rb
->srand(*rb
->current_tick
);
432 /* Generate Human's resources */
433 for(i
=0;i
<humanres
.inds
;i
++) {
434 inccash
+= (300+rb
->rand()%200);
436 for(i
=0;i
<humanres
.farms
;i
++) {
437 incfood
+= (200+rb
->rand()%200);
440 ratecash
= inccash
/humanres
.inds
;
442 ratefood
= incfood
/humanres
.farms
;
445 rb
->splash(HZ
*2, "Patriotism sweeps the land, all production"
446 " is up this year!");
448 rb
->splash(HZ
*2, "Factories working at maximum efficiency,"
449 " cash production up this year!");
451 } else if(ratecash
> 350) {
453 rb
->splash(HZ
*2, "Record crop harvest this year!");
454 } else if(ratefood
> 250) {
455 rb
->splash(HZ
*2, "Production continues as normal");
457 rb
->splash(HZ
*2, "Spoilage of crops leads to reduced farm"
458 " output this year");
462 rb
->splash(HZ
*2, "Record crop harvest this year!");
463 } else if(ratefood
> 250) {
464 rb
->splash(HZ
*2, "Factory unions introduced. Industrial"
465 " production is down this year.");
467 rb
->splash(HZ
*2, "Internet created. All production is down"
468 " due to time wasted.");
471 humanres
.cash
+= inccash
;
472 humanres
.food
+= incfood
;
474 /* Generate Computer's resources */
477 for(i
=0;i
<compres
.inds
;i
++) {
478 inccash
+= (300+rb
->rand()%200);
480 for(i
=0;i
<compres
.farms
;i
++) {
481 incfood
+= (200+rb
->rand()%200);
483 compres
.cash
+= inccash
;
484 compres
.food
+= incfood
;
487 void update_score(void) {
489 rb
->lcd_setfont(FONT_SYSFIXED
);
490 rb
->lcd_set_drawmode(DRMODE_BG
|DRMODE_INVERSEVID
);
491 rb
->lcd_fillrect(5,LCD_HEIGHT
-20,105,20);
492 rb
->lcd_set_drawmode(DRMODE_SOLID
);
493 strength
= calc_strength(COLOUR_LIGHT
, cursor
.x
, cursor
.y
);
494 rb
->snprintf(buf
, sizeof(buf
), "Your power: %d.%d",
495 strength
/10, strength
%10);
496 rb
->lcd_putsxy(5,LCD_HEIGHT
-20, buf
);
497 strength
= calc_strength(COLOUR_DARK
, cursor
.x
, cursor
.y
);
498 rb
->snprintf(buf
, sizeof(buf
), "Comp power: %d.%d",
499 strength
/10, strength
%10);
500 rb
->lcd_putsxy(5,LCD_HEIGHT
-10, buf
);
501 rb
->lcd_setfont(FONT_UI
);
504 int settings_menu(void) {
507 MENUITEM_STRINGLIST(menu
, "Super Domination Settings", NULL
,
508 "Computer starting farms", "Computer starting factories",
509 "Human starting farms", "Human starting factories",
510 "Starting cash", "Starting food", "Moves per turn");
513 switch(rb
->do_menu(&menu
, &selection
, NULL
, false)) {
515 rb
->set_int("Computer starting farms", "", UNIT_INT
,
516 &superdom_settings
.compstartfarms
, NULL
,
520 rb
->set_int("Computer starting factories", "", UNIT_INT
,
521 &superdom_settings
.compstartinds
, NULL
,
525 rb
->set_int("Human starting farms", "", UNIT_INT
,
526 &superdom_settings
.humanstartfarms
, NULL
,
530 rb
->set_int("Human starting factories", "", UNIT_INT
,
531 &superdom_settings
.humanstartinds
, NULL
,
535 rb
->set_int("Starting cash", "", UNIT_INT
,
536 &superdom_settings
.startcash
, NULL
,
540 rb
->set_int("Starting food", "", UNIT_INT
,
541 &superdom_settings
.startfood
, NULL
,
545 rb
->set_int("Moves per turn", "", UNIT_INT
,
546 &superdom_settings
.movesperturn
, NULL
,
549 case MENU_ATTACHED_USB
:
560 static int superdom_help(void) {
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(ARRAYLEN(help_text
), help_text
, NULL
, NULL
))
578 button
= rb
->button_get(true);
579 if ( rb
->default_event_handler( button
) == SYS_USB_CONNECTED
)
581 } while( ( button
== BUTTON_NONE
)
582 || ( button
& (BUTTON_REL
|BUTTON_REPEAT
) ) );
587 int start_menu(void) {
590 MENUITEM_STRINGLIST(menu
, "Super Domination Menu", NULL
,
591 "Play Super Domination", "Settings",
592 "Help", "Playback Control", "Quit");
595 switch(rb
->do_menu(&menu
, &selection
, NULL
, false)) {
597 return RET_VAL_OK
; /* start playing */
600 if(settings_menu()==RET_VAL_USB
)
604 if(superdom_help()==RET_VAL_USB
)
608 if(playback_control(NULL
))
612 return RET_VAL_QUIT_ERR
;
616 return RET_VAL_QUIT_ERR
;
619 int save_game(void) {
621 char savepath
[MAX_PATH
];
623 rb
->snprintf(savepath
, sizeof(savepath
), "/Savegame.ssg");
624 if(rb
->kbd_input(savepath
, MAX_PATH
)) {
625 DEBUGF("Keyboard input failed\n");
629 fd
= rb
->open(savepath
, O_WRONLY
|O_CREAT
);
630 DEBUGF("savepath: %s\n", savepath
);
632 DEBUGF("Couldn't create/open file\n");
636 rb
->write(fd
, "SSGv3", 5);
637 rb
->write(fd
, &gamestate
, sizeof(gamestate
));
638 rb
->write(fd
, &humanres
.cash
, sizeof(humanres
.cash
));
639 rb
->write(fd
, &humanres
.food
, sizeof(humanres
.food
));
640 rb
->write(fd
, &humanres
.bank
, sizeof(humanres
.bank
));
641 rb
->write(fd
, &humanres
.planes
, sizeof(humanres
.planes
));
642 rb
->write(fd
, &humanres
.tanks
, sizeof(humanres
.tanks
));
643 rb
->write(fd
, &humanres
.men
, sizeof(humanres
.men
));
644 rb
->write(fd
, &humanres
.nukes
, sizeof(humanres
.nukes
));
645 rb
->write(fd
, &humanres
.inds
, sizeof(humanres
.inds
));
646 rb
->write(fd
, &humanres
.farms
, sizeof(humanres
.farms
));
647 rb
->write(fd
, &humanres
.moves
, sizeof(humanres
.moves
));
648 rb
->write(fd
, &compres
.cash
, sizeof(compres
.cash
));
649 rb
->write(fd
, &compres
.food
, sizeof(compres
.food
));
650 rb
->write(fd
, &compres
.bank
, sizeof(compres
.bank
));
651 rb
->write(fd
, &compres
.planes
, sizeof(compres
.planes
));
652 rb
->write(fd
, &compres
.tanks
, sizeof(compres
.tanks
));
653 rb
->write(fd
, &compres
.men
, sizeof(compres
.men
));
654 rb
->write(fd
, &compres
.nukes
, sizeof(compres
.nukes
));
655 rb
->write(fd
, &compres
.inds
, sizeof(compres
.inds
));
656 rb
->write(fd
, &compres
.farms
, sizeof(compres
.farms
));
657 rb
->write(fd
, &compres
.moves
, sizeof(compres
.moves
));
658 rb
->write(fd
, board
, sizeof(board
));
659 rb
->write(fd
, &superdom_settings
.compstartfarms
, sizeof(int));
660 rb
->write(fd
, &superdom_settings
.compstartinds
, sizeof(int));
661 rb
->write(fd
, &superdom_settings
.humanstartfarms
, sizeof(int));
662 rb
->write(fd
, &superdom_settings
.humanstartinds
, sizeof(int));
663 rb
->write(fd
, &superdom_settings
.startcash
, sizeof(int));
664 rb
->write(fd
, &superdom_settings
.startfood
, sizeof(int));
665 rb
->write(fd
, &superdom_settings
.movesperturn
, sizeof(int));
670 int ingame_menu(void) {
671 MENUITEM_STRINGLIST(menu
, "Super Domination Menu", NULL
,
672 "Return to game", "Save Game",
673 "Playback Control", "Quit");
675 switch(rb
->do_menu(&menu
, NULL
, NULL
, false)) {
681 rb
->splash(HZ
, "Game saved");
683 rb
->splash(HZ
, "Error in save");
686 if(playback_control(NULL
))
690 return RET_VAL_QUIT_ERR
;
692 case MENU_ATTACHED_USB
:
702 int get_number(char* param
, int* value
, int max
) {
703 static const char *button_labels
[4][3] = {
711 int button
= 0, ret
= RET_VAL_OK
;
713 rb
->lcd_clear_display();
714 rb
->lcd_getstringsize("CLR", &width
, &height
);
715 if(width
> NUM_BOX_WIDTH
|| height
> NUM_BOX_HEIGHT
)
716 rb
->lcd_setfont(FONT_SYSFIXED
);
717 /* Draw a 3x4 grid */
718 for(i
=0;i
<=3;i
++) { /* Vertical lines */
719 rb
->lcd_vline(NUM_MARGIN_X
+(NUM_BOX_WIDTH
*i
), NUM_MARGIN_Y
,
720 NUM_MARGIN_Y
+(4*NUM_BOX_HEIGHT
));
722 for(i
=0;i
<=4;i
++) { /* Horizontal lines */
723 rb
->lcd_hline(NUM_MARGIN_X
, NUM_MARGIN_X
+(3*NUM_BOX_WIDTH
),
724 NUM_MARGIN_Y
+(NUM_BOX_HEIGHT
*i
));
728 rb
->lcd_getstringsize(button_labels
[i
][j
], &width
, &height
);
730 NUM_MARGIN_X
+(j
*NUM_BOX_WIDTH
)+NUM_BOX_WIDTH
/2-width
/2,
731 NUM_MARGIN_Y
+(i
*NUM_BOX_HEIGHT
)+NUM_BOX_HEIGHT
/2-height
/2,
732 button_labels
[i
][j
]);
735 rb
->snprintf(buf
,sizeof(buf
), "%d", *value
);
736 rb
->lcd_putsxy(NUM_MARGIN_X
+10, NUM_MARGIN_Y
+4*NUM_BOX_HEIGHT
+10, buf
);
737 rb
->lcd_getstringsize(param
, &width
, &height
);
738 if(width
< LCD_WIDTH
)
739 rb
->lcd_putsxy((LCD_WIDTH
-width
)/2, (NUM_MARGIN_Y
-height
)/2, param
);
741 rb
->lcd_puts_scroll(0, (NUM_MARGIN_Y
/height
-1)/2, param
);
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
);
749 button
= rb
->button_get(true);
750 rb
->lcd_set_drawmode(DRMODE_COMPLEMENT
);
751 rb
->lcd_fillrect(NUM_MARGIN_X
+(NUM_BOX_WIDTH
*x
),
752 NUM_MARGIN_Y
+(NUM_BOX_HEIGHT
*y
),
753 NUM_BOX_WIDTH
+1, NUM_BOX_HEIGHT
+1);
754 rb
->lcd_set_drawmode(DRMODE_SOLID
);
759 *value
+= button_labels
[y
][x
][0] - '0';
768 if ((unsigned) *value
> (unsigned) max
)
770 rb
->lcd_set_drawmode(DRMODE_BG
|DRMODE_INVERSEVID
);
771 rb
->lcd_fillrect(0, NUM_MARGIN_Y
+4*NUM_BOX_HEIGHT
+10,
773 rb
->lcd_set_drawmode(DRMODE_SOLID
);
774 rb
->snprintf(buf
,sizeof(buf
), "%d", *value
);
775 rb
->lcd_putsxy(NUM_MARGIN_X
+10,
776 NUM_MARGIN_Y
+4*NUM_BOX_HEIGHT
+10, buf
);
778 case SUPERDOM_CANCEL
:
781 ret
= RET_VAL_QUIT_ERR
;
783 #if CONFIG_KEYPAD != IRIVER_H10_PAD
814 #if CONFIG_KEYPAD == IRIVER_H10_PAD
827 #if CONFIG_KEYPAD == IRIVER_H10_PAD
840 if (rb
->default_event_handler(button
) == SYS_USB_CONNECTED
)
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
);
854 rb
->lcd_setfont(FONT_UI
);
855 rb
->lcd_stop_scroll();
856 if (ret
== RET_VAL_QUIT_ERR
)
857 rb
->splash(HZ
, "Cancelled");
861 bool tile_has_item(int type
, int x
, int y
) {
864 return (board
[x
][y
].men
> 0);
867 return board
[x
][y
].tank
;
870 return board
[x
][y
].plane
;
873 return board
[x
][y
].farm
;
876 return board
[x
][y
].ind
;
879 return board
[x
][y
].nuke
;
885 int buy_resources(int colour
, int type
, int x
, int y
, int nummen
) {
886 const char *itemnames
[][6] = {
892 "the industrial plant",
899 "build an industrial plant",
906 "an industrial plant",
911 bool human
= (colour
== COLOUR_LIGHT
);
914 struct resources
*res
;
934 case 4: /* Factory */
941 if(res
->cash
< price
) {
943 rb
->splash(HZ
, "Not enough money!");
944 return RET_VAL_QUIT_ERR
;
947 rb
->splashf(HZ
, "Where do you want to place %s?", itemnames
[0][type
]);
948 if((temp
= select_square()) != RET_VAL_OK
)
953 if(board
[x
][y
].colour
!= colour
) {
955 rb
->splashf(HZ
, "Can't %s on enemy territory", itemnames
[1][type
]);
956 return RET_VAL_QUIT_ERR
;
958 if(type
!= 0 && tile_has_item(type
, x
, y
)) {
960 rb
->splashf(HZ
, "There is already %s there", itemnames
[2][type
]);
961 return RET_VAL_QUIT_ERR
;
965 board
[x
][y
].men
+= nummen
;
969 board
[x
][y
].tank
= true;
973 board
[x
][y
].plane
= true;
977 board
[x
][y
].farm
= true;
981 board
[x
][y
].ind
= true;
985 board
[x
][y
].nuke
= true;
997 int buy_resources_menu(void) {
998 int selection
= 0,nummen
;
1000 MENUITEM_STRINGLIST(menu
, "Buy Resources", NULL
,
1001 "Buy men ($1)", "Buy tank ($300)", "Buy plane ($600)",
1002 "Buy Farm ($1150)", "Buy Factory ($1300)",
1007 switch(rb
->do_menu(&menu
, &selection
, NULL
, false)) {
1010 if(get_number("How many men would you like?", &nummen
,
1011 humanres
.cash
) == RET_VAL_USB
)
1021 if(buy_resources(COLOUR_LIGHT
, selection
, 0, 0, nummen
)
1028 case MENU_ATTACHED_USB
:
1031 case GO_TO_PREVIOUS
:
1039 int move_unit(int colour
, int type
, int fromx
, int fromy
,
1040 int tox
, int toy
, int nummen
) {
1041 const char *itemnames
[][3] = {
1056 bool human
= (colour
== COLOUR_LIGHT
);
1060 rb
->splashf(HZ
, "Select where you want to move %s from",
1061 itemnames
[0][type
]);
1062 if((temp
= select_square()) != RET_VAL_OK
)
1067 if(board
[fromx
][fromy
].colour
!= colour
) {
1069 rb
->splash(HZ
, "That isn't your territory");
1070 return RET_VAL_QUIT_ERR
;
1072 if(!tile_has_item(type
, fromx
, fromy
)) {
1074 rb
->splashf(HZ
, "You don't have %s there", itemnames
[1][type
]);
1075 return RET_VAL_QUIT_ERR
;
1079 nummen
= board
[fromx
][fromy
].men
;
1080 if((temp
= get_number("How many men do you want to move?", &nummen
,
1081 nummen
)) != RET_VAL_OK
)
1084 if(nummen
> board
[fromx
][fromy
].men
) {
1086 rb
->splash(HZ
, "You don't have that many troops.");
1087 return RET_VAL_QUIT_ERR
;
1091 rb
->splashf(HZ
, "Select where you want to move %s to",
1092 itemnames
[2][type
]);
1093 if((temp
= select_square()) != RET_VAL_OK
)
1098 if((tox
== fromx
&& toy
== fromy
) ||
1099 board
[tox
][toy
].colour
!= colour
||
1100 (type
!= 2 && (abs(tox
- fromx
) > 1 || abs(toy
- fromy
) > 1))) {
1102 rb
->splash(HZ
, "Invalid move");
1103 return RET_VAL_QUIT_ERR
;
1105 if(type
!= 0 && tile_has_item(type
, tox
, toy
)) {
1107 rb
->splashf(HZ
, "There is already %s there", itemnames
[1][type
]);
1108 return RET_VAL_QUIT_ERR
;
1112 board
[fromx
][fromy
].men
-= nummen
;
1113 board
[tox
][toy
].men
+= nummen
;
1116 board
[fromx
][fromy
].tank
= false;
1117 board
[tox
][toy
].tank
= true;
1120 board
[fromx
][fromy
].plane
= false;
1121 board
[tox
][toy
].plane
= true;
1127 int move_unit_menu(void) {
1130 MENUITEM_STRINGLIST(menu
, "Move unit", NULL
,
1131 "Move men", "Move tank", "Move plane");
1132 switch(rb
->do_menu(&menu
, &selection
, NULL
, false)) {
1136 switch(move_unit(COLOUR_LIGHT
, selection
, 0, 0, 0, 0, 0)) {
1145 case MENU_ATTACHED_USB
:
1151 int launch_nuke(int colour
, int nukex
, int nukey
, int targetx
, int targety
) {
1152 bool human
= (colour
== COLOUR_LIGHT
);
1154 struct resources
*res
;
1156 if(board
[nukex
][nukey
].colour
!= colour
) {
1158 rb
->splash(HZ
, "That isn't your territory");
1159 return RET_VAL_QUIT_ERR
;
1161 if(! board
[nukex
][nukey
].nuke
) {
1163 rb
->splashf(HZ
, "You don't have %s there", "a nuke");
1164 return RET_VAL_QUIT_ERR
;
1167 rb
->splash(HZ
, "Select place to target with nuke");
1168 if((temp
= select_square()) != RET_VAL_OK
)
1178 board
[nukex
][nukey
].nuke
= false;
1180 if(board
[targetx
][targety
].colour
== COLOUR_LIGHT
) {
1185 res
->men
-= board
[targetx
][targety
].men
;
1186 res
->tanks
-= board
[targetx
][targety
].tank
;
1187 res
->planes
-= board
[targetx
][targety
].plane
;
1188 res
->nukes
-= board
[targetx
][targety
].nuke
;
1189 res
->farms
-= board
[targetx
][targety
].farm
;
1190 res
->inds
-= board
[targetx
][targety
].ind
;
1191 board
[targetx
][targety
].men
= 0;
1192 board
[targetx
][targety
].tank
= false;
1193 board
[targetx
][targety
].plane
= false;
1194 board
[targetx
][targety
].ind
= false;
1195 board
[targetx
][targety
].nuke
= false;
1196 board
[targetx
][targety
].farm
= false;
1197 /* TODO: Fallout carried by wind */
1202 int movement_menu(void) {
1203 int selection
= 0, temp
;
1205 MENUITEM_STRINGLIST(menu
, "Movement", NULL
,
1206 "Move unit", "Buy additional moves ($100)",
1207 "Launch nuclear missile", "Check map",
1208 "Finish moving", "Game menu");
1211 switch(rb
->do_menu(&menu
, &selection
, NULL
, false)) {
1213 if(humanres
.moves
) {
1214 if(move_unit_menu()==RET_VAL_USB
)
1217 rb
->splash(HZ
, "You have no more moves left."
1218 " You can buy more for $100 each.");
1222 if(humanres
.cash
> 100) {
1224 humanres
.cash
-= 100;
1225 rb
->snprintf(buf
, sizeof(buf
), "You now have %d moves",
1227 rb
->splash(HZ
, buf
);
1231 if(humanres
.nukes
==0) {
1232 rb
->splash(HZ
, "You do not have any nukes to launch");
1234 rb
->splash(HZ
, "Select place to launch nuke from");
1235 switch(select_square()) {
1237 if(launch_nuke(COLOUR_LIGHT
, cursor
.x
, cursor
.y
,
1238 0, 0) == RET_VAL_USB
)
1248 if(select_square() == RET_VAL_USB
)
1255 if((temp
= ingame_menu()) != RET_VAL_OK
)
1258 case MENU_ATTACHED_USB
:
1266 static const char* inventory_data(int selected_item
, void * data
,
1267 char * buffer
, size_t buffer_len
) {
1269 switch(selected_item
) {
1271 rb
->snprintf(buffer
,buffer_len
,"Men: %d", humanres
.men
);
1274 rb
->snprintf(buffer
,buffer_len
,"Tanks: %d", humanres
.tanks
);
1277 rb
->snprintf(buffer
,buffer_len
,"Planes: %d", humanres
.planes
);
1280 rb
->snprintf(buffer
,buffer_len
,"Factories: %d", humanres
.inds
);
1283 rb
->snprintf(buffer
,buffer_len
,"Farms: %d", humanres
.farms
);
1286 rb
->snprintf(buffer
,buffer_len
,"Nukes: %d", humanres
.nukes
);
1289 rb
->snprintf(buffer
,buffer_len
,"Cash: %d", humanres
.cash
);
1292 rb
->snprintf(buffer
,buffer_len
,"Food: %d", humanres
.food
);
1295 rb
->snprintf(buffer
,buffer_len
,"Bank: %d", humanres
.bank
);
1303 int show_inventory(void) {
1304 struct simplelist_info info
;
1305 rb
->simplelist_info_init(&info
, "Inventory", 9, NULL
);
1306 info
.hide_selection
= true;
1307 info
.get_name
= inventory_data
;
1308 if(rb
->simplelist_show_list(&info
)) {
1315 int production_menu(void) {
1316 int selection
= 0, temp
;
1318 MENUITEM_STRINGLIST(menu
, "Production", NULL
,
1319 "Buy resources", "Show inventory", "Check map",
1320 "Invest money", "Withdraw money",
1321 "Finish turn", "Game menu");
1324 switch(rb
->do_menu(&menu
, &selection
, NULL
, false)) {
1326 if(buy_resources_menu() == RET_VAL_USB
)
1330 if(show_inventory() == RET_VAL_USB
)
1334 if(select_square() == RET_VAL_USB
)
1338 temp
= humanres
.cash
;
1339 if(get_number("How much do you want to invest?", &temp
,
1340 humanres
.cash
) == RET_VAL_USB
)
1342 if(temp
> humanres
.cash
) {
1343 rb
->splash(HZ
, "You don't have that much cash to invest");
1345 humanres
.cash
-= temp
;
1346 humanres
.bank
+= temp
;
1350 temp
= humanres
.bank
;
1351 if(get_number("How much do you want to withdraw?", &temp
,
1352 humanres
.bank
) == RET_VAL_USB
)
1354 if(temp
> humanres
.bank
) {
1355 rb
->splash(HZ
, "You don't have that much cash to withdraw");
1357 humanres
.cash
+= temp
;
1358 humanres
.bank
-= temp
;
1365 if((temp
= ingame_menu()) != RET_VAL_OK
)
1368 case MENU_ATTACHED_USB
:
1376 void init_resources(void) {
1377 humanres
.cash
= superdom_settings
.startcash
;
1378 humanres
.food
= superdom_settings
.startfood
;
1380 humanres
.planes
= 0;
1387 compres
.cash
= superdom_settings
.startcash
;
1388 compres
.food
= superdom_settings
.startfood
;
1399 int select_square(void) {
1404 #if LCD_WIDTH >= 220
1405 rb
->lcd_setfont(FONT_SYSFIXED
);
1406 rb
->snprintf(buf
, sizeof(buf
), "Cash: %d", humanres
.cash
);
1407 rb
->lcd_putsxy(125, LCD_HEIGHT
-20, buf
);
1408 rb
->snprintf(buf
, sizeof(buf
), "Food: %d", humanres
.food
);
1409 rb
->lcd_putsxy(125, LCD_HEIGHT
-10, buf
);
1410 rb
->lcd_setfont(FONT_UI
);
1414 button
= rb
->button_get(true);
1416 case SUPERDOM_CANCEL
:
1417 rb
->splash(HZ
, "Cancelled");
1418 return RET_VAL_QUIT_ERR
;
1423 #if CONFIG_KEYPAD != IRIVER_H10_PAD
1425 case (SUPERDOM_LEFT
|BUTTON_REPEAT
):
1426 draw_cursor(); /* Deselect the current tile */
1441 case SUPERDOM_RIGHT
:
1442 case (SUPERDOM_RIGHT
|BUTTON_REPEAT
):
1443 draw_cursor(); /* Deselect the current tile */
1461 case (SUPERDOM_UP
|BUTTON_REPEAT
):
1462 draw_cursor(); /* Deselect the current tile */
1466 #if CONFIG_KEYPAD == IRIVER_H10_PAD
1478 case (SUPERDOM_DOWN
|BUTTON_REPEAT
):
1479 draw_cursor(); /* Deselect the current tile */
1483 #if CONFIG_KEYPAD == IRIVER_H10_PAD
1496 if (rb
->default_event_handler(button
) == SYS_USB_CONNECTED
)
1504 int killmen(int colour
) {
1505 bool human
= (colour
== COLOUR_LIGHT
);
1509 percent
= (humanres
.food
*1000)/humanres
.men
;
1512 percent
= (compres
.food
*1000)/compres
.men
;
1518 if(board
[i
][j
].colour
== colour
) {
1519 int nummen
= ((board
[i
][j
].men
* percent
)/1000);
1520 menkilled
+= board
[i
][j
].men
- nummen
;
1521 board
[i
][j
].men
= nummen
;
1527 humanres
.men
-= menkilled
;
1529 compres
.men
-= menkilled
;
1533 /* return -1 if error, 1 if attack is succeeded, 0 otherwise */
1534 int attack_territory(int colour
, int x
, int y
) {
1535 bool human
= (colour
== COLOUR_LIGHT
);
1538 if(board
[x
][y
].colour
== colour
) {
1540 rb
->splash(HZ
, "You can't attack your own territory");
1543 str_diff
= calc_strength(COLOUR_DARK
, x
, y
) -
1544 calc_strength(COLOUR_LIGHT
, x
, y
);
1546 str_diff
= -str_diff
;
1548 rb
->srand(*rb
->current_tick
);
1549 if(str_diff
> 0 || (str_diff
== 0 && rb
->rand()%2)) {
1550 struct resources
*offres
, *defres
;
1558 defres
->men
-= board
[x
][y
].men
;
1559 defres
->tanks
-= board
[x
][y
].tank
;
1560 defres
->planes
-= board
[x
][y
].plane
;
1561 defres
->nukes
-= board
[x
][y
].nuke
;
1562 defres
->farms
-= board
[x
][y
].farm
;
1563 defres
->inds
-= board
[x
][y
].ind
;
1564 offres
->farms
+= board
[x
][y
].farm
;
1565 offres
->inds
+= board
[x
][y
].ind
;
1566 board
[x
][y
].colour
= colour
;
1567 board
[x
][y
].men
= 0;
1568 board
[x
][y
].tank
= false;
1569 board
[x
][y
].plane
= false;
1570 board
[x
][y
].nuke
= false;
1579 rb
->splash(HZ
, "Your troops were unable to overcome"
1580 " the enemy troops");
1582 rb
->splash(HZ
*2, "The computer attempted to "
1583 "attack, but the invasion was"
1590 int war_menu(void) {
1591 int selection
= 0, temp
;
1593 MENUITEM_STRINGLIST(menu
, "War!", NULL
,
1594 "Select territory to attack",
1595 "Finish turn", "Game menu");
1597 while(humanres
.moves
) {
1598 switch(rb
->do_menu(&menu
, &selection
, NULL
, false)) {
1600 switch(select_square()) {
1602 if(attack_territory(COLOUR_LIGHT
, cursor
.x
, cursor
.y
)
1615 if((temp
= ingame_menu()) != RET_VAL_OK
)
1629 bool place_adjacent(bool tank
, int x
, int y
) {
1630 int type
= (tank
? 1: 2);
1631 if(!buy_resources(COLOUR_DARK
, type
, x
, y
, 0)) {
1634 if(!buy_resources(COLOUR_DARK
, type
, x
-1, y
, 0)) {
1637 if(!buy_resources(COLOUR_DARK
, type
, x
+1, y
, 0)) {
1640 if(!buy_resources(COLOUR_DARK
, type
, x
, y
-1, 0)) {
1643 if(!buy_resources(COLOUR_DARK
, type
, x
, y
+1, 0)) {
1649 bool has_adjacent(int x
, int y
) {
1650 if((board
[x
][y
].colour
== COLOUR_LIGHT
) &&
1651 ((board
[x
-1][y
].colour
== COLOUR_DARK
) ||
1652 (board
[x
+1][y
].colour
== COLOUR_DARK
) ||
1653 (board
[x
][y
+1].colour
== COLOUR_DARK
) ||
1654 (board
[x
][y
-1].colour
== COLOUR_DARK
)))
1660 void find_adjacent(int x
, int y
, int* adj_x
, int* adj_y
) {
1661 /* Finds adjacent squares, returning squares without tanks on them
1662 * in preference to those with them */
1663 if(board
[x
-1][y
].colour
== COLOUR_DARK
) {
1668 if(board
[x
+1][y
].colour
== COLOUR_DARK
) {
1673 if(board
[x
][y
-1].colour
== COLOUR_DARK
) {
1678 if(board
[x
][y
+1].colour
== COLOUR_DARK
) {
1685 void computer_allocate(void) {
1686 /* Firstly, decide whether to go offensive or defensive.
1687 * This is primarily decided by the human player posing a threat to either
1688 * the computer's farms or factories */
1690 bool offensive
= true;
1691 struct threat threats
[4];
1693 int total_str_diff
= 0;
1694 int numterritory
= 0;
1697 struct threat targets
[2];
1701 compres
.cash
+= compres
.bank
;
1705 if(board
[i
][j
].colour
== COLOUR_DARK
) {
1707 str_diff
= calc_strength(COLOUR_LIGHT
,i
,j
) -
1708 calc_strength(COLOUR_DARK
,i
,j
);
1709 if(str_diff
> 0 && (board
[i
][j
].ind
|| board
[i
][j
].farm
)) {
1710 if(numthreats
< 3) {
1712 threats
[numthreats
].x
= i
;
1713 threats
[numthreats
].y
= j
;
1714 threats
[numthreats
].str_diff
= str_diff
;
1723 /* The AI is going to go straight for the throat here and attack
1724 * the player's farms and factories. The amount of cash
1725 * the AI has to spend will determine how many targets there are */
1726 if(compres
.cash
> 1200) {
1727 /* 1200 is a figure I pulled out of nowhere. Adjust as needed */
1732 /* Work out which target(s) to attack. They must have adjacent squares
1733 * owned by the computer. If none are found just place troops in
1734 * random places around the map until we run out of money */
1738 if(has_adjacent(i
,j
) &&
1739 (board
[i
][j
].ind
|| board
[i
][j
].farm
)) {
1743 targets
[k
].str_diff
=
1744 calc_strength(COLOUR_LIGHT
, i
, j
) -
1745 calc_strength(COLOUR_DARK
, i
, j
);
1753 /* No targets found! Randomly pick squares and if they're owned
1754 * by the computer then stick a tank on it. */
1755 rb
->srand(*rb
->current_tick
);
1756 while(compres
.cash
>= 300 && compres
.tanks
< numterritory
) {
1757 i
= rb
->rand()%10 + 1;
1758 j
= rb
->rand()%10 + 1;
1759 if(board
[i
][j
].colour
== COLOUR_DARK
) {
1760 buy_resources(COLOUR_DARK
, 1, i
, j
, 0);
1766 str_diff
= targets
[i
].str_diff
;
1767 while(str_diff
+ 20 > 0 && compres
.cash
> 0) {
1768 /* While we still need them keep placing men */
1769 if(!place_adjacent(true, targets
[i
].x
, targets
[i
].y
)) {
1770 find_adjacent(targets
[i
].x
, targets
[i
].y
,
1772 men_needed
= (str_diff
+ 20)*1000/133;
1773 if(compres
.cash
< men_needed
) {
1774 men_needed
= compres
.cash
;
1776 buy_resources(COLOUR_DARK
, 0, adj
.x
, adj
.y
,
1780 str_diff
= calc_strength(COLOUR_LIGHT
,
1781 targets
[i
].x
, targets
[i
].y
) -
1782 calc_strength(COLOUR_DARK
,
1783 targets
[i
].x
, targets
[i
].y
);
1788 /* Work out what to place on each square to defend it.
1789 * Tanks are preferential because they do not require food,
1790 * but if the budget is tight then we fall back onto troops.
1791 * Conversely if cash is not an issue and there are already tanks in
1792 * place planes will be deployed. We would like a margin of at least
1793 * 20 points to be safe. */
1795 for(i
=0;i
<numthreats
;i
++) {
1796 total_str_diff
+= threats
[i
].str_diff
;
1798 if((total_str_diff
+20)*10 > compres
.cash
) {
1799 /* Not enough cash to accomodate all threats using tanks alone -
1800 * use men as a backup */
1801 for(i
=0;i
<numthreats
;i
++) {
1802 men_needed
= ((threats
[i
].str_diff
+ 20)*1000)/133;
1803 if(compres
.cash
< men_needed
) {
1804 men_needed
= compres
.cash
;
1806 buy_resources(COLOUR_DARK
, 0, threats
[i
].x
, threats
[i
].y
,
1811 /* Enough money to pay their way by planes? */
1812 bool tank
= ((total_str_diff
+20)*15 >= compres
.cash
);
1813 for(i
=0;i
<numthreats
;i
++) {
1814 str_diff
= threats
[i
].str_diff
;
1815 while(str_diff
+ 20 > 0) {
1816 if(!place_adjacent(tank
, threats
[i
].x
, threats
[i
].y
)) {
1817 /* No room for any more planes or tanks, revert to
1819 find_adjacent(threats
[i
].x
, threats
[i
].y
,
1821 men_needed
= (str_diff
+ 20)*1000/133;
1822 if(compres
.cash
< men_needed
) {
1823 men_needed
= compres
.cash
;
1825 buy_resources(COLOUR_DARK
, 0, threats
[i
].x
,
1826 threats
[i
].y
, men_needed
);
1829 str_diff
= calc_strength(COLOUR_LIGHT
,
1830 threats
[i
].x
, threats
[i
].y
) -
1831 calc_strength(COLOUR_DARK
,
1832 threats
[i
].x
, threats
[i
].y
);
1837 compres
.bank
+= compres
.cash
;
1841 int find_adj_target(int x
, int y
, struct cursor
* adj
) {
1842 /* Find a square next to a computer's farm or factory owned by the player
1843 * that is vulnerable. Return 1 on success, 0 otherwise */
1844 if(board
[x
+1][y
].colour
== COLOUR_LIGHT
&&
1845 calc_strength(COLOUR_LIGHT
,x
+1,y
)<=calc_strength(COLOUR_DARK
,x
+1,y
)) {
1850 if(board
[x
-1][y
].colour
== COLOUR_LIGHT
&&
1851 calc_strength(COLOUR_LIGHT
,x
-1,y
)<=calc_strength(COLOUR_DARK
,x
-1,y
)) {
1856 if(board
[x
][y
+1].colour
== COLOUR_LIGHT
&&
1857 calc_strength(COLOUR_LIGHT
,x
,y
+1)<=calc_strength(COLOUR_DARK
,x
,y
+1)) {
1862 if(board
[x
][y
-1].colour
== COLOUR_LIGHT
&&
1863 calc_strength(COLOUR_LIGHT
,x
,y
-1)<=calc_strength(COLOUR_DARK
,x
,y
-1)) {
1871 void computer_war(void) {
1872 /* Work out where to attack - prioritise the defence of buildings */
1874 bool found_target
= true;
1877 while(found_target
) {
1878 found_target
= false;
1881 if((board
[i
][j
].colour
== COLOUR_DARK
) &&
1882 (board
[i
][j
].farm
|| board
[i
][j
].ind
) &&
1883 find_adj_target(i
, j
, &adj
)) {
1884 found_target
= true;
1885 if(attack_territory(COLOUR_DARK
, adj
.x
, adj
.y
) >= 0) {
1895 /* Defence stage done, move on to OFFENCE */
1896 found_target
= true;
1897 while(found_target
) {
1898 found_target
= false;
1901 if(board
[i
][j
].colour
== COLOUR_LIGHT
&&
1902 (board
[i
][j
].ind
|| board
[i
][j
].farm
) &&
1903 (calc_strength(COLOUR_DARK
, i
, j
) >=
1904 calc_strength(COLOUR_LIGHT
, i
, j
))) {
1905 found_target
= true;
1906 if(attack_territory(COLOUR_DARK
, i
, j
) >= 0) {
1916 /* Spend leftover moves wherever attacking randomly */
1917 found_target
= true;
1918 while(found_target
) {
1919 found_target
= false;
1922 if(board
[i
][j
].colour
== COLOUR_LIGHT
&&
1923 (calc_strength(COLOUR_DARK
, i
, j
) >=
1924 calc_strength(COLOUR_LIGHT
, i
, j
))) {
1925 found_target
= true;
1926 if(attack_territory(COLOUR_DARK
, i
, j
) >= 0) {
1938 static int load_game(const char* file
) {
1941 fd
= rb
->open(file
, O_RDONLY
);
1943 DEBUGF("Couldn't open savegame\n");
1946 rb
->read(fd
, buf
, 5);
1947 if(rb
->strcmp(buf
, "SSGv3")) {
1948 rb
->splash(HZ
, "Invalid/incompatible savegame");
1951 rb
->read(fd
, &gamestate
, sizeof(gamestate
));
1952 rb
->read(fd
, &humanres
.cash
, sizeof(humanres
.cash
));
1953 rb
->read(fd
, &humanres
.food
, sizeof(humanres
.food
));
1954 rb
->read(fd
, &humanres
.bank
, sizeof(humanres
.bank
));
1955 rb
->read(fd
, &humanres
.planes
, sizeof(humanres
.planes
));
1956 rb
->read(fd
, &humanres
.tanks
, sizeof(humanres
.tanks
));
1957 rb
->read(fd
, &humanres
.men
, sizeof(humanres
.men
));
1958 rb
->read(fd
, &humanres
.nukes
, sizeof(humanres
.nukes
));
1959 rb
->read(fd
, &humanres
.inds
, sizeof(humanres
.inds
));
1960 rb
->read(fd
, &humanres
.farms
, sizeof(humanres
.farms
));
1961 rb
->read(fd
, &humanres
.moves
, sizeof(humanres
.moves
));
1962 rb
->read(fd
, &compres
.cash
, sizeof(humanres
.cash
));
1963 rb
->read(fd
, &compres
.food
, sizeof(humanres
.food
));
1964 rb
->read(fd
, &compres
.bank
, sizeof(humanres
.bank
));
1965 rb
->read(fd
, &compres
.planes
, sizeof(humanres
.planes
));
1966 rb
->read(fd
, &compres
.tanks
, sizeof(humanres
.tanks
));
1967 rb
->read(fd
, &compres
.men
, sizeof(humanres
.men
));
1968 rb
->read(fd
, &compres
.nukes
, sizeof(humanres
.nukes
));
1969 rb
->read(fd
, &compres
.inds
, sizeof(humanres
.inds
));
1970 rb
->read(fd
, &compres
.farms
, sizeof(humanres
.farms
));
1971 rb
->read(fd
, &compres
.moves
, sizeof(humanres
.moves
));
1972 rb
->read(fd
, board
, sizeof(board
));
1973 rb
->read(fd
, &superdom_settings
.compstartfarms
, sizeof(int));
1974 rb
->read(fd
, &superdom_settings
.compstartinds
, sizeof(int));
1975 rb
->read(fd
, &superdom_settings
.humanstartfarms
, sizeof(int));
1976 rb
->read(fd
, &superdom_settings
.humanstartinds
, sizeof(int));
1977 rb
->read(fd
, &superdom_settings
.startcash
, sizeof(int));
1978 rb
->read(fd
, &superdom_settings
.startfood
, sizeof(int));
1979 rb
->read(fd
, &superdom_settings
.movesperturn
, sizeof(int));
1984 void default_settings(void) {
1985 superdom_settings
.compstartfarms
= 1;
1986 superdom_settings
.compstartinds
= 1;
1987 superdom_settings
.humanstartfarms
= 2;
1988 superdom_settings
.humanstartinds
= 2;
1989 superdom_settings
.startcash
= 0;
1990 superdom_settings
.startfood
= 0;
1991 superdom_settings
.movesperturn
= 2;
1994 int average_strength(int colour
) {
1995 /* This function calculates the average strength of the given player,
1996 * used to determine when the computer wins or loses. */
2001 if(board
[i
][j
].colour
!= -1) {
2002 totalpower
+= calc_strength(colour
, i
, j
);
2006 return totalpower
/100;
2009 enum plugin_status
plugin_start(const void* parameter
)
2012 rb
->lcd_set_backdrop(NULL
);
2013 rb
->lcd_set_foreground(LCD_BLACK
);
2014 rb
->lcd_set_background(LCD_WHITE
);
2021 if(load_game(parameter
) != 0) {
2022 DEBUGF("Loading failed, generating new game\n");
2041 switch(start_menu()) {
2042 case RET_VAL_OK
: /* start playing */
2044 case RET_VAL_QUIT_ERR
: /* quit */
2048 return PLUGIN_USB_CONNECTED
;
2057 int avg_str_diff
= (average_strength(COLOUR_LIGHT
) -
2058 average_strength(COLOUR_DARK
));
2059 if(avg_str_diff
> 15) {
2060 rb
->splash(HZ
*4, "The computer has surrendered. You win.");
2063 if(-avg_str_diff
> 15) {
2064 rb
->splash(HZ
*4, "Your army have suffered terrible morale from"
2065 " the bleak prospects of winning. You lose.");
2071 gamestate
= GS_PROD
;
2072 switch(production_menu()) {
2074 return PLUGIN_USB_CONNECTED
;
2076 case RET_VAL_QUIT_ERR
:
2080 computer_allocate();
2083 humanres
.moves
= superdom_settings
.movesperturn
;
2085 gamestate
= GS_MOVE
;
2086 switch(movement_menu()) {
2088 return PLUGIN_USB_CONNECTED
;
2090 case RET_VAL_QUIT_ERR
:
2096 if(humanres
.food
> humanres
.men
) {
2097 rb
->snprintf(buf
, sizeof(buf
), "Your men ate %d units of food",
2099 humanres
.food
-= humanres
.men
;
2101 rb
->snprintf(buf
, sizeof(buf
), "There was not enough food"
2102 " to feed all your men, %d men have died of starvation",
2103 killmen(COLOUR_LIGHT
));
2105 rb
->splash(HZ
*2, buf
);
2108 if(compres
.food
> compres
.men
) {
2109 compres
.food
-= compres
.men
;
2111 rb
->snprintf(buf
, sizeof(buf
), "The computer does not have"
2112 " enough food to feed its men. %d have died of starvation",
2113 killmen(COLOUR_DARK
));
2114 rb
->splash(HZ
, buf
);
2118 humanres
.moves
= superdom_settings
.movesperturn
;
2121 switch(war_menu()) {
2123 return PLUGIN_USB_CONNECTED
;
2125 case RET_VAL_QUIT_ERR
:
2129 compres
.moves
= superdom_settings
.movesperturn
;