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
} gamestate
;
248 struct tile board
[12][12];
250 void init_board(void) {
252 rb
->srand(*rb
->current_tick
);
253 for(i
=0;i
<12;i
++) { /* Hopefully about 50% each colour */
255 if((i
<1)||(j
<1)||(i
>10)||(j
>10))
256 board
[i
][j
].colour
= -1; /* Unset */
258 board
[i
][j
].colour
= rb
->rand()%2;
259 board
[i
][j
].tank
= false;
260 board
[i
][j
].plane
= false;
261 board
[i
][j
].nuke
= false;
262 board
[i
][j
].ind
= false;
263 board
[i
][j
].farm
= false;
268 while(compres
.farms
< superdom_settings
.compstartfarms
) {
269 i
= rb
->rand()%10 + 1;
270 j
= rb
->rand()%10 + 1;
271 if((board
[i
][j
].colour
== COLOUR_DARK
) && (board
[i
][j
].farm
== false)) {
272 board
[i
][j
].farm
= true;
276 while(compres
.inds
< superdom_settings
.compstartinds
) {
277 i
= rb
->rand()%10 + 1;
278 j
= rb
->rand()%10 + 1;
279 if((board
[i
][j
].colour
== COLOUR_DARK
) && (board
[i
][j
].ind
== false)) {
280 board
[i
][j
].ind
= true;
284 while(humanres
.farms
< superdom_settings
.humanstartfarms
) {
285 i
= rb
->rand()%10 + 1;
286 j
= rb
->rand()%10 + 1;
287 if((board
[i
][j
].colour
== COLOUR_LIGHT
)&&(board
[i
][j
].farm
== false)) {
288 board
[i
][j
].farm
= true;
292 while(humanres
.inds
< superdom_settings
.humanstartinds
) {
293 i
= rb
->rand()%10 + 1;
294 j
= rb
->rand()%10 + 1;
295 if((board
[i
][j
].colour
== COLOUR_LIGHT
) && (board
[i
][j
].ind
== false)) {
296 board
[i
][j
].ind
= true;
302 void draw_board(void) {
304 rb
->lcd_clear_display();
307 if(board
[i
][j
].colour
== COLOUR_DARK
) {
308 rb
->lcd_set_foreground(LCD_DARKGRAY
);
310 rb
->lcd_set_foreground(LCD_LIGHTGRAY
);
312 rb
->lcd_fillrect(MARGIN
+(BOX_WIDTH
*(i
-1)),
313 MARGIN
+(BOX_HEIGHT
*(j
-1)), BOX_WIDTH
,
316 rb
->lcd_set_drawmode(DRMODE_BG
| DRMODE_INVERSEVID
);
318 if(board
[i
][j
].ind
) {
319 MY_BITMAP_PART(superdom_boarditems
,
320 board
[i
][j
].colour
?ICON_WIDTH
:0, 0, ICON_STRIDE
,
321 #if LCD_WIDTH > LCD_HEIGHT
322 MARGIN
+(BOX_WIDTH
*(i
-1))+1,
323 MARGIN
+(BOX_HEIGHT
*(j
-1))+ICON_HEIGHT
+1,
325 MARGIN
+(BOX_WIDTH
*(i
-1))+1+ICON_WIDTH
,
326 MARGIN
+(BOX_HEIGHT
*(j
-1))+1,
328 ICON_WIDTH
, ICON_HEIGHT
);
330 if(board
[i
][j
].farm
) {
331 MY_BITMAP_PART(superdom_boarditems
,
332 board
[i
][j
].colour
?ICON_WIDTH
:0, ICON_HEIGHT
,
333 ICON_STRIDE
, MARGIN
+(BOX_WIDTH
*(i
-1))+1,
334 MARGIN
+(BOX_HEIGHT
*(j
-1))+1,
335 ICON_WIDTH
, ICON_HEIGHT
);
337 if(board
[i
][j
].tank
) {
338 MY_BITMAP_PART(superdom_boarditems
,
339 board
[i
][j
].colour
?ICON_WIDTH
:0, ICON_HEIGHT
*2,
340 ICON_STRIDE
, MARGIN
+(BOX_WIDTH
*(i
-1))+ICON_WIDTH
+1,
341 MARGIN
+(BOX_HEIGHT
*(j
-1))+ICON_HEIGHT
+1,
342 ICON_WIDTH
, ICON_HEIGHT
);
344 if(board
[i
][j
].men
) {
345 MY_BITMAP_PART(superdom_boarditems
,
346 board
[i
][j
].colour
?ICON_WIDTH
:0, ICON_HEIGHT
*3,
347 #if LCD_WIDTH > LCD_HEIGHT
348 ICON_STRIDE
, MARGIN
+(BOX_WIDTH
*(i
-1))+ICON_WIDTH
+1,
349 MARGIN
+(BOX_HEIGHT
*(j
-1))+1,
351 ICON_STRIDE
, MARGIN
+(BOX_WIDTH
*(i
-1))+1,
352 MARGIN
+(BOX_HEIGHT
*(j
-1))+1+ICON_HEIGHT
,
354 ICON_WIDTH
, ICON_HEIGHT
);
356 if(board
[i
][j
].plane
) {
357 MY_BITMAP_PART(superdom_boarditems
,
358 board
[i
][j
].colour
?ICON_WIDTH
:0, ICON_HEIGHT
*4,
359 #if LCD_WIDTH > LCD_HEIGHT
360 ICON_STRIDE
,MARGIN
+(BOX_WIDTH
*(i
-1))+ICON_WIDTH
*2+1,
361 MARGIN
+(BOX_HEIGHT
*(j
-1))+ICON_HEIGHT
+1,
363 ICON_STRIDE
,MARGIN
+(BOX_WIDTH
*(i
-1))+ICON_WIDTH
+1,
364 MARGIN
+(BOX_HEIGHT
*(j
-1))+ICON_HEIGHT
*2+1,
366 ICON_WIDTH
, ICON_HEIGHT
);
368 if(board
[i
][j
].nuke
) {
369 MY_BITMAP_PART(superdom_boarditems
,
370 board
[i
][j
].colour
?ICON_WIDTH
:0, ICON_HEIGHT
*5,
371 #if LCD_WIDTH > LCD_HEIGHT
372 ICON_STRIDE
,MARGIN
+(BOX_WIDTH
*(i
-1))+ICON_WIDTH
*2+1,
373 MARGIN
+(BOX_HEIGHT
*(j
-1))+1,
375 ICON_STRIDE
,MARGIN
+(BOX_WIDTH
*(i
-1))+1,
376 MARGIN
+(BOX_HEIGHT
*(j
-1))+ICON_HEIGHT
*2+1,
378 ICON_WIDTH
, ICON_HEIGHT
);
381 rb
->lcd_set_drawmode(DRMODE_SOLID
);
385 rb
->lcd_set_foreground(LCD_BLACK
);
386 for(i
=0;i
<=10;i
++) { /* Draw Horizontal lines */
387 rb
->lcd_hline(MARGIN
, MARGIN
+(BOX_WIDTH
*10), MARGIN
+(BOX_HEIGHT
*i
));
389 for(i
=0;i
<=10;i
++) { /* Draw Vertical lines */
390 rb
->lcd_vline(MARGIN
+(BOX_WIDTH
*i
), MARGIN
, MARGIN
+(BOX_HEIGHT
*10));
395 int calc_strength(int colour
, int x
, int y
) {
397 for (a
= -1; a
< 2; a
++) {
398 for (b
= -1; b
< 2; b
++) {
399 if ((b
== 0 || a
== 0) &&
400 (board
[x
+ a
][y
+ b
].colour
== colour
)) {
402 if(board
[x
+ a
][y
+ b
].tank
|| board
[x
+ a
][y
+ b
].farm
)
404 if(board
[x
+ a
][y
+ b
].plane
|| board
[x
+ a
][y
+ b
].ind
)
406 if(board
[x
+ a
][y
+ b
].nuke
)
408 if(board
[x
+ a
][y
+ b
].men
)
409 score
+= (board
[x
+ a
][y
+ b
].men
*133/1000);
416 void gen_interest(void) {
417 /* Interest should be around 10% */
418 rb
->srand(*rb
->current_tick
);
419 int interest
= 7+rb
->rand()%6;
420 humanres
.bank
= humanres
.bank
+(interest
*humanres
.bank
/100);
421 compres
.bank
= compres
.bank
+(interest
*compres
.bank
/100);
424 void draw_cursor(void) {
425 rb
->lcd_set_drawmode(DRMODE_COMPLEMENT
);
426 rb
->lcd_fillrect(MARGIN
+((cursor
.x
-1)*BOX_WIDTH
),
427 MARGIN
+((cursor
.y
-1)*BOX_HEIGHT
), BOX_WIDTH
+1, BOX_HEIGHT
+1);
428 rb
->lcd_set_drawmode(DRMODE_SOLID
);
432 void gen_resources(void) {
439 rb
->srand(*rb
->current_tick
);
440 /* Generate Human's resources */
441 for(i
=0;i
<humanres
.inds
;i
++) {
442 inccash
+= (300+rb
->rand()%200);
444 for(i
=0;i
<humanres
.farms
;i
++) {
445 incfood
+= (200+rb
->rand()%200);
448 ratecash
= inccash
/humanres
.inds
;
450 ratefood
= incfood
/humanres
.farms
;
453 rb
->splash(HZ
*2, "Patriotism sweeps the land, all production"
454 " is up this year!");
456 rb
->splash(HZ
*2, "Factories working at maximum efficiency,"
457 " cash production up this year!");
459 } else if(ratecash
> 350) {
461 rb
->splash(HZ
*2, "Record crop harvest this year!");
462 } else if(ratefood
> 250) {
463 rb
->splash(HZ
*2, "Production continues as normal");
465 rb
->splash(HZ
*2, "Spoilage of crops leads to reduced farm"
466 " output this year");
470 rb
->splash(HZ
*2, "Record crop harvest this year!");
471 } else if(ratefood
> 250) {
472 rb
->splash(HZ
*2, "Factory unions introduced. Industrial"
473 " production is down this year.");
475 rb
->splash(HZ
*2, "Internet created. All production is down"
476 " due to time wasted.");
479 humanres
.cash
+= inccash
;
480 humanres
.food
+= incfood
;
482 /* Generate Computer's resources */
485 for(i
=0;i
<compres
.inds
;i
++) {
486 inccash
+= (300+rb
->rand()%200);
488 for(i
=0;i
<compres
.farms
;i
++) {
489 incfood
+= (200+rb
->rand()%200);
491 compres
.cash
+= inccash
;
492 compres
.food
+= incfood
;
495 void update_score(void) {
497 rb
->lcd_setfont(FONT_SYSFIXED
);
498 rb
->lcd_set_drawmode(DRMODE_BG
|DRMODE_INVERSEVID
);
499 rb
->lcd_fillrect(5,LCD_HEIGHT
-20,105,20);
500 rb
->lcd_set_drawmode(DRMODE_SOLID
);
501 strength
= calc_strength(COLOUR_LIGHT
, cursor
.x
, cursor
.y
);
502 rb
->snprintf(buf
, sizeof(buf
), "Your power: %d.%d",
503 strength
/10, strength
%10);
504 rb
->lcd_putsxy(5,LCD_HEIGHT
-20, buf
);
505 strength
= calc_strength(COLOUR_DARK
, cursor
.x
, cursor
.y
);
506 rb
->snprintf(buf
, sizeof(buf
), "Comp power: %d.%d",
507 strength
/10, strength
%10);
508 rb
->lcd_putsxy(5,LCD_HEIGHT
-10, buf
);
509 rb
->lcd_setfont(FONT_UI
);
512 int settings_menu(void) {
515 MENUITEM_STRINGLIST(menu
, "Super Domination Settings", NULL
,
516 "Computer starting farms", "Computer starting factories",
517 "Human starting farms", "Human starting factories",
518 "Starting cash", "Starting food", "Moves per turn");
521 switch(rb
->do_menu(&menu
, &selection
, NULL
, false)) {
523 rb
->set_int("Computer starting farms", "", UNIT_INT
,
524 &superdom_settings
.compstartfarms
, NULL
,
528 rb
->set_int("Computer starting factories", "", UNIT_INT
,
529 &superdom_settings
.compstartinds
, NULL
,
533 rb
->set_int("Human starting farms", "", UNIT_INT
,
534 &superdom_settings
.humanstartfarms
, NULL
,
538 rb
->set_int("Human starting factories", "", UNIT_INT
,
539 &superdom_settings
.humanstartinds
, NULL
,
543 rb
->set_int("Starting cash", "", UNIT_INT
,
544 &superdom_settings
.startcash
, NULL
,
548 rb
->set_int("Starting food", "", UNIT_INT
,
549 &superdom_settings
.startfood
, NULL
,
553 rb
->set_int("Moves per turn", "", UNIT_INT
,
554 &superdom_settings
.movesperturn
, NULL
,
557 case MENU_ATTACHED_USB
:
568 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
))
586 button
= rb
->button_get(true);
587 if ( rb
->default_event_handler( button
) == SYS_USB_CONNECTED
)
589 } while( ( button
== BUTTON_NONE
)
590 || ( button
& (BUTTON_REL
|BUTTON_REPEAT
) ) );
595 int start_menu(void) {
598 MENUITEM_STRINGLIST(menu
, "Super Domination Menu", NULL
,
599 "Play Super Domination", "Settings",
600 "Help", "Playback Control", "Quit");
603 switch(rb
->do_menu(&menu
, &selection
, NULL
, false)) {
605 return RET_VAL_OK
; /* start playing */
608 if(settings_menu()==RET_VAL_USB
)
612 if(superdom_help()==RET_VAL_USB
)
616 if(playback_control(NULL
))
620 return RET_VAL_QUIT_ERR
;
624 return RET_VAL_QUIT_ERR
;
627 int save_game(void) {
629 char savepath
[MAX_PATH
];
631 rb
->snprintf(savepath
, sizeof(savepath
), "/Savegame.ssg");
632 if(rb
->kbd_input(savepath
, MAX_PATH
)) {
633 DEBUGF("Keyboard input failed\n");
637 fd
= rb
->open(savepath
, O_WRONLY
|O_CREAT
);
638 DEBUGF("savepath: %s\n", savepath
);
640 DEBUGF("Couldn't create/open file\n");
644 rb
->write(fd
, "SSGv3", 5);
645 rb
->write(fd
, &gamestate
, sizeof(gamestate
));
646 rb
->write(fd
, &humanres
.cash
, sizeof(humanres
.cash
));
647 rb
->write(fd
, &humanres
.food
, sizeof(humanres
.food
));
648 rb
->write(fd
, &humanres
.bank
, sizeof(humanres
.bank
));
649 rb
->write(fd
, &humanres
.planes
, sizeof(humanres
.planes
));
650 rb
->write(fd
, &humanres
.tanks
, sizeof(humanres
.tanks
));
651 rb
->write(fd
, &humanres
.men
, sizeof(humanres
.men
));
652 rb
->write(fd
, &humanres
.nukes
, sizeof(humanres
.nukes
));
653 rb
->write(fd
, &humanres
.inds
, sizeof(humanres
.inds
));
654 rb
->write(fd
, &humanres
.farms
, sizeof(humanres
.farms
));
655 rb
->write(fd
, &humanres
.moves
, sizeof(humanres
.moves
));
656 rb
->write(fd
, &compres
.cash
, sizeof(compres
.cash
));
657 rb
->write(fd
, &compres
.food
, sizeof(compres
.food
));
658 rb
->write(fd
, &compres
.bank
, sizeof(compres
.bank
));
659 rb
->write(fd
, &compres
.planes
, sizeof(compres
.planes
));
660 rb
->write(fd
, &compres
.tanks
, sizeof(compres
.tanks
));
661 rb
->write(fd
, &compres
.men
, sizeof(compres
.men
));
662 rb
->write(fd
, &compres
.nukes
, sizeof(compres
.nukes
));
663 rb
->write(fd
, &compres
.inds
, sizeof(compres
.inds
));
664 rb
->write(fd
, &compres
.farms
, sizeof(compres
.farms
));
665 rb
->write(fd
, &compres
.moves
, sizeof(compres
.moves
));
666 rb
->write(fd
, board
, sizeof(board
));
667 rb
->write(fd
, &superdom_settings
.compstartfarms
, sizeof(int));
668 rb
->write(fd
, &superdom_settings
.compstartinds
, sizeof(int));
669 rb
->write(fd
, &superdom_settings
.humanstartfarms
, sizeof(int));
670 rb
->write(fd
, &superdom_settings
.humanstartinds
, sizeof(int));
671 rb
->write(fd
, &superdom_settings
.startcash
, sizeof(int));
672 rb
->write(fd
, &superdom_settings
.startfood
, sizeof(int));
673 rb
->write(fd
, &superdom_settings
.movesperturn
, sizeof(int));
678 int ingame_menu(void) {
679 MENUITEM_STRINGLIST(menu
, "Super Domination Menu", NULL
,
680 "Return to game", "Save Game",
681 "Playback Control", "Quit");
683 switch(rb
->do_menu(&menu
, NULL
, NULL
, false)) {
689 rb
->splash(HZ
, "Game saved");
691 rb
->splash(HZ
, "Error in save");
694 if(playback_control(NULL
))
698 return RET_VAL_QUIT_ERR
;
700 case MENU_ATTACHED_USB
:
710 int get_number(char* param
, int* value
, int max
) {
711 static const char *button_labels
[4][3] = {
719 int button
= 0, ret
= RET_VAL_OK
;
721 rb
->lcd_clear_display();
722 rb
->lcd_getstringsize("CLR", &width
, &height
);
723 if(width
> NUM_BOX_WIDTH
|| height
> NUM_BOX_HEIGHT
)
724 rb
->lcd_setfont(FONT_SYSFIXED
);
725 /* Draw a 3x4 grid */
726 for(i
=0;i
<=3;i
++) { /* Vertical lines */
727 rb
->lcd_vline(NUM_MARGIN_X
+(NUM_BOX_WIDTH
*i
), NUM_MARGIN_Y
,
728 NUM_MARGIN_Y
+(4*NUM_BOX_HEIGHT
));
730 for(i
=0;i
<=4;i
++) { /* Horizontal lines */
731 rb
->lcd_hline(NUM_MARGIN_X
, NUM_MARGIN_X
+(3*NUM_BOX_WIDTH
),
732 NUM_MARGIN_Y
+(NUM_BOX_HEIGHT
*i
));
736 rb
->lcd_getstringsize(button_labels
[i
][j
], &width
, &height
);
738 NUM_MARGIN_X
+(j
*NUM_BOX_WIDTH
)+NUM_BOX_WIDTH
/2-width
/2,
739 NUM_MARGIN_Y
+(i
*NUM_BOX_HEIGHT
)+NUM_BOX_HEIGHT
/2-height
/2,
740 button_labels
[i
][j
]);
743 rb
->snprintf(buf
,sizeof(buf
), "%d", *value
);
744 rb
->lcd_putsxy(NUM_MARGIN_X
+10, NUM_MARGIN_Y
+4*NUM_BOX_HEIGHT
+10, buf
);
745 rb
->lcd_getstringsize(param
, &width
, &height
);
746 if(width
< LCD_WIDTH
)
747 rb
->lcd_putsxy((LCD_WIDTH
-width
)/2, (NUM_MARGIN_Y
-height
)/2, param
);
749 rb
->lcd_puts_scroll(0, (NUM_MARGIN_Y
/height
-1)/2, param
);
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
);
757 button
= rb
->button_get(true);
758 rb
->lcd_set_drawmode(DRMODE_COMPLEMENT
);
759 rb
->lcd_fillrect(NUM_MARGIN_X
+(NUM_BOX_WIDTH
*x
),
760 NUM_MARGIN_Y
+(NUM_BOX_HEIGHT
*y
),
761 NUM_BOX_WIDTH
+1, NUM_BOX_HEIGHT
+1);
762 rb
->lcd_set_drawmode(DRMODE_SOLID
);
767 *value
+= button_labels
[y
][x
][0] - '0';
776 if ((unsigned) *value
> (unsigned) max
)
778 rb
->lcd_set_drawmode(DRMODE_BG
|DRMODE_INVERSEVID
);
779 rb
->lcd_fillrect(0, NUM_MARGIN_Y
+4*NUM_BOX_HEIGHT
+10,
781 rb
->lcd_set_drawmode(DRMODE_SOLID
);
782 rb
->snprintf(buf
,sizeof(buf
), "%d", *value
);
783 rb
->lcd_putsxy(NUM_MARGIN_X
+10,
784 NUM_MARGIN_Y
+4*NUM_BOX_HEIGHT
+10, buf
);
786 case SUPERDOM_CANCEL
:
789 ret
= RET_VAL_QUIT_ERR
;
791 #if CONFIG_KEYPAD != IRIVER_H10_PAD
822 #if CONFIG_KEYPAD == IRIVER_H10_PAD
835 #if CONFIG_KEYPAD == IRIVER_H10_PAD
848 if (rb
->default_event_handler(button
) == SYS_USB_CONNECTED
)
855 rb
->lcd_set_drawmode(DRMODE_COMPLEMENT
);
856 rb
->lcd_fillrect(NUM_MARGIN_X
+(NUM_BOX_WIDTH
*x
),
857 NUM_MARGIN_Y
+(NUM_BOX_HEIGHT
*y
),
858 NUM_BOX_WIDTH
+1, NUM_BOX_HEIGHT
+1);
859 rb
->lcd_set_drawmode(DRMODE_SOLID
);
862 rb
->lcd_setfont(FONT_UI
);
863 rb
->lcd_stop_scroll();
864 if (ret
== RET_VAL_QUIT_ERR
)
865 rb
->splash(HZ
, "Cancelled");
869 bool tile_has_item(int type
, int x
, int y
) {
872 return (board
[x
][y
].men
> 0);
875 return board
[x
][y
].tank
;
878 return board
[x
][y
].plane
;
881 return board
[x
][y
].farm
;
884 return board
[x
][y
].ind
;
887 return board
[x
][y
].nuke
;
893 int buy_resources(int colour
, int type
, int x
, int y
, int nummen
) {
894 const char *itemnames
[][6] = {
900 "the industrial plant",
907 "build an industrial plant",
914 "an industrial plant",
919 bool human
= (colour
== COLOUR_LIGHT
);
922 struct resources
*res
;
942 case 4: /* Factory */
949 if(res
->cash
< price
) {
951 rb
->splash(HZ
, "Not enough money!");
952 return RET_VAL_QUIT_ERR
;
955 rb
->splashf(HZ
, "Where do you want to place %s?", itemnames
[0][type
]);
956 if((temp
= select_square()) != RET_VAL_OK
)
961 if(board
[x
][y
].colour
!= colour
) {
963 rb
->splashf(HZ
, "Can't %s on enemy territory", itemnames
[1][type
]);
964 return RET_VAL_QUIT_ERR
;
966 if(type
!= 0 && tile_has_item(type
, x
, y
)) {
968 rb
->splashf(HZ
, "There is already %s there", itemnames
[2][type
]);
969 return RET_VAL_QUIT_ERR
;
973 board
[x
][y
].men
+= nummen
;
977 board
[x
][y
].tank
= true;
981 board
[x
][y
].plane
= true;
985 board
[x
][y
].farm
= true;
989 board
[x
][y
].ind
= true;
993 board
[x
][y
].nuke
= true;
1005 int buy_resources_menu(void) {
1006 int selection
= 0,nummen
;
1008 MENUITEM_STRINGLIST(menu
, "Buy Resources", NULL
,
1009 "Buy men ($1)", "Buy tank ($300)", "Buy plane ($600)",
1010 "Buy Farm ($1150)", "Buy Factory ($1300)",
1015 switch(rb
->do_menu(&menu
, &selection
, NULL
, false)) {
1018 if(get_number("How many men would you like?", &nummen
,
1019 humanres
.cash
) == RET_VAL_USB
)
1029 if(buy_resources(COLOUR_LIGHT
, selection
, 0, 0, nummen
)
1036 case MENU_ATTACHED_USB
:
1039 case GO_TO_PREVIOUS
:
1047 int move_unit(int colour
, int type
, int fromx
, int fromy
,
1048 int tox
, int toy
, int nummen
) {
1049 const char *itemnames
[][3] = {
1064 bool human
= (colour
== COLOUR_LIGHT
);
1068 rb
->splashf(HZ
, "Select where you want to move %s from",
1069 itemnames
[0][type
]);
1070 if((temp
= select_square()) != RET_VAL_OK
)
1075 if(board
[fromx
][fromy
].colour
!= colour
) {
1077 rb
->splash(HZ
, "That isn't your territory");
1078 return RET_VAL_QUIT_ERR
;
1080 if(!tile_has_item(type
, fromx
, fromy
)) {
1082 rb
->splashf(HZ
, "You don't have %s there", itemnames
[1][type
]);
1083 return RET_VAL_QUIT_ERR
;
1087 nummen
= board
[fromx
][fromy
].men
;
1088 if((temp
= get_number("How many men do you want to move?", &nummen
,
1089 nummen
)) != RET_VAL_OK
)
1092 if(nummen
> board
[fromx
][fromy
].men
) {
1094 rb
->splash(HZ
, "You don't have that many troops.");
1095 return RET_VAL_QUIT_ERR
;
1099 rb
->splashf(HZ
, "Select where you want to move %s to",
1100 itemnames
[2][type
]);
1101 if((temp
= select_square()) != RET_VAL_OK
)
1106 if((tox
== fromx
&& toy
== fromy
) ||
1107 board
[tox
][toy
].colour
!= colour
||
1108 (type
!= 2 && (abs(tox
- fromx
) > 1 || abs(toy
- fromy
) > 1))) {
1110 rb
->splash(HZ
, "Invalid move");
1111 return RET_VAL_QUIT_ERR
;
1113 if(type
!= 0 && tile_has_item(type
, tox
, toy
)) {
1115 rb
->splashf(HZ
, "There is already %s there", itemnames
[1][type
]);
1116 return RET_VAL_QUIT_ERR
;
1120 board
[fromx
][fromy
].men
-= nummen
;
1121 board
[tox
][toy
].men
+= nummen
;
1124 board
[fromx
][fromy
].tank
= false;
1125 board
[tox
][toy
].tank
= true;
1128 board
[fromx
][fromy
].plane
= false;
1129 board
[tox
][toy
].plane
= true;
1135 int move_unit_menu(void) {
1138 MENUITEM_STRINGLIST(menu
, "Move unit", NULL
,
1139 "Move men", "Move tank", "Move plane");
1140 switch(rb
->do_menu(&menu
, &selection
, NULL
, false)) {
1144 switch(move_unit(COLOUR_LIGHT
, selection
, 0, 0, 0, 0, 0)) {
1153 case MENU_ATTACHED_USB
:
1159 int launch_nuke(int colour
, int nukex
, int nukey
, int targetx
, int targety
) {
1160 bool human
= (colour
== COLOUR_LIGHT
);
1162 struct resources
*res
;
1164 if(board
[nukex
][nukey
].colour
!= colour
) {
1166 rb
->splash(HZ
, "That isn't your territory");
1167 return RET_VAL_QUIT_ERR
;
1169 if(! board
[nukex
][nukey
].nuke
) {
1171 rb
->splashf(HZ
, "You don't have %s there", "a nuke");
1172 return RET_VAL_QUIT_ERR
;
1175 rb
->splash(HZ
, "Select place to target with nuke");
1176 if((temp
= select_square()) != RET_VAL_OK
)
1186 board
[nukex
][nukey
].nuke
= false;
1188 if(board
[targetx
][targety
].colour
== COLOUR_LIGHT
) {
1193 res
->men
-= board
[targetx
][targety
].men
;
1194 res
->tanks
-= board
[targetx
][targety
].tank
;
1195 res
->planes
-= board
[targetx
][targety
].plane
;
1196 res
->nukes
-= board
[targetx
][targety
].nuke
;
1197 res
->farms
-= board
[targetx
][targety
].farm
;
1198 res
->inds
-= board
[targetx
][targety
].ind
;
1199 board
[targetx
][targety
].men
= 0;
1200 board
[targetx
][targety
].tank
= false;
1201 board
[targetx
][targety
].plane
= false;
1202 board
[targetx
][targety
].ind
= false;
1203 board
[targetx
][targety
].nuke
= false;
1204 board
[targetx
][targety
].farm
= false;
1205 /* TODO: Fallout carried by wind */
1210 int movement_menu(void) {
1211 int selection
= 0, temp
;
1213 MENUITEM_STRINGLIST(menu
, "Movement", NULL
,
1214 "Move unit", "Buy additional moves ($100)",
1215 "Launch nuclear missile", "Check map",
1216 "Finish moving", "Game menu");
1219 switch(rb
->do_menu(&menu
, &selection
, NULL
, false)) {
1221 if(humanres
.moves
) {
1222 if(move_unit_menu()==RET_VAL_USB
)
1225 rb
->splash(HZ
, "You have no more moves left."
1226 " You can buy more for $100 each.");
1230 if(humanres
.cash
> 100) {
1232 humanres
.cash
-= 100;
1233 rb
->snprintf(buf
, sizeof(buf
), "You now have %d moves",
1235 rb
->splash(HZ
, buf
);
1239 if(humanres
.nukes
==0) {
1240 rb
->splash(HZ
, "You do not have any nukes to launch");
1242 rb
->splash(HZ
, "Select place to launch nuke from");
1243 switch(select_square()) {
1245 if(launch_nuke(COLOUR_LIGHT
, cursor
.x
, cursor
.y
,
1246 0, 0) == RET_VAL_USB
)
1256 if(select_square() == RET_VAL_USB
)
1263 if((temp
= ingame_menu()) != RET_VAL_OK
)
1266 case MENU_ATTACHED_USB
:
1274 static const char* inventory_data(int selected_item
, void * data
,
1275 char * buffer
, size_t buffer_len
) {
1277 switch(selected_item
) {
1279 rb
->snprintf(buffer
,buffer_len
,"Men: %d", humanres
.men
);
1282 rb
->snprintf(buffer
,buffer_len
,"Tanks: %d", humanres
.tanks
);
1285 rb
->snprintf(buffer
,buffer_len
,"Planes: %d", humanres
.planes
);
1288 rb
->snprintf(buffer
,buffer_len
,"Factories: %d", humanres
.inds
);
1291 rb
->snprintf(buffer
,buffer_len
,"Farms: %d", humanres
.farms
);
1294 rb
->snprintf(buffer
,buffer_len
,"Nukes: %d", humanres
.nukes
);
1297 rb
->snprintf(buffer
,buffer_len
,"Cash: %d", humanres
.cash
);
1300 rb
->snprintf(buffer
,buffer_len
,"Food: %d", humanres
.food
);
1303 rb
->snprintf(buffer
,buffer_len
,"Bank: %d", humanres
.bank
);
1311 int show_inventory(void) {
1312 struct simplelist_info info
;
1313 rb
->simplelist_info_init(&info
, "Inventory", 9, NULL
);
1314 info
.hide_selection
= true;
1315 info
.get_name
= inventory_data
;
1316 if(rb
->simplelist_show_list(&info
)) {
1323 int production_menu(void) {
1324 int selection
= 0, temp
;
1326 MENUITEM_STRINGLIST(menu
, "Production", NULL
,
1327 "Buy resources", "Show inventory", "Check map",
1328 "Invest money", "Withdraw money",
1329 "Finish turn", "Game menu");
1332 switch(rb
->do_menu(&menu
, &selection
, NULL
, false)) {
1334 if(buy_resources_menu() == RET_VAL_USB
)
1338 if(show_inventory() == RET_VAL_USB
)
1342 if(select_square() == RET_VAL_USB
)
1346 temp
= humanres
.cash
;
1347 if(get_number("How much do you want to invest?", &temp
,
1348 humanres
.cash
) == RET_VAL_USB
)
1350 if(temp
> humanres
.cash
) {
1351 rb
->splash(HZ
, "You don't have that much cash to invest");
1353 humanres
.cash
-= temp
;
1354 humanres
.bank
+= temp
;
1358 temp
= humanres
.bank
;
1359 if(get_number("How much do you want to withdraw?", &temp
,
1360 humanres
.bank
) == RET_VAL_USB
)
1362 if(temp
> humanres
.bank
) {
1363 rb
->splash(HZ
, "You don't have that much cash to withdraw");
1365 humanres
.cash
+= temp
;
1366 humanres
.bank
-= temp
;
1373 if((temp
= ingame_menu()) != RET_VAL_OK
)
1376 case MENU_ATTACHED_USB
:
1384 void init_resources(void) {
1385 humanres
.cash
= superdom_settings
.startcash
;
1386 humanres
.food
= superdom_settings
.startfood
;
1388 humanres
.planes
= 0;
1395 compres
.cash
= superdom_settings
.startcash
;
1396 compres
.food
= superdom_settings
.startfood
;
1407 int select_square(void) {
1412 #if LCD_WIDTH >= 220
1413 rb
->lcd_setfont(FONT_SYSFIXED
);
1414 rb
->snprintf(buf
, sizeof(buf
), "Cash: %d", humanres
.cash
);
1415 rb
->lcd_putsxy(125, LCD_HEIGHT
-20, buf
);
1416 rb
->snprintf(buf
, sizeof(buf
), "Food: %d", humanres
.food
);
1417 rb
->lcd_putsxy(125, LCD_HEIGHT
-10, buf
);
1418 rb
->lcd_setfont(FONT_UI
);
1422 button
= rb
->button_get(true);
1424 case SUPERDOM_CANCEL
:
1425 rb
->splash(HZ
, "Cancelled");
1426 return RET_VAL_QUIT_ERR
;
1431 #if CONFIG_KEYPAD != IRIVER_H10_PAD
1433 case (SUPERDOM_LEFT
|BUTTON_REPEAT
):
1434 draw_cursor(); /* Deselect the current tile */
1449 case SUPERDOM_RIGHT
:
1450 case (SUPERDOM_RIGHT
|BUTTON_REPEAT
):
1451 draw_cursor(); /* Deselect the current tile */
1469 case (SUPERDOM_UP
|BUTTON_REPEAT
):
1470 draw_cursor(); /* Deselect the current tile */
1474 #if CONFIG_KEYPAD == IRIVER_H10_PAD
1486 case (SUPERDOM_DOWN
|BUTTON_REPEAT
):
1487 draw_cursor(); /* Deselect the current tile */
1491 #if CONFIG_KEYPAD == IRIVER_H10_PAD
1504 if (rb
->default_event_handler(button
) == SYS_USB_CONNECTED
)
1512 int killmen(int colour
) {
1513 bool human
= (colour
== COLOUR_LIGHT
);
1517 percent
= (humanres
.food
*1000)/humanres
.men
;
1520 percent
= (compres
.food
*1000)/compres
.men
;
1526 if(board
[i
][j
].colour
== colour
) {
1527 int nummen
= ((board
[i
][j
].men
* percent
)/1000);
1528 menkilled
+= board
[i
][j
].men
- nummen
;
1529 board
[i
][j
].men
= nummen
;
1535 humanres
.men
-= menkilled
;
1537 compres
.men
-= menkilled
;
1541 /* return -1 if error, 1 if attack is succeeded, 0 otherwise */
1542 int attack_territory(int colour
, int x
, int y
) {
1543 bool human
= (colour
== COLOUR_LIGHT
);
1546 if(board
[x
][y
].colour
== colour
) {
1548 rb
->splash(HZ
, "You can't attack your own territory");
1551 str_diff
= calc_strength(COLOUR_DARK
, x
, y
) -
1552 calc_strength(COLOUR_LIGHT
, x
, y
);
1554 str_diff
= -str_diff
;
1556 rb
->srand(*rb
->current_tick
);
1557 if(str_diff
> 0 || (str_diff
== 0 && rb
->rand()%2)) {
1558 struct resources
*offres
, *defres
;
1566 defres
->men
-= board
[x
][y
].men
;
1567 defres
->tanks
-= board
[x
][y
].tank
;
1568 defres
->planes
-= board
[x
][y
].plane
;
1569 defres
->nukes
-= board
[x
][y
].nuke
;
1570 defres
->farms
-= board
[x
][y
].farm
;
1571 defres
->inds
-= board
[x
][y
].ind
;
1572 offres
->farms
+= board
[x
][y
].farm
;
1573 offres
->inds
+= board
[x
][y
].ind
;
1574 board
[x
][y
].colour
= colour
;
1575 board
[x
][y
].men
= 0;
1576 board
[x
][y
].tank
= false;
1577 board
[x
][y
].plane
= false;
1578 board
[x
][y
].nuke
= false;
1587 rb
->splash(HZ
, "Your troops were unable to overcome"
1588 " the enemy troops");
1590 rb
->splash(HZ
*2, "The computer attempted to "
1591 "attack, but the invasion was"
1598 int war_menu(void) {
1599 int selection
= 0, temp
;
1601 MENUITEM_STRINGLIST(menu
, "War!", NULL
,
1602 "Select territory to attack",
1603 "Finish turn", "Game menu");
1605 while(humanres
.moves
) {
1606 switch(rb
->do_menu(&menu
, &selection
, NULL
, false)) {
1608 switch(select_square()) {
1610 if(attack_territory(COLOUR_LIGHT
, cursor
.x
, cursor
.y
)
1623 if((temp
= ingame_menu()) != RET_VAL_OK
)
1637 bool place_adjacent(bool tank
, int x
, int y
) {
1638 int type
= (tank
? 1: 2);
1639 if(!buy_resources(COLOUR_DARK
, type
, x
, y
, 0)) {
1642 if(!buy_resources(COLOUR_DARK
, type
, x
-1, y
, 0)) {
1645 if(!buy_resources(COLOUR_DARK
, type
, x
+1, y
, 0)) {
1648 if(!buy_resources(COLOUR_DARK
, type
, x
, y
-1, 0)) {
1651 if(!buy_resources(COLOUR_DARK
, type
, x
, y
+1, 0)) {
1657 bool has_adjacent(int x
, int y
) {
1658 if((board
[x
][y
].colour
== COLOUR_LIGHT
) &&
1659 ((board
[x
-1][y
].colour
== COLOUR_DARK
) ||
1660 (board
[x
+1][y
].colour
== COLOUR_DARK
) ||
1661 (board
[x
][y
+1].colour
== COLOUR_DARK
) ||
1662 (board
[x
][y
-1].colour
== COLOUR_DARK
)))
1668 void find_adjacent(int x
, int y
, int* adj_x
, int* adj_y
) {
1669 /* Finds adjacent squares, returning squares without tanks on them
1670 * in preference to those with them */
1671 if(board
[x
-1][y
].colour
== COLOUR_DARK
) {
1676 if(board
[x
+1][y
].colour
== COLOUR_DARK
) {
1681 if(board
[x
][y
-1].colour
== COLOUR_DARK
) {
1686 if(board
[x
][y
+1].colour
== COLOUR_DARK
) {
1693 void computer_allocate(void) {
1694 /* Firstly, decide whether to go offensive or defensive.
1695 * This is primarily decided by the human player posing a threat to either
1696 * the computer's farms or factories */
1698 bool offensive
= true;
1699 struct threat threats
[4];
1701 int total_str_diff
= 0;
1702 int numterritory
= 0;
1705 struct threat targets
[2];
1709 compres
.cash
+= compres
.bank
;
1713 if(board
[i
][j
].colour
== COLOUR_DARK
) {
1715 str_diff
= calc_strength(COLOUR_LIGHT
,i
,j
) -
1716 calc_strength(COLOUR_DARK
,i
,j
);
1717 if(str_diff
> 0 && (board
[i
][j
].ind
|| board
[i
][j
].farm
)) {
1718 if(numthreats
< 3) {
1720 threats
[numthreats
].x
= i
;
1721 threats
[numthreats
].y
= j
;
1722 threats
[numthreats
].str_diff
= str_diff
;
1731 /* The AI is going to go straight for the throat here and attack
1732 * the player's farms and factories. The amount of cash
1733 * the AI has to spend will determine how many targets there are */
1734 if(compres
.cash
> 1200) {
1735 /* 1200 is a figure I pulled out of nowhere. Adjust as needed */
1740 /* Work out which target(s) to attack. They must have adjacent squares
1741 * owned by the computer. If none are found just place troops in
1742 * random places around the map until we run out of money */
1746 if(has_adjacent(i
,j
) &&
1747 (board
[i
][j
].ind
|| board
[i
][j
].farm
)) {
1751 targets
[k
].str_diff
=
1752 calc_strength(COLOUR_LIGHT
, i
, j
) -
1753 calc_strength(COLOUR_DARK
, i
, j
);
1761 /* No targets found! Randomly pick squares and if they're owned
1762 * by the computer then stick a tank on it. */
1763 rb
->srand(*rb
->current_tick
);
1764 while(compres
.cash
>= 300 && compres
.tanks
< numterritory
) {
1765 i
= rb
->rand()%10 + 1;
1766 j
= rb
->rand()%10 + 1;
1767 if(board
[i
][j
].colour
== COLOUR_DARK
) {
1768 buy_resources(COLOUR_DARK
, 1, i
, j
, 0);
1774 str_diff
= targets
[i
].str_diff
;
1775 while(str_diff
+ 20 > 0 && compres
.cash
> 0) {
1776 /* While we still need them keep placing men */
1777 if(!place_adjacent(true, targets
[i
].x
, targets
[i
].y
)) {
1778 find_adjacent(targets
[i
].x
, targets
[i
].y
,
1780 men_needed
= (str_diff
+ 20)*1000/133;
1781 if(compres
.cash
< men_needed
) {
1782 men_needed
= compres
.cash
;
1784 buy_resources(COLOUR_DARK
, 0, adj
.x
, adj
.y
,
1788 str_diff
= calc_strength(COLOUR_LIGHT
,
1789 targets
[i
].x
, targets
[i
].y
) -
1790 calc_strength(COLOUR_DARK
,
1791 targets
[i
].x
, targets
[i
].y
);
1796 /* Work out what to place on each square to defend it.
1797 * Tanks are preferential because they do not require food,
1798 * but if the budget is tight then we fall back onto troops.
1799 * Conversely if cash is not an issue and there are already tanks in
1800 * place planes will be deployed. We would like a margin of at least
1801 * 20 points to be safe. */
1803 for(i
=0;i
<numthreats
;i
++) {
1804 total_str_diff
+= threats
[i
].str_diff
;
1806 if((total_str_diff
+20)*10 > compres
.cash
) {
1807 /* Not enough cash to accomodate all threats using tanks alone -
1808 * use men as a backup */
1809 for(i
=0;i
<numthreats
;i
++) {
1810 men_needed
= ((threats
[i
].str_diff
+ 20)*1000)/133;
1811 if(compres
.cash
< men_needed
) {
1812 men_needed
= compres
.cash
;
1814 buy_resources(COLOUR_DARK
, 0, threats
[i
].x
, threats
[i
].y
,
1819 /* Enough money to pay their way by planes? */
1820 bool tank
= ((total_str_diff
+20)*15 >= compres
.cash
);
1821 for(i
=0;i
<numthreats
;i
++) {
1822 str_diff
= threats
[i
].str_diff
;
1823 while(str_diff
+ 20 > 0) {
1824 if(!place_adjacent(tank
, threats
[i
].x
, threats
[i
].y
)) {
1825 /* No room for any more planes or tanks, revert to
1827 find_adjacent(threats
[i
].x
, threats
[i
].y
,
1829 men_needed
= (str_diff
+ 20)*1000/133;
1830 if(compres
.cash
< men_needed
) {
1831 men_needed
= compres
.cash
;
1833 buy_resources(COLOUR_DARK
, 0, threats
[i
].x
,
1834 threats
[i
].y
, men_needed
);
1837 str_diff
= calc_strength(COLOUR_LIGHT
,
1838 threats
[i
].x
, threats
[i
].y
) -
1839 calc_strength(COLOUR_DARK
,
1840 threats
[i
].x
, threats
[i
].y
);
1845 compres
.bank
+= compres
.cash
;
1849 int find_adj_target(int x
, int y
, struct cursor
* adj
) {
1850 /* Find a square next to a computer's farm or factory owned by the player
1851 * that is vulnerable. Return 1 on success, 0 otherwise */
1852 if(board
[x
+1][y
].colour
== COLOUR_LIGHT
&&
1853 calc_strength(COLOUR_LIGHT
,x
+1,y
)<=calc_strength(COLOUR_DARK
,x
+1,y
)) {
1858 if(board
[x
-1][y
].colour
== COLOUR_LIGHT
&&
1859 calc_strength(COLOUR_LIGHT
,x
-1,y
)<=calc_strength(COLOUR_DARK
,x
-1,y
)) {
1864 if(board
[x
][y
+1].colour
== COLOUR_LIGHT
&&
1865 calc_strength(COLOUR_LIGHT
,x
,y
+1)<=calc_strength(COLOUR_DARK
,x
,y
+1)) {
1870 if(board
[x
][y
-1].colour
== COLOUR_LIGHT
&&
1871 calc_strength(COLOUR_LIGHT
,x
,y
-1)<=calc_strength(COLOUR_DARK
,x
,y
-1)) {
1879 void computer_war(void) {
1880 /* Work out where to attack - prioritise the defence of buildings */
1882 bool found_target
= true;
1885 while(found_target
) {
1886 found_target
= false;
1889 if((board
[i
][j
].colour
== COLOUR_DARK
) &&
1890 (board
[i
][j
].farm
|| board
[i
][j
].ind
) &&
1891 find_adj_target(i
, j
, &adj
)) {
1892 found_target
= true;
1893 if(attack_territory(COLOUR_DARK
, adj
.x
, adj
.y
) >= 0) {
1903 /* Defence stage done, move on to OFFENCE */
1904 found_target
= true;
1905 while(found_target
) {
1906 found_target
= false;
1909 if(board
[i
][j
].colour
== COLOUR_LIGHT
&&
1910 (board
[i
][j
].ind
|| board
[i
][j
].farm
) &&
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) {
1924 /* Spend leftover moves wherever attacking randomly */
1925 found_target
= true;
1926 while(found_target
) {
1927 found_target
= false;
1930 if(board
[i
][j
].colour
== COLOUR_LIGHT
&&
1931 (calc_strength(COLOUR_DARK
, i
, j
) >=
1932 calc_strength(COLOUR_LIGHT
, i
, j
))) {
1933 found_target
= true;
1934 if(attack_territory(COLOUR_DARK
, i
, j
) >= 0) {
1946 static int load_game(const char* file
) {
1949 fd
= rb
->open(file
, O_RDONLY
);
1951 DEBUGF("Couldn't open savegame\n");
1954 rb
->read(fd
, buf
, 5);
1955 if(rb
->strcmp(buf
, "SSGv3")) {
1956 rb
->splash(HZ
, "Invalid/incompatible savegame");
1959 rb
->read(fd
, &gamestate
, sizeof(gamestate
));
1960 rb
->read(fd
, &humanres
.cash
, sizeof(humanres
.cash
));
1961 rb
->read(fd
, &humanres
.food
, sizeof(humanres
.food
));
1962 rb
->read(fd
, &humanres
.bank
, sizeof(humanres
.bank
));
1963 rb
->read(fd
, &humanres
.planes
, sizeof(humanres
.planes
));
1964 rb
->read(fd
, &humanres
.tanks
, sizeof(humanres
.tanks
));
1965 rb
->read(fd
, &humanres
.men
, sizeof(humanres
.men
));
1966 rb
->read(fd
, &humanres
.nukes
, sizeof(humanres
.nukes
));
1967 rb
->read(fd
, &humanres
.inds
, sizeof(humanres
.inds
));
1968 rb
->read(fd
, &humanres
.farms
, sizeof(humanres
.farms
));
1969 rb
->read(fd
, &humanres
.moves
, sizeof(humanres
.moves
));
1970 rb
->read(fd
, &compres
.cash
, sizeof(humanres
.cash
));
1971 rb
->read(fd
, &compres
.food
, sizeof(humanres
.food
));
1972 rb
->read(fd
, &compres
.bank
, sizeof(humanres
.bank
));
1973 rb
->read(fd
, &compres
.planes
, sizeof(humanres
.planes
));
1974 rb
->read(fd
, &compres
.tanks
, sizeof(humanres
.tanks
));
1975 rb
->read(fd
, &compres
.men
, sizeof(humanres
.men
));
1976 rb
->read(fd
, &compres
.nukes
, sizeof(humanres
.nukes
));
1977 rb
->read(fd
, &compres
.inds
, sizeof(humanres
.inds
));
1978 rb
->read(fd
, &compres
.farms
, sizeof(humanres
.farms
));
1979 rb
->read(fd
, &compres
.moves
, sizeof(humanres
.moves
));
1980 rb
->read(fd
, board
, sizeof(board
));
1981 rb
->read(fd
, &superdom_settings
.compstartfarms
, sizeof(int));
1982 rb
->read(fd
, &superdom_settings
.compstartinds
, sizeof(int));
1983 rb
->read(fd
, &superdom_settings
.humanstartfarms
, sizeof(int));
1984 rb
->read(fd
, &superdom_settings
.humanstartinds
, sizeof(int));
1985 rb
->read(fd
, &superdom_settings
.startcash
, sizeof(int));
1986 rb
->read(fd
, &superdom_settings
.startfood
, sizeof(int));
1987 rb
->read(fd
, &superdom_settings
.movesperturn
, sizeof(int));
1992 void default_settings(void) {
1993 superdom_settings
.compstartfarms
= 1;
1994 superdom_settings
.compstartinds
= 1;
1995 superdom_settings
.humanstartfarms
= 2;
1996 superdom_settings
.humanstartinds
= 2;
1997 superdom_settings
.startcash
= 0;
1998 superdom_settings
.startfood
= 0;
1999 superdom_settings
.movesperturn
= 2;
2002 int average_strength(int colour
) {
2003 /* This function calculates the average strength of the given player,
2004 * used to determine when the computer wins or loses. */
2009 if(board
[i
][j
].colour
!= -1) {
2010 totalpower
+= calc_strength(colour
, i
, j
);
2014 return totalpower
/100;
2017 enum plugin_status
plugin_start(const void* parameter
)
2020 rb
->lcd_set_backdrop(NULL
);
2021 rb
->lcd_set_foreground(LCD_BLACK
);
2022 rb
->lcd_set_background(LCD_WHITE
);
2029 if(load_game(parameter
) != 0) {
2030 DEBUGF("Loading failed, generating new game\n");
2049 switch(start_menu()) {
2050 case RET_VAL_OK
: /* start playing */
2052 case RET_VAL_QUIT_ERR
: /* quit */
2056 return PLUGIN_USB_CONNECTED
;
2065 int avg_str_diff
= (average_strength(COLOUR_LIGHT
) -
2066 average_strength(COLOUR_DARK
));
2067 if(avg_str_diff
> 15) {
2068 rb
->splash(HZ
*4, "The computer has surrendered. You win.");
2071 if(-avg_str_diff
> 15) {
2072 rb
->splash(HZ
*4, "Your army have suffered terrible morale from"
2073 " the bleak prospects of winning. You lose.");
2079 gamestate
= GS_PROD
;
2080 switch(production_menu()) {
2082 return PLUGIN_USB_CONNECTED
;
2084 case RET_VAL_QUIT_ERR
:
2088 computer_allocate();
2091 humanres
.moves
= superdom_settings
.movesperturn
;
2093 gamestate
= GS_MOVE
;
2094 switch(movement_menu()) {
2096 return PLUGIN_USB_CONNECTED
;
2098 case RET_VAL_QUIT_ERR
:
2104 if(humanres
.food
> humanres
.men
) {
2105 rb
->snprintf(buf
, sizeof(buf
), "Your men ate %d units of food",
2107 humanres
.food
-= humanres
.men
;
2109 rb
->snprintf(buf
, sizeof(buf
), "There was not enough food"
2110 " to feed all your men, %d men have died of starvation",
2111 killmen(COLOUR_LIGHT
));
2113 rb
->splash(HZ
*2, buf
);
2116 if(compres
.food
> compres
.men
) {
2117 compres
.food
-= compres
.men
;
2119 rb
->snprintf(buf
, sizeof(buf
), "The computer does not have"
2120 " enough food to feed its men. %d have died of starvation",
2121 killmen(COLOUR_DARK
));
2122 rb
->splash(HZ
, buf
);
2126 humanres
.moves
= superdom_settings
.movesperturn
;
2129 switch(war_menu()) {
2131 return PLUGIN_USB_CONNECTED
;
2133 case RET_VAL_QUIT_ERR
:
2137 compres
.moves
= superdom_settings
.movesperturn
;