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
.humanstartfarms
) {
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 #define WORDS (sizeof help_text / sizeof (char*))
563 static char* help_text
[] = {
564 "Super", "domination", "is", "a", "turn", "based", "strategy", "game,",
565 "where", "the", "aim", "is", "to", "overpower", "the", "computer",
566 "player", "by", "taking", "their", "territory.", "",
567 "Each", "year", "you", "are", "allocated", "an", "amount", "of", "cash",
568 "and", "food,", "depending", "on", "how", "many", "farms", "and",
569 "factories", "you", "control.", "",
570 "Use", "this", "cash", "and", "food", "to", "buy", "and", "feed", "your",
571 "army.", "Each", "tile", "has", "a", "strength,", "calculated", "by",
572 "the", "ownership", "of", "adjacent", "tiles,", "and", "the", "type",
573 "and", "number", "of", "troops", "on", "them.",
576 if (display_text(WORDS
, help_text
, NULL
, NULL
))
579 button
= rb
->button_get(true);
580 if ( rb
->default_event_handler( button
) == SYS_USB_CONNECTED
)
582 } while( ( button
== BUTTON_NONE
)
583 || ( button
& (BUTTON_REL
|BUTTON_REPEAT
) ) );
588 int start_menu(void) {
591 MENUITEM_STRINGLIST(menu
, "Super Domination Menu", NULL
,
592 "Play Super Domination", "Settings",
593 "Help", "Playback Control", "Quit");
596 switch(rb
->do_menu(&menu
, &selection
, NULL
, false)) {
598 return RET_VAL_OK
; /* start playing */
601 if(settings_menu()==RET_VAL_USB
)
605 if(superdom_help()==RET_VAL_USB
)
609 if(playback_control(NULL
))
613 return RET_VAL_QUIT_ERR
;
617 return RET_VAL_QUIT_ERR
;
620 int save_game(void) {
622 char savepath
[MAX_PATH
];
624 rb
->snprintf(savepath
, sizeof(savepath
), "/Savegame.ssg");
625 if(rb
->kbd_input(savepath
, MAX_PATH
)) {
626 DEBUGF("Keyboard input failed\n");
630 fd
= rb
->open(savepath
, O_WRONLY
|O_CREAT
);
631 DEBUGF("savepath: %s\n", savepath
);
633 DEBUGF("Couldn't create/open file\n");
637 rb
->write(fd
, "SSGv3", 5);
638 rb
->write(fd
, &gamestate
, sizeof(gamestate
));
639 rb
->write(fd
, &humanres
.cash
, sizeof(humanres
.cash
));
640 rb
->write(fd
, &humanres
.food
, sizeof(humanres
.food
));
641 rb
->write(fd
, &humanres
.bank
, sizeof(humanres
.bank
));
642 rb
->write(fd
, &humanres
.planes
, sizeof(humanres
.planes
));
643 rb
->write(fd
, &humanres
.tanks
, sizeof(humanres
.tanks
));
644 rb
->write(fd
, &humanres
.men
, sizeof(humanres
.men
));
645 rb
->write(fd
, &humanres
.nukes
, sizeof(humanres
.nukes
));
646 rb
->write(fd
, &humanres
.inds
, sizeof(humanres
.inds
));
647 rb
->write(fd
, &humanres
.farms
, sizeof(humanres
.farms
));
648 rb
->write(fd
, &humanres
.moves
, sizeof(humanres
.moves
));
649 rb
->write(fd
, &compres
.cash
, sizeof(compres
.cash
));
650 rb
->write(fd
, &compres
.food
, sizeof(compres
.food
));
651 rb
->write(fd
, &compres
.bank
, sizeof(compres
.bank
));
652 rb
->write(fd
, &compres
.planes
, sizeof(compres
.planes
));
653 rb
->write(fd
, &compres
.tanks
, sizeof(compres
.tanks
));
654 rb
->write(fd
, &compres
.men
, sizeof(compres
.men
));
655 rb
->write(fd
, &compres
.nukes
, sizeof(compres
.nukes
));
656 rb
->write(fd
, &compres
.inds
, sizeof(compres
.inds
));
657 rb
->write(fd
, &compres
.farms
, sizeof(compres
.farms
));
658 rb
->write(fd
, &compres
.moves
, sizeof(compres
.moves
));
659 rb
->write(fd
, board
, sizeof(board
));
660 rb
->write(fd
, &superdom_settings
.compstartfarms
, sizeof(int));
661 rb
->write(fd
, &superdom_settings
.compstartinds
, sizeof(int));
662 rb
->write(fd
, &superdom_settings
.humanstartfarms
, sizeof(int));
663 rb
->write(fd
, &superdom_settings
.humanstartfarms
, sizeof(int));
664 rb
->write(fd
, &superdom_settings
.startcash
, sizeof(int));
665 rb
->write(fd
, &superdom_settings
.startfood
, sizeof(int));
666 rb
->write(fd
, &superdom_settings
.movesperturn
, sizeof(int));
671 int ingame_menu(void) {
672 MENUITEM_STRINGLIST(menu
, "Super Domination Menu", NULL
,
673 "Return to game", "Save Game",
674 "Playback Control", "Quit");
676 switch(rb
->do_menu(&menu
, NULL
, NULL
, false)) {
682 rb
->splash(HZ
, "Game saved");
684 rb
->splash(HZ
, "Error in save");
687 if(playback_control(NULL
))
691 return RET_VAL_QUIT_ERR
;
693 case MENU_ATTACHED_USB
:
703 int get_number(char* param
, int* value
) {
704 static const char *button_labels
[4][3] = {
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';
765 rb
->lcd_setfont(FONT_UI
);
768 rb
->lcd_set_drawmode(DRMODE_BG
|DRMODE_INVERSEVID
);
769 rb
->lcd_fillrect(0, NUM_MARGIN_Y
+4*NUM_BOX_HEIGHT
+10,
771 rb
->lcd_set_drawmode(DRMODE_SOLID
);
772 rb
->snprintf(buf
,sizeof(buf
), "%d", *value
);
773 rb
->lcd_putsxy(NUM_MARGIN_X
+10,
774 NUM_MARGIN_Y
+4*NUM_BOX_HEIGHT
+10, buf
);
776 case SUPERDOM_CANCEL
:
778 rb
->lcd_setfont(FONT_UI
);
779 rb
->splash(HZ
, "Cancelled");
780 return RET_VAL_QUIT_ERR
;
782 #if CONFIG_KEYPAD != IRIVER_H10_PAD
813 #if CONFIG_KEYPAD == IRIVER_H10_PAD
826 #if CONFIG_KEYPAD == IRIVER_H10_PAD
839 if (rb
->default_event_handler(button
) == SYS_USB_CONNECTED
)
841 rb
->lcd_setfont(FONT_UI
);
846 rb
->lcd_set_drawmode(DRMODE_COMPLEMENT
);
847 rb
->lcd_fillrect(NUM_MARGIN_X
+(NUM_BOX_WIDTH
*x
),
848 NUM_MARGIN_Y
+(NUM_BOX_HEIGHT
*y
),
849 NUM_BOX_WIDTH
+1, NUM_BOX_HEIGHT
+1);
850 rb
->lcd_set_drawmode(DRMODE_SOLID
);
853 rb
->lcd_setfont(FONT_UI
);
857 bool tile_has_item(int type
, int x
, int y
) {
860 return (board
[x
][y
].men
> 0);
863 return board
[x
][y
].tank
;
866 return board
[x
][y
].plane
;
869 return board
[x
][y
].farm
;
872 return board
[x
][y
].ind
;
875 return board
[x
][y
].nuke
;
881 int buy_resources(int colour
, int type
, int x
, int y
, int nummen
) {
882 const char *itemnames
[][6] = {
888 "the industrial plant",
895 "build an industrial plant",
902 "an industrial plant",
907 bool human
= (colour
== COLOUR_LIGHT
);
910 struct resources
*res
;
930 case 4: /* Factory */
937 if(res
->cash
< price
) {
939 rb
->splash(HZ
, "Not enough money!");
940 return RET_VAL_QUIT_ERR
;
943 rb
->splashf(HZ
, "Where do you want to place %s?", itemnames
[0][type
]);
944 if((temp
= select_square()) != RET_VAL_OK
)
949 if(board
[x
][y
].colour
!= colour
) {
951 rb
->splashf(HZ
, "Can't %s on enemy territory", itemnames
[1][type
]);
952 return RET_VAL_QUIT_ERR
;
954 if(type
!= 0 && tile_has_item(type
, x
, y
)) {
956 rb
->splashf(HZ
, "There is already %s there", itemnames
[2][type
]);
957 return RET_VAL_QUIT_ERR
;
961 board
[x
][y
].men
+= nummen
;
965 board
[x
][y
].tank
= true;
969 board
[x
][y
].plane
= true;
973 board
[x
][y
].farm
= true;
977 board
[x
][y
].ind
= true;
981 board
[x
][y
].nuke
= true;
993 int buy_resources_menu(void) {
994 int selection
= 0,nummen
;
996 MENUITEM_STRINGLIST(menu
, "Buy Resources", NULL
,
997 "Buy men ($1)", "Buy tank ($300)", "Buy plane ($600)",
998 "Buy Farm ($1150)", "Buy Factory ($1300)",
1003 switch(rb
->do_menu(&menu
, &selection
, NULL
, false)) {
1006 if(get_number("How many men would you like?", &nummen
)
1017 if(buy_resources(COLOUR_LIGHT
, selection
, 0, 0, nummen
)
1024 case MENU_ATTACHED_USB
:
1027 case GO_TO_PREVIOUS
:
1035 int move_unit(int colour
, int type
, int fromx
, int fromy
,
1036 int tox
, int toy
, int nummen
) {
1037 const char *itemnames
[][3] = {
1052 bool human
= (colour
== COLOUR_LIGHT
);
1056 rb
->splashf(HZ
, "Select where you want to move %s from",
1057 itemnames
[0][type
]);
1058 if((temp
= select_square()) != RET_VAL_OK
)
1063 if(board
[fromx
][fromy
].colour
!= colour
) {
1065 rb
->splash(HZ
, "That isn't your territory");
1066 return RET_VAL_QUIT_ERR
;
1068 if(!tile_has_item(type
, fromx
, fromy
)) {
1070 rb
->splashf(HZ
, "You don't have %s there", itemnames
[1][type
]);
1071 return RET_VAL_QUIT_ERR
;
1075 nummen
= board
[fromx
][fromy
].men
;
1076 if((temp
= get_number("How many men do you want to move?", &nummen
))
1080 if(nummen
> board
[fromx
][fromy
].men
) {
1082 rb
->splash(HZ
, "You don't have that many troops.");
1083 return RET_VAL_QUIT_ERR
;
1087 rb
->splashf(HZ
, "Select where you want to move %s to",
1088 itemnames
[2][type
]);
1089 if((temp
= select_square()) != RET_VAL_OK
)
1094 if((tox
== fromx
&& toy
== fromy
) ||
1095 board
[tox
][toy
].colour
!= colour
||
1096 (type
!= 2 && (abs(tox
- fromx
) > 1 || abs(toy
- fromy
) > 1))) {
1098 rb
->splash(HZ
, "Invalid move");
1099 return RET_VAL_QUIT_ERR
;
1101 if(type
!= 0 && tile_has_item(type
, tox
, toy
)) {
1103 rb
->splashf(HZ
, "There is already %s there", itemnames
[1][type
]);
1104 return RET_VAL_QUIT_ERR
;
1108 board
[fromx
][fromy
].men
-= nummen
;
1109 board
[tox
][toy
].men
+= nummen
;
1112 board
[fromx
][fromy
].tank
= false;
1113 board
[tox
][toy
].tank
= true;
1116 board
[fromx
][fromy
].plane
= false;
1117 board
[tox
][toy
].plane
= true;
1123 int move_unit_menu(void) {
1126 MENUITEM_STRINGLIST(menu
, "Move unit", NULL
,
1127 "Move men", "Move tank", "Move plane");
1128 switch(rb
->do_menu(&menu
, &selection
, NULL
, false)) {
1132 switch(move_unit(COLOUR_LIGHT
, selection
, 0, 0, 0, 0, 0)) {
1141 case MENU_ATTACHED_USB
:
1147 int launch_nuke(int colour
, int nukex
, int nukey
, int targetx
, int targety
) {
1148 bool human
= (colour
== COLOUR_LIGHT
);
1150 struct resources
*res
;
1152 if(board
[nukex
][nukey
].colour
!= colour
) {
1154 rb
->splash(HZ
, "That isn't your territory");
1155 return RET_VAL_QUIT_ERR
;
1157 if(! board
[nukex
][nukey
].nuke
) {
1159 rb
->splashf(HZ
, "You don't have %s there", "a nuke");
1160 return RET_VAL_QUIT_ERR
;
1163 rb
->splash(HZ
, "Select place to target with nuke");
1164 if((temp
= select_square()) != RET_VAL_OK
)
1174 board
[nukex
][nukey
].nuke
= false;
1176 if(board
[targetx
][targety
].colour
== COLOUR_LIGHT
) {
1181 res
->men
-= board
[targetx
][targety
].men
;
1182 res
->tanks
-= board
[targetx
][targety
].tank
;
1183 res
->planes
-= board
[targetx
][targety
].plane
;
1184 res
->nukes
-= board
[targetx
][targety
].nuke
;
1185 res
->farms
-= board
[targetx
][targety
].farm
;
1186 res
->inds
-= board
[targetx
][targety
].ind
;
1187 board
[targetx
][targety
].men
= 0;
1188 board
[targetx
][targety
].tank
= false;
1189 board
[targetx
][targety
].plane
= false;
1190 board
[targetx
][targety
].ind
= false;
1191 board
[targetx
][targety
].nuke
= false;
1192 board
[targetx
][targety
].farm
= false;
1193 /* TODO: Fallout carried by wind */
1198 int movement_menu(void) {
1199 int selection
= 0, temp
;
1201 MENUITEM_STRINGLIST(menu
, "Movement", NULL
,
1202 "Move unit", "Buy additional moves ($100)",
1203 "Launch nuclear missile", "Check map",
1204 "Finish moving", "Game menu");
1207 switch(rb
->do_menu(&menu
, &selection
, NULL
, false)) {
1209 if(humanres
.moves
) {
1210 if(move_unit_menu()==RET_VAL_USB
)
1213 rb
->splash(HZ
, "You have no more moves left."
1214 " You can buy more for $100 each.");
1218 if(humanres
.cash
> 100) {
1220 humanres
.cash
-= 100;
1221 rb
->snprintf(buf
, sizeof(buf
), "You now have %d moves",
1223 rb
->splash(HZ
, buf
);
1227 if(humanres
.nukes
==0) {
1228 rb
->splash(HZ
, "You do not have any nukes to launch");
1230 rb
->splash(HZ
, "Select place to launch nuke from");
1231 switch(select_square()) {
1233 if(launch_nuke(COLOUR_LIGHT
, cursor
.x
, cursor
.y
,
1234 0, 0) == RET_VAL_USB
)
1244 if(select_square() == RET_VAL_USB
)
1251 if((temp
= ingame_menu()) != RET_VAL_OK
)
1254 case MENU_ATTACHED_USB
:
1262 static const char* inventory_data(int selected_item
, void * data
,
1263 char * buffer
, size_t buffer_len
) {
1265 switch(selected_item
) {
1267 rb
->snprintf(buffer
,buffer_len
,"Men: %d", humanres
.men
);
1270 rb
->snprintf(buffer
,buffer_len
,"Tanks: %d", humanres
.tanks
);
1273 rb
->snprintf(buffer
,buffer_len
,"Planes: %d", humanres
.planes
);
1276 rb
->snprintf(buffer
,buffer_len
,"Factories: %d", humanres
.inds
);
1279 rb
->snprintf(buffer
,buffer_len
,"Farms: %d", humanres
.farms
);
1282 rb
->snprintf(buffer
,buffer_len
,"Nukes: %d", humanres
.nukes
);
1285 rb
->snprintf(buffer
,buffer_len
,"Cash: %d", humanres
.cash
);
1288 rb
->snprintf(buffer
,buffer_len
,"Food: %d", humanres
.food
);
1291 rb
->snprintf(buffer
,buffer_len
,"Bank: %d", humanres
.bank
);
1299 int show_inventory(void) {
1300 struct simplelist_info info
;
1301 rb
->simplelist_info_init(&info
, "Inventory", 9, NULL
);
1302 info
.hide_selection
= true;
1303 info
.get_name
= inventory_data
;
1304 if(rb
->simplelist_show_list(&info
)) {
1311 int production_menu(void) {
1312 int selection
= 0, temp
;
1314 MENUITEM_STRINGLIST(menu
, "Production", NULL
,
1315 "Buy resources", "Show inventory", "Check map",
1316 "Invest money", "Withdraw money",
1317 "Finish turn", "Game menu");
1320 switch(rb
->do_menu(&menu
, &selection
, NULL
, false)) {
1322 if(buy_resources_menu() == RET_VAL_USB
)
1326 if(show_inventory() == RET_VAL_USB
)
1330 if(select_square() == RET_VAL_USB
)
1334 temp
= humanres
.cash
;
1335 if(get_number("How much do you want to invest?", &temp
)
1338 if(temp
> humanres
.cash
) {
1339 rb
->splash(HZ
, "You don't have that much cash to invest");
1341 humanres
.cash
-= temp
;
1342 humanres
.bank
+= temp
;
1346 temp
= humanres
.bank
;
1347 if(get_number("How much do you want to withdraw?", &temp
)
1350 if(temp
> humanres
.bank
) {
1351 rb
->splash(HZ
, "You don't have that much cash to withdraw");
1353 humanres
.cash
+= temp
;
1354 humanres
.bank
-= temp
;
1361 if((temp
= ingame_menu()) != RET_VAL_OK
)
1364 case MENU_ATTACHED_USB
:
1372 void init_resources(void) {
1373 humanres
.cash
= superdom_settings
.startcash
;
1374 humanres
.food
= superdom_settings
.startfood
;
1376 humanres
.planes
= 0;
1383 compres
.cash
= superdom_settings
.startcash
;
1384 compres
.food
= superdom_settings
.startfood
;
1395 int select_square(void) {
1400 #if LCD_WIDTH >= 220
1401 rb
->lcd_setfont(FONT_SYSFIXED
);
1402 rb
->snprintf(buf
, sizeof(buf
), "Cash: %d", humanres
.cash
);
1403 rb
->lcd_putsxy(125, LCD_HEIGHT
-20, buf
);
1404 rb
->snprintf(buf
, sizeof(buf
), "Food: %d", humanres
.food
);
1405 rb
->lcd_putsxy(125, LCD_HEIGHT
-10, buf
);
1406 rb
->lcd_setfont(FONT_UI
);
1410 button
= rb
->button_get(true);
1412 case SUPERDOM_CANCEL
:
1413 rb
->splash(HZ
, "Cancelled");
1414 return RET_VAL_QUIT_ERR
;
1419 #if CONFIG_KEYPAD != IRIVER_H10_PAD
1421 case (SUPERDOM_LEFT
|BUTTON_REPEAT
):
1422 draw_cursor(); /* Deselect the current tile */
1437 case SUPERDOM_RIGHT
:
1438 case (SUPERDOM_RIGHT
|BUTTON_REPEAT
):
1439 draw_cursor(); /* Deselect the current tile */
1457 case (SUPERDOM_UP
|BUTTON_REPEAT
):
1458 draw_cursor(); /* Deselect the current tile */
1462 #if CONFIG_KEYPAD == IRIVER_H10_PAD
1474 case (SUPERDOM_DOWN
|BUTTON_REPEAT
):
1475 draw_cursor(); /* Deselect the current tile */
1479 #if CONFIG_KEYPAD == IRIVER_H10_PAD
1492 if (rb
->default_event_handler(button
) == SYS_USB_CONNECTED
)
1500 int killmen(int colour
) {
1501 bool human
= (colour
== COLOUR_LIGHT
);
1505 percent
= (humanres
.food
*1000)/humanres
.men
;
1508 percent
= (compres
.food
*1000)/compres
.men
;
1514 if(board
[i
][j
].colour
== colour
) {
1515 int nummen
= ((board
[i
][j
].men
* percent
)/1000);
1516 menkilled
+= board
[i
][j
].men
- nummen
;
1517 board
[i
][j
].men
= nummen
;
1523 humanres
.men
-= menkilled
;
1525 compres
.men
-= menkilled
;
1529 /* return -1 if error, 1 if attack is succeeded, 0 otherwise */
1530 int attack_territory(int colour
, int x
, int y
) {
1531 bool human
= (colour
== COLOUR_LIGHT
);
1534 if(board
[x
][y
].colour
== colour
) {
1536 rb
->splash(HZ
, "You can't attack your own territory");
1539 str_diff
= calc_strength(COLOUR_DARK
, x
, y
) -
1540 calc_strength(COLOUR_LIGHT
, x
, y
);
1542 str_diff
= -str_diff
;
1544 rb
->srand(*rb
->current_tick
);
1545 if(str_diff
> 0 || (str_diff
== 0 && rb
->rand()%2)) {
1546 struct resources
*offres
, *defres
;
1554 defres
->men
-= board
[x
][y
].men
;
1555 defres
->tanks
-= board
[x
][y
].tank
;
1556 defres
->planes
-= board
[x
][y
].plane
;
1557 defres
->nukes
-= board
[x
][y
].nuke
;
1558 defres
->farms
-= board
[x
][y
].farm
;
1559 defres
->inds
-= board
[x
][y
].ind
;
1560 offres
->farms
+= board
[x
][y
].farm
;
1561 offres
->inds
+= board
[x
][y
].ind
;
1562 board
[x
][y
].colour
= colour
;
1563 board
[x
][y
].men
= 0;
1564 board
[x
][y
].tank
= false;
1565 board
[x
][y
].plane
= false;
1566 board
[x
][y
].nuke
= false;
1575 rb
->splash(HZ
, "Your troops were unable to overcome"
1576 " the enemy troops");
1578 rb
->splash(HZ
*2, "The computer attempted to "
1579 "attack, but the invasion was"
1586 int war_menu(void) {
1587 int selection
= 0, temp
;
1589 MENUITEM_STRINGLIST(menu
, "War!", NULL
,
1590 "Select territory to attack",
1591 "Finish turn", "Game menu");
1593 while(humanres
.moves
) {
1594 switch(rb
->do_menu(&menu
, &selection
, NULL
, false)) {
1596 switch(select_square()) {
1598 if(attack_territory(COLOUR_LIGHT
, cursor
.x
, cursor
.y
)
1611 if((temp
= ingame_menu()) != RET_VAL_OK
)
1625 bool place_adjacent(bool tank
, int x
, int y
) {
1626 int type
= (tank
? 1: 2);
1627 if(!buy_resources(COLOUR_DARK
, type
, x
, y
, 0)) {
1630 if(!buy_resources(COLOUR_DARK
, type
, x
-1, y
, 0)) {
1633 if(!buy_resources(COLOUR_DARK
, type
, x
+1, y
, 0)) {
1636 if(!buy_resources(COLOUR_DARK
, type
, x
, y
-1, 0)) {
1639 if(!buy_resources(COLOUR_DARK
, type
, x
, y
+1, 0)) {
1645 bool has_adjacent(int x
, int y
) {
1646 if((board
[x
][y
].colour
== COLOUR_LIGHT
) &&
1647 ((board
[x
-1][y
].colour
== COLOUR_DARK
) ||
1648 (board
[x
+1][y
].colour
== COLOUR_DARK
) ||
1649 (board
[x
][y
+1].colour
== COLOUR_DARK
) ||
1650 (board
[x
][y
-1].colour
== COLOUR_DARK
)))
1656 void find_adjacent(int x
, int y
, int* adj_x
, int* adj_y
) {
1657 /* Finds adjacent squares, returning squares without tanks on them
1658 * in preference to those with them */
1659 if(board
[x
-1][y
].colour
== COLOUR_DARK
) {
1664 if(board
[x
+1][y
].colour
== COLOUR_DARK
) {
1669 if(board
[x
][y
-1].colour
== COLOUR_DARK
) {
1674 if(board
[x
][y
+1].colour
== COLOUR_DARK
) {
1681 void computer_allocate(void) {
1682 /* Firstly, decide whether to go offensive or defensive.
1683 * This is primarily decided by the human player posing a threat to either
1684 * the computer's farms or factories */
1686 bool offensive
= true;
1687 struct threat threats
[4];
1689 int total_str_diff
= 0;
1690 int numterritory
= 0;
1693 struct threat targets
[2];
1697 compres
.cash
+= compres
.bank
;
1701 if(board
[i
][j
].colour
== COLOUR_DARK
) {
1703 str_diff
= calc_strength(COLOUR_LIGHT
,i
,j
) -
1704 calc_strength(COLOUR_DARK
,i
,j
);
1705 if(str_diff
> 0 && (board
[i
][j
].ind
|| board
[i
][j
].farm
)) {
1706 if(numthreats
< 3) {
1708 threats
[numthreats
].x
= i
;
1709 threats
[numthreats
].y
= j
;
1710 threats
[numthreats
].str_diff
= str_diff
;
1719 /* The AI is going to go straight for the throat here and attack
1720 * the player's farms and factories. The amount of cash
1721 * the AI has to spend will determine how many targets there are */
1722 if(compres
.cash
> 1200) {
1723 /* 1200 is a figure I pulled out of nowhere. Adjust as needed */
1728 /* Work out which target(s) to attack. They must have adjacent squares
1729 * owned by the computer. If none are found just place troops in
1730 * random places around the map until we run out of money */
1734 if(has_adjacent(i
,j
) &&
1735 (board
[i
][j
].ind
|| board
[i
][j
].farm
)) {
1739 targets
[k
].str_diff
=
1740 calc_strength(COLOUR_LIGHT
, i
, j
) -
1741 calc_strength(COLOUR_DARK
, i
, j
);
1749 /* No targets found! Randomly pick squares and if they're owned
1750 * by the computer then stick a tank on it. */
1751 rb
->srand(*rb
->current_tick
);
1752 while(compres
.cash
>= 300 && compres
.tanks
< numterritory
) {
1753 i
= rb
->rand()%10 + 1;
1754 j
= rb
->rand()%10 + 1;
1755 if(board
[i
][j
].colour
== COLOUR_DARK
) {
1756 buy_resources(COLOUR_DARK
, 1, i
, j
, 0);
1762 str_diff
= targets
[i
].str_diff
;
1763 while(str_diff
+ 20 > 0 && compres
.cash
> 0) {
1764 /* While we still need them keep placing men */
1765 if(!place_adjacent(true, targets
[i
].x
, targets
[i
].y
)) {
1766 find_adjacent(targets
[i
].x
, targets
[i
].y
,
1768 men_needed
= (str_diff
+ 20)*1000/133;
1769 if(compres
.cash
< men_needed
) {
1770 men_needed
= compres
.cash
;
1772 buy_resources(COLOUR_DARK
, 0, adj
.x
, adj
.y
,
1776 str_diff
= calc_strength(COLOUR_LIGHT
,
1777 targets
[i
].x
, targets
[i
].y
) -
1778 calc_strength(COLOUR_DARK
,
1779 targets
[i
].x
, targets
[i
].y
);
1784 /* Work out what to place on each square to defend it.
1785 * Tanks are preferential because they do not require food,
1786 * but if the budget is tight then we fall back onto troops.
1787 * Conversely if cash is not an issue and there are already tanks in
1788 * place planes will be deployed. We would like a margin of at least
1789 * 20 points to be safe. */
1791 for(i
=0;i
<numthreats
;i
++) {
1792 total_str_diff
+= threats
[i
].str_diff
;
1794 if((total_str_diff
+20)*10 > compres
.cash
) {
1795 /* Not enough cash to accomodate all threats using tanks alone -
1796 * use men as a backup */
1797 for(i
=0;i
<numthreats
;i
++) {
1798 men_needed
= ((threats
[i
].str_diff
+ 20)*1000)/133;
1799 if(compres
.cash
< men_needed
) {
1800 men_needed
= compres
.cash
;
1802 buy_resources(COLOUR_DARK
, 0, threats
[i
].x
, threats
[i
].y
,
1807 /* Enough money to pay their way by planes? */
1808 bool tank
= ((total_str_diff
+20)*15 >= compres
.cash
);
1809 for(i
=0;i
<numthreats
;i
++) {
1810 str_diff
= threats
[i
].str_diff
;
1811 while(str_diff
+ 20 > 0) {
1812 if(!place_adjacent(tank
, threats
[i
].x
, threats
[i
].y
)) {
1813 /* No room for any more planes or tanks, revert to
1815 find_adjacent(threats
[i
].x
, threats
[i
].y
,
1817 men_needed
= (str_diff
+ 20)*1000/133;
1818 if(compres
.cash
< men_needed
) {
1819 men_needed
= compres
.cash
;
1821 buy_resources(COLOUR_DARK
, 0, threats
[i
].x
,
1822 threats
[i
].y
, men_needed
);
1825 str_diff
= calc_strength(COLOUR_LIGHT
,
1826 threats
[i
].x
, threats
[i
].y
) -
1827 calc_strength(COLOUR_DARK
,
1828 threats
[i
].x
, threats
[i
].y
);
1833 compres
.bank
+= compres
.cash
;
1837 int find_adj_target(int x
, int y
, struct cursor
* adj
) {
1838 /* Find a square next to a computer's farm or factory owned by the player
1839 * that is vulnerable. Return 1 on success, 0 otherwise */
1840 if(board
[x
+1][y
].colour
== COLOUR_LIGHT
&&
1841 calc_strength(COLOUR_LIGHT
,x
+1,y
)<=calc_strength(COLOUR_DARK
,x
+1,y
)) {
1846 if(board
[x
-1][y
].colour
== COLOUR_LIGHT
&&
1847 calc_strength(COLOUR_LIGHT
,x
-1,y
)<=calc_strength(COLOUR_DARK
,x
-1,y
)) {
1852 if(board
[x
][y
+1].colour
== COLOUR_LIGHT
&&
1853 calc_strength(COLOUR_LIGHT
,x
,y
+1)<=calc_strength(COLOUR_DARK
,x
,y
+1)) {
1858 if(board
[x
][y
-1].colour
== COLOUR_LIGHT
&&
1859 calc_strength(COLOUR_LIGHT
,x
,y
-1)<=calc_strength(COLOUR_DARK
,x
,y
-1)) {
1867 void computer_war(void) {
1868 /* Work out where to attack - prioritise the defence of buildings */
1870 bool found_target
= true;
1873 while(found_target
) {
1874 found_target
= false;
1877 if((board
[i
][j
].colour
== COLOUR_DARK
) &&
1878 (board
[i
][j
].farm
|| board
[i
][j
].ind
) &&
1879 find_adj_target(i
, j
, &adj
)) {
1880 found_target
= true;
1881 if(attack_territory(COLOUR_DARK
, adj
.x
, adj
.y
) >= 0) {
1891 /* Defence stage done, move on to OFFENCE */
1892 found_target
= true;
1893 while(found_target
) {
1894 found_target
= false;
1897 if(board
[i
][j
].colour
== COLOUR_LIGHT
&&
1898 (board
[i
][j
].ind
|| board
[i
][j
].farm
) &&
1899 (calc_strength(COLOUR_DARK
, i
, j
) >=
1900 calc_strength(COLOUR_LIGHT
, i
, j
))) {
1901 found_target
= true;
1902 if(attack_territory(COLOUR_DARK
, i
, j
) >= 0) {
1912 /* Spend leftover moves wherever attacking randomly */
1913 found_target
= true;
1914 while(found_target
) {
1915 found_target
= false;
1918 if(board
[i
][j
].colour
== COLOUR_LIGHT
&&
1919 (calc_strength(COLOUR_DARK
, i
, j
) >=
1920 calc_strength(COLOUR_LIGHT
, i
, j
))) {
1921 found_target
= true;
1922 if(attack_territory(COLOUR_DARK
, i
, j
) >= 0) {
1934 static int load_game(const char* file
) {
1937 fd
= rb
->open(file
, O_RDONLY
);
1939 DEBUGF("Couldn't open savegame\n");
1942 rb
->read(fd
, buf
, 5);
1943 if(rb
->strcmp(buf
, "SSGv3")) {
1944 rb
->splash(HZ
, "Invalid/incompatible savegame");
1947 rb
->read(fd
, &gamestate
, sizeof(gamestate
));
1948 rb
->read(fd
, &humanres
.cash
, sizeof(humanres
.cash
));
1949 rb
->read(fd
, &humanres
.food
, sizeof(humanres
.food
));
1950 rb
->read(fd
, &humanres
.bank
, sizeof(humanres
.bank
));
1951 rb
->read(fd
, &humanres
.planes
, sizeof(humanres
.planes
));
1952 rb
->read(fd
, &humanres
.tanks
, sizeof(humanres
.tanks
));
1953 rb
->read(fd
, &humanres
.men
, sizeof(humanres
.men
));
1954 rb
->read(fd
, &humanres
.nukes
, sizeof(humanres
.nukes
));
1955 rb
->read(fd
, &humanres
.inds
, sizeof(humanres
.inds
));
1956 rb
->read(fd
, &humanres
.farms
, sizeof(humanres
.farms
));
1957 rb
->read(fd
, &humanres
.moves
, sizeof(humanres
.moves
));
1958 rb
->read(fd
, &compres
.cash
, sizeof(humanres
.cash
));
1959 rb
->read(fd
, &compres
.food
, sizeof(humanres
.food
));
1960 rb
->read(fd
, &compres
.bank
, sizeof(humanres
.bank
));
1961 rb
->read(fd
, &compres
.planes
, sizeof(humanres
.planes
));
1962 rb
->read(fd
, &compres
.tanks
, sizeof(humanres
.tanks
));
1963 rb
->read(fd
, &compres
.men
, sizeof(humanres
.men
));
1964 rb
->read(fd
, &compres
.nukes
, sizeof(humanres
.nukes
));
1965 rb
->read(fd
, &compres
.inds
, sizeof(humanres
.inds
));
1966 rb
->read(fd
, &compres
.farms
, sizeof(humanres
.farms
));
1967 rb
->read(fd
, &compres
.moves
, sizeof(humanres
.moves
));
1968 rb
->read(fd
, board
, sizeof(board
));
1969 rb
->read(fd
, &superdom_settings
.compstartfarms
, sizeof(int));
1970 rb
->read(fd
, &superdom_settings
.compstartinds
, sizeof(int));
1971 rb
->read(fd
, &superdom_settings
.humanstartfarms
, sizeof(int));
1972 rb
->read(fd
, &superdom_settings
.humanstartfarms
, sizeof(int));
1973 rb
->read(fd
, &superdom_settings
.startcash
, sizeof(int));
1974 rb
->read(fd
, &superdom_settings
.startfood
, sizeof(int));
1975 rb
->read(fd
, &superdom_settings
.movesperturn
, sizeof(int));
1980 void default_settings(void) {
1981 superdom_settings
.compstartfarms
= 1;
1982 superdom_settings
.compstartinds
= 1;
1983 superdom_settings
.humanstartfarms
= 2;
1984 superdom_settings
.humanstartinds
= 2;
1985 superdom_settings
.startcash
= 0;
1986 superdom_settings
.startfood
= 0;
1987 superdom_settings
.movesperturn
= 2;
1990 int average_strength(int colour
) {
1991 /* This function calculates the average strength of the given player,
1992 * used to determine when the computer wins or loses. */
1997 if(board
[i
][j
].colour
!= -1) {
1998 totalpower
+= calc_strength(colour
, i
, j
);
2002 return totalpower
/100;
2005 enum plugin_status
plugin_start(const void* parameter
)
2008 rb
->lcd_set_backdrop(NULL
);
2009 rb
->lcd_set_foreground(LCD_BLACK
);
2010 rb
->lcd_set_background(LCD_WHITE
);
2017 if(load_game(parameter
) != 0) {
2018 DEBUGF("Loading failed, generating new game\n");
2037 switch(start_menu()) {
2038 case RET_VAL_OK
: /* start playing */
2040 case RET_VAL_QUIT_ERR
: /* quit */
2044 return PLUGIN_USB_CONNECTED
;
2053 int avg_str_diff
= (average_strength(COLOUR_LIGHT
) -
2054 average_strength(COLOUR_DARK
));
2055 if(avg_str_diff
> 15) {
2056 rb
->splash(HZ
*4, "The computer has surrendered. You win.");
2059 if(-avg_str_diff
> 15) {
2060 rb
->splash(HZ
*4, "Your army have suffered terrible morale from"
2061 " the bleak prospects of winning. You lose.");
2067 gamestate
= GS_PROD
;
2068 switch(production_menu()) {
2070 return PLUGIN_USB_CONNECTED
;
2072 case RET_VAL_QUIT_ERR
:
2076 computer_allocate();
2079 humanres
.moves
= superdom_settings
.movesperturn
;
2081 gamestate
= GS_MOVE
;
2082 switch(movement_menu()) {
2084 return PLUGIN_USB_CONNECTED
;
2086 case RET_VAL_QUIT_ERR
:
2092 if(humanres
.food
> humanres
.men
) {
2093 rb
->snprintf(buf
, sizeof(buf
), "Your men ate %d units of food",
2095 humanres
.food
-= humanres
.men
;
2097 rb
->snprintf(buf
, sizeof(buf
), "There was not enough food"
2098 " to feed all your men, %d men have died of starvation",
2099 killmen(COLOUR_LIGHT
));
2101 rb
->splash(HZ
*2, buf
);
2104 if(compres
.food
> compres
.men
) {
2105 compres
.food
-= compres
.men
;
2107 rb
->snprintf(buf
, sizeof(buf
), "The computer does not have"
2108 " enough food to feed its men. %d have died of starvation",
2109 killmen(COLOUR_DARK
));
2110 rb
->splash(HZ
, buf
);
2114 humanres
.moves
= superdom_settings
.movesperturn
;
2117 switch(war_menu()) {
2119 return PLUGIN_USB_CONNECTED
;
2121 case RET_VAL_QUIT_ERR
:
2125 compres
.moves
= superdom_settings
.movesperturn
;