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_HDD6330_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 == PHILIPS_SA9200_PAD
151 #define SUPERDOM_OK BUTTON_PLAY
152 #define SUPERDOM_UP BUTTON_UP
153 #define SUPERDOM_DOWN BUTTON_DOWN
154 #define SUPERDOM_LEFT BUTTON_PREV
155 #define SUPERDOM_RIGHT BUTTON_NEXT
156 #define SUPERDOM_CANCEL BUTTON_LEFT
158 #elif (CONFIG_KEYPAD == ONDAVX747_PAD) || (CONFIG_KEYPAD == MROBE500_PAD)
159 #define SUPERDOM_CANCEL BUTTON_POWER
161 #elif CONFIG_KEYPAD == SAMSUNG_YH_PAD
162 #define SUPERDOM_OK BUTTON_PLAY
163 #define SUPERDOM_UP BUTTON_UP
164 #define SUPERDOM_DOWN BUTTON_DOWN
165 #define SUPERDOM_LEFT BUTTON_LEFT
166 #define SUPERDOM_RIGHT BUTTON_RIGHT
167 #define SUPERDOM_CANCEL BUTTON_REW
169 #elif CONFIG_KEYPAD == PBELL_VIBE500_PAD
170 #define SUPERDOM_OK BUTTON_OK
171 #define SUPERDOM_UP BUTTON_UP
172 #define SUPERDOM_DOWN BUTTON_DOWN
173 #define SUPERDOM_LEFT BUTTON_PREV
174 #define SUPERDOM_RIGHT BUTTON_NEXT
175 #define SUPERDOM_CANCEL BUTTON_CANCEL
177 #elif CONFIG_KEYPAD == MPIO_HD300_PAD
178 #define SUPERDOM_OK BUTTON_ENTER
179 #define SUPERDOM_UP BUTTON_UP
180 #define SUPERDOM_DOWN BUTTON_DOWN
181 #define SUPERDOM_LEFT BUTTON_REW
182 #define SUPERDOM_RIGHT BUTTON_FF
183 #define SUPERDOM_CANCEL BUTTON_MENU
187 #ifdef HAVE_TOUCHSCREEN
189 #define SUPERDOM_OK BUTTON_CENTER
192 #define SUPERDOM_UP BUTTON_TOPMIDDLE
194 #ifndef SUPERDOM_LEFT
195 #define SUPERDOM_LEFT BUTTON_MIDLEFT
197 #ifndef SUPERDOM_RIGHT
198 #define SUPERDOM_RIGHT BUTTON_MIDRIGHT
200 #ifndef SUPERDOM_DOWN
201 #define SUPERDOM_DOWN BUTTON_BOTTOMMIDDLE
203 #ifndef SUPERDOM_CANCEL
204 #define SUPERDOM_CANCEL BUTTON_TOPLEFT
211 RET_VAL_QUIT_ERR
, /* quit or error */
214 void gen_interest(void);
215 void init_resources(void);
216 int select_square(void);
217 void update_score(void);
218 void gen_resources(void);
219 void draw_cursor(void);
220 void draw_board(void);
223 signed int colour
; /* -1 = Unset */
255 struct resources humanres
;
256 struct resources compres
;
257 enum { GS_PROD
, GS_MOVE
, GS_WAR
};
265 struct tile board
[12][12];
267 void init_board(void) {
269 rb
->srand(*rb
->current_tick
);
270 for(i
=0;i
<12;i
++) { /* Hopefully about 50% each colour */
272 if((i
<1)||(j
<1)||(i
>10)||(j
>10))
273 board
[i
][j
].colour
= -1; /* Unset */
275 board
[i
][j
].colour
= rb
->rand()%2;
276 board
[i
][j
].tank
= false;
277 board
[i
][j
].plane
= false;
278 board
[i
][j
].nuke
= false;
279 board
[i
][j
].ind
= false;
280 board
[i
][j
].farm
= false;
285 while(compres
.farms
< superdom_settings
.compstartfarms
) {
286 i
= rb
->rand()%10 + 1;
287 j
= rb
->rand()%10 + 1;
288 if((board
[i
][j
].colour
== COLOUR_DARK
) && (board
[i
][j
].farm
== false)) {
289 board
[i
][j
].farm
= true;
293 while(compres
.inds
< superdom_settings
.compstartinds
) {
294 i
= rb
->rand()%10 + 1;
295 j
= rb
->rand()%10 + 1;
296 if((board
[i
][j
].colour
== COLOUR_DARK
) && (board
[i
][j
].ind
== false)) {
297 board
[i
][j
].ind
= true;
301 while(humanres
.farms
< superdom_settings
.humanstartfarms
) {
302 i
= rb
->rand()%10 + 1;
303 j
= rb
->rand()%10 + 1;
304 if((board
[i
][j
].colour
== COLOUR_LIGHT
)&&(board
[i
][j
].farm
== false)) {
305 board
[i
][j
].farm
= true;
309 while(humanres
.inds
< superdom_settings
.humanstartinds
) {
310 i
= rb
->rand()%10 + 1;
311 j
= rb
->rand()%10 + 1;
312 if((board
[i
][j
].colour
== COLOUR_LIGHT
) && (board
[i
][j
].ind
== false)) {
313 board
[i
][j
].ind
= true;
319 void draw_board(void) {
321 rb
->lcd_clear_display();
324 if(board
[i
][j
].colour
== COLOUR_DARK
) {
325 rb
->lcd_set_foreground(LCD_DARKGRAY
);
327 rb
->lcd_set_foreground(LCD_LIGHTGRAY
);
329 rb
->lcd_fillrect(MARGIN
+(BOX_WIDTH
*(i
-1)),
330 MARGIN
+(BOX_HEIGHT
*(j
-1)), BOX_WIDTH
,
333 rb
->lcd_set_drawmode(DRMODE_BG
| DRMODE_INVERSEVID
);
335 if(board
[i
][j
].ind
) {
336 MY_BITMAP_PART(superdom_boarditems
,
337 board
[i
][j
].colour
?ICON_WIDTH
:0, 0, ICON_STRIDE
,
338 #if LCD_WIDTH > LCD_HEIGHT
339 MARGIN
+(BOX_WIDTH
*(i
-1))+1,
340 MARGIN
+(BOX_HEIGHT
*(j
-1))+ICON_HEIGHT
+1,
342 MARGIN
+(BOX_WIDTH
*(i
-1))+1+ICON_WIDTH
,
343 MARGIN
+(BOX_HEIGHT
*(j
-1))+1,
345 ICON_WIDTH
, ICON_HEIGHT
);
347 if(board
[i
][j
].farm
) {
348 MY_BITMAP_PART(superdom_boarditems
,
349 board
[i
][j
].colour
?ICON_WIDTH
:0, ICON_HEIGHT
,
350 ICON_STRIDE
, MARGIN
+(BOX_WIDTH
*(i
-1))+1,
351 MARGIN
+(BOX_HEIGHT
*(j
-1))+1,
352 ICON_WIDTH
, ICON_HEIGHT
);
354 if(board
[i
][j
].tank
) {
355 MY_BITMAP_PART(superdom_boarditems
,
356 board
[i
][j
].colour
?ICON_WIDTH
:0, ICON_HEIGHT
*2,
357 ICON_STRIDE
, MARGIN
+(BOX_WIDTH
*(i
-1))+ICON_WIDTH
+1,
358 MARGIN
+(BOX_HEIGHT
*(j
-1))+ICON_HEIGHT
+1,
359 ICON_WIDTH
, ICON_HEIGHT
);
361 if(board
[i
][j
].men
) {
362 MY_BITMAP_PART(superdom_boarditems
,
363 board
[i
][j
].colour
?ICON_WIDTH
:0, ICON_HEIGHT
*3,
364 #if LCD_WIDTH > LCD_HEIGHT
365 ICON_STRIDE
, MARGIN
+(BOX_WIDTH
*(i
-1))+ICON_WIDTH
+1,
366 MARGIN
+(BOX_HEIGHT
*(j
-1))+1,
368 ICON_STRIDE
, MARGIN
+(BOX_WIDTH
*(i
-1))+1,
369 MARGIN
+(BOX_HEIGHT
*(j
-1))+1+ICON_HEIGHT
,
371 ICON_WIDTH
, ICON_HEIGHT
);
373 if(board
[i
][j
].plane
) {
374 MY_BITMAP_PART(superdom_boarditems
,
375 board
[i
][j
].colour
?ICON_WIDTH
:0, ICON_HEIGHT
*4,
376 #if LCD_WIDTH > LCD_HEIGHT
377 ICON_STRIDE
,MARGIN
+(BOX_WIDTH
*(i
-1))+ICON_WIDTH
*2+1,
378 MARGIN
+(BOX_HEIGHT
*(j
-1))+ICON_HEIGHT
+1,
380 ICON_STRIDE
,MARGIN
+(BOX_WIDTH
*(i
-1))+ICON_WIDTH
+1,
381 MARGIN
+(BOX_HEIGHT
*(j
-1))+ICON_HEIGHT
*2+1,
383 ICON_WIDTH
, ICON_HEIGHT
);
385 if(board
[i
][j
].nuke
) {
386 MY_BITMAP_PART(superdom_boarditems
,
387 board
[i
][j
].colour
?ICON_WIDTH
:0, ICON_HEIGHT
*5,
388 #if LCD_WIDTH > LCD_HEIGHT
389 ICON_STRIDE
,MARGIN
+(BOX_WIDTH
*(i
-1))+ICON_WIDTH
*2+1,
390 MARGIN
+(BOX_HEIGHT
*(j
-1))+1,
392 ICON_STRIDE
,MARGIN
+(BOX_WIDTH
*(i
-1))+1,
393 MARGIN
+(BOX_HEIGHT
*(j
-1))+ICON_HEIGHT
*2+1,
395 ICON_WIDTH
, ICON_HEIGHT
);
398 rb
->lcd_set_drawmode(DRMODE_SOLID
);
402 rb
->lcd_set_foreground(LCD_BLACK
);
403 for(i
=0;i
<=10;i
++) { /* Draw Horizontal lines */
404 rb
->lcd_hline(MARGIN
, MARGIN
+(BOX_WIDTH
*10), MARGIN
+(BOX_HEIGHT
*i
));
406 for(i
=0;i
<=10;i
++) { /* Draw Vertical lines */
407 rb
->lcd_vline(MARGIN
+(BOX_WIDTH
*i
), MARGIN
, MARGIN
+(BOX_HEIGHT
*10));
412 int calc_strength(int colour
, int x
, int y
) {
414 for (a
= -1; a
< 2; a
++) {
415 for (b
= -1; b
< 2; b
++) {
416 if ((b
== 0 || a
== 0) &&
417 (board
[x
+ a
][y
+ b
].colour
== colour
)) {
419 if(board
[x
+ a
][y
+ b
].tank
|| board
[x
+ a
][y
+ b
].farm
)
421 if(board
[x
+ a
][y
+ b
].plane
|| board
[x
+ a
][y
+ b
].ind
)
423 if(board
[x
+ a
][y
+ b
].nuke
)
425 if(board
[x
+ a
][y
+ b
].men
)
426 score
+= (board
[x
+ a
][y
+ b
].men
*133/1000);
433 void gen_interest(void) {
434 /* Interest should be around 10% */
435 rb
->srand(*rb
->current_tick
);
436 int interest
= 7+rb
->rand()%6;
437 humanres
.bank
= humanres
.bank
+(interest
*humanres
.bank
/100);
438 compres
.bank
= compres
.bank
+(interest
*compres
.bank
/100);
441 void draw_cursor(void) {
442 rb
->lcd_set_drawmode(DRMODE_COMPLEMENT
);
443 rb
->lcd_fillrect(MARGIN
+((cursor
.x
-1)*BOX_WIDTH
),
444 MARGIN
+((cursor
.y
-1)*BOX_HEIGHT
), BOX_WIDTH
+1, BOX_HEIGHT
+1);
445 rb
->lcd_set_drawmode(DRMODE_SOLID
);
449 void gen_resources(void) {
456 rb
->srand(*rb
->current_tick
);
457 /* Generate Human's resources */
458 for(i
=0;i
<humanres
.inds
;i
++) {
459 inccash
+= (300+rb
->rand()%200);
461 for(i
=0;i
<humanres
.farms
;i
++) {
462 incfood
+= (200+rb
->rand()%200);
465 ratecash
= inccash
/humanres
.inds
;
467 ratefood
= incfood
/humanres
.farms
;
470 rb
->splash(HZ
*2, "Patriotism sweeps the land, all production"
471 " is up this year!");
473 rb
->splash(HZ
*2, "Factories working at maximum efficiency,"
474 " cash production up this year!");
476 } else if(ratecash
> 350) {
478 rb
->splash(HZ
*2, "Record crop harvest this year!");
479 } else if(ratefood
> 250) {
480 rb
->splash(HZ
*2, "Production continues as normal");
482 rb
->splash(HZ
*2, "Spoilage of crops leads to reduced farm"
483 " output this year");
487 rb
->splash(HZ
*2, "Record crop harvest this year!");
488 } else if(ratefood
> 250) {
489 rb
->splash(HZ
*2, "Factory unions introduced. Industrial"
490 " production is down this year.");
492 rb
->splash(HZ
*2, "Internet created. All production is down"
493 " due to time wasted.");
496 humanres
.cash
+= inccash
;
497 humanres
.food
+= incfood
;
499 /* Generate Computer's resources */
502 for(i
=0;i
<compres
.inds
;i
++) {
503 inccash
+= (300+rb
->rand()%200);
505 for(i
=0;i
<compres
.farms
;i
++) {
506 incfood
+= (200+rb
->rand()%200);
508 compres
.cash
+= inccash
;
509 compres
.food
+= incfood
;
512 void update_score(void) {
514 rb
->lcd_setfont(FONT_SYSFIXED
);
515 rb
->lcd_set_drawmode(DRMODE_BG
|DRMODE_INVERSEVID
);
516 rb
->lcd_fillrect(5,LCD_HEIGHT
-20,105,20);
517 rb
->lcd_set_drawmode(DRMODE_SOLID
);
518 strength
= calc_strength(COLOUR_LIGHT
, cursor
.x
, cursor
.y
);
519 rb
->lcd_putsxyf(5,LCD_HEIGHT
-20,"Your power: %d.%d",strength
/10,strength
%10);
520 strength
= calc_strength(COLOUR_DARK
, cursor
.x
, cursor
.y
);
521 rb
->lcd_putsxyf(5,LCD_HEIGHT
-10,"Comp power: %d.%d",strength
/10,strength
%10);
522 rb
->lcd_setfont(FONT_UI
);
525 int settings_menu(void) {
528 MENUITEM_STRINGLIST(menu
, "Super Domination Settings", NULL
,
529 "Computer starting farms", "Computer starting factories",
530 "Human starting farms", "Human starting factories",
531 "Starting cash", "Starting food", "Moves per turn");
534 switch(rb
->do_menu(&menu
, &selection
, NULL
, false)) {
536 rb
->set_int("Computer starting farms", "", UNIT_INT
,
537 &superdom_settings
.compstartfarms
, NULL
,
541 rb
->set_int("Computer starting factories", "", UNIT_INT
,
542 &superdom_settings
.compstartinds
, NULL
,
546 rb
->set_int("Human starting farms", "", UNIT_INT
,
547 &superdom_settings
.humanstartfarms
, NULL
,
551 rb
->set_int("Human starting factories", "", UNIT_INT
,
552 &superdom_settings
.humanstartinds
, NULL
,
556 rb
->set_int("Starting cash", "", UNIT_INT
,
557 &superdom_settings
.startcash
, NULL
,
561 rb
->set_int("Starting food", "", UNIT_INT
,
562 &superdom_settings
.startfood
, NULL
,
566 rb
->set_int("Moves per turn", "", UNIT_INT
,
567 &superdom_settings
.movesperturn
, NULL
,
570 case MENU_ATTACHED_USB
:
581 static int superdom_help(void) {
582 static char* help_text
[] = {
583 "Super", "domination", "is", "a", "turn", "based", "strategy", "game,",
584 "where", "the", "aim", "is", "to", "overpower", "the", "computer",
585 "player", "by", "taking", "their", "territory.", "",
586 "Each", "year", "you", "are", "allocated", "an", "amount", "of", "cash",
587 "and", "food,", "depending", "on", "how", "many", "farms", "and",
588 "factories", "you", "control.", "",
589 "Use", "this", "cash", "and", "food", "to", "buy", "and", "feed", "your",
590 "army.", "Each", "tile", "has", "a", "strength,", "calculated", "by",
591 "the", "ownership", "of", "adjacent", "tiles,", "and", "the", "type",
592 "and", "number", "of", "troops", "on", "them.",
595 if (display_text(ARRAYLEN(help_text
), help_text
, NULL
, NULL
, true))
600 int start_menu(void) {
603 MENUITEM_STRINGLIST(menu
, "Super Domination Menu", NULL
,
604 "Play Super Domination", "Settings",
605 "Help", "Playback Control", "Quit");
608 switch(rb
->do_menu(&menu
, &selection
, NULL
, false)) {
610 return RET_VAL_OK
; /* start playing */
613 if(settings_menu()==RET_VAL_USB
)
617 if(superdom_help()==RET_VAL_USB
)
621 if(playback_control(NULL
))
625 return RET_VAL_QUIT_ERR
;
629 return RET_VAL_QUIT_ERR
;
632 int save_game(void) {
634 char savepath
[MAX_PATH
];
636 rb
->snprintf(savepath
, sizeof(savepath
), "/Savegame.ssg");
637 if(rb
->kbd_input(savepath
, MAX_PATH
)) {
638 DEBUGF("Keyboard input failed\n");
642 fd
= rb
->open(savepath
, O_WRONLY
|O_CREAT
, 0666);
643 DEBUGF("savepath: %s\n", savepath
);
645 DEBUGF("Couldn't create/open file\n");
649 rb
->write(fd
, "SSGv3", 5);
650 rb
->write(fd
, &gamestate
, sizeof(gamestate
));
651 rb
->write(fd
, &humanres
.cash
, sizeof(humanres
.cash
));
652 rb
->write(fd
, &humanres
.food
, sizeof(humanres
.food
));
653 rb
->write(fd
, &humanres
.bank
, sizeof(humanres
.bank
));
654 rb
->write(fd
, &humanres
.planes
, sizeof(humanres
.planes
));
655 rb
->write(fd
, &humanres
.tanks
, sizeof(humanres
.tanks
));
656 rb
->write(fd
, &humanres
.men
, sizeof(humanres
.men
));
657 rb
->write(fd
, &humanres
.nukes
, sizeof(humanres
.nukes
));
658 rb
->write(fd
, &humanres
.inds
, sizeof(humanres
.inds
));
659 rb
->write(fd
, &humanres
.farms
, sizeof(humanres
.farms
));
660 rb
->write(fd
, &humanres
.moves
, sizeof(humanres
.moves
));
661 rb
->write(fd
, &compres
.cash
, sizeof(compres
.cash
));
662 rb
->write(fd
, &compres
.food
, sizeof(compres
.food
));
663 rb
->write(fd
, &compres
.bank
, sizeof(compres
.bank
));
664 rb
->write(fd
, &compres
.planes
, sizeof(compres
.planes
));
665 rb
->write(fd
, &compres
.tanks
, sizeof(compres
.tanks
));
666 rb
->write(fd
, &compres
.men
, sizeof(compres
.men
));
667 rb
->write(fd
, &compres
.nukes
, sizeof(compres
.nukes
));
668 rb
->write(fd
, &compres
.inds
, sizeof(compres
.inds
));
669 rb
->write(fd
, &compres
.farms
, sizeof(compres
.farms
));
670 rb
->write(fd
, &compres
.moves
, sizeof(compres
.moves
));
671 rb
->write(fd
, board
, sizeof(board
));
672 rb
->write(fd
, &superdom_settings
.compstartfarms
, sizeof(int));
673 rb
->write(fd
, &superdom_settings
.compstartinds
, sizeof(int));
674 rb
->write(fd
, &superdom_settings
.humanstartfarms
, sizeof(int));
675 rb
->write(fd
, &superdom_settings
.humanstartinds
, sizeof(int));
676 rb
->write(fd
, &superdom_settings
.startcash
, sizeof(int));
677 rb
->write(fd
, &superdom_settings
.startfood
, sizeof(int));
678 rb
->write(fd
, &superdom_settings
.movesperturn
, sizeof(int));
683 int ingame_menu(void) {
684 MENUITEM_STRINGLIST(menu
, "Super Domination Menu", NULL
,
685 "Return to game", "Save Game",
686 "Playback Control", "Quit");
688 switch(rb
->do_menu(&menu
, NULL
, NULL
, false)) {
694 rb
->splash(HZ
, "Game saved");
696 rb
->splash(HZ
, "Error in save");
699 if(playback_control(NULL
))
703 return RET_VAL_QUIT_ERR
;
705 case MENU_ATTACHED_USB
:
715 int get_number(char* param
, int* value
, int max
) {
716 static const char *button_labels
[4][3] = {
724 int button
= 0, ret
= RET_VAL_OK
;
726 rb
->lcd_clear_display();
727 rb
->lcd_getstringsize("CLR", &width
, &height
);
728 if(width
> NUM_BOX_WIDTH
|| height
> NUM_BOX_HEIGHT
)
729 rb
->lcd_setfont(FONT_SYSFIXED
);
730 /* Draw a 3x4 grid */
731 for(i
=0;i
<=3;i
++) { /* Vertical lines */
732 rb
->lcd_vline(NUM_MARGIN_X
+(NUM_BOX_WIDTH
*i
), NUM_MARGIN_Y
,
733 NUM_MARGIN_Y
+(4*NUM_BOX_HEIGHT
));
735 for(i
=0;i
<=4;i
++) { /* Horizontal lines */
736 rb
->lcd_hline(NUM_MARGIN_X
, NUM_MARGIN_X
+(3*NUM_BOX_WIDTH
),
737 NUM_MARGIN_Y
+(NUM_BOX_HEIGHT
*i
));
741 rb
->lcd_getstringsize(button_labels
[i
][j
], &width
, &height
);
743 NUM_MARGIN_X
+(j
*NUM_BOX_WIDTH
)+NUM_BOX_WIDTH
/2-width
/2,
744 NUM_MARGIN_Y
+(i
*NUM_BOX_HEIGHT
)+NUM_BOX_HEIGHT
/2-height
/2,
745 button_labels
[i
][j
]);
748 rb
->lcd_putsxyf(NUM_MARGIN_X
+10, NUM_MARGIN_Y
+4*NUM_BOX_HEIGHT
+10,"%d",*value
);
749 rb
->lcd_getstringsize(param
, &width
, &height
);
750 if(width
< LCD_WIDTH
)
751 rb
->lcd_putsxy((LCD_WIDTH
-width
)/2, (NUM_MARGIN_Y
-height
)/2, param
);
753 rb
->lcd_puts_scroll(0, (NUM_MARGIN_Y
/height
-1)/2, param
);
754 rb
->lcd_set_drawmode(DRMODE_COMPLEMENT
);
755 rb
->lcd_fillrect(NUM_MARGIN_X
+(NUM_BOX_WIDTH
*x
),
756 NUM_MARGIN_Y
+(NUM_BOX_HEIGHT
*y
),
757 NUM_BOX_WIDTH
+1, NUM_BOX_HEIGHT
+1);
758 rb
->lcd_set_drawmode(DRMODE_SOLID
);
761 button
= rb
->button_get(true);
762 rb
->lcd_set_drawmode(DRMODE_COMPLEMENT
);
763 rb
->lcd_fillrect(NUM_MARGIN_X
+(NUM_BOX_WIDTH
*x
),
764 NUM_MARGIN_Y
+(NUM_BOX_HEIGHT
*y
),
765 NUM_BOX_WIDTH
+1, NUM_BOX_HEIGHT
+1);
766 rb
->lcd_set_drawmode(DRMODE_SOLID
);
771 *value
+= button_labels
[y
][x
][0] - '0';
780 if ((unsigned) *value
> (unsigned) max
)
782 rb
->lcd_set_drawmode(DRMODE_BG
|DRMODE_INVERSEVID
);
783 rb
->lcd_fillrect(0, NUM_MARGIN_Y
+4*NUM_BOX_HEIGHT
+10,
785 rb
->lcd_set_drawmode(DRMODE_SOLID
);
786 rb
->lcd_putsxyf(NUM_MARGIN_X
+10,NUM_MARGIN_Y
+4*NUM_BOX_HEIGHT
+10,
789 case SUPERDOM_CANCEL
:
792 ret
= RET_VAL_QUIT_ERR
;
794 #if CONFIG_KEYPAD != IRIVER_H10_PAD
825 #if CONFIG_KEYPAD == IRIVER_H10_PAD
838 #if CONFIG_KEYPAD == IRIVER_H10_PAD
851 if (rb
->default_event_handler(button
) == SYS_USB_CONNECTED
)
858 rb
->lcd_set_drawmode(DRMODE_COMPLEMENT
);
859 rb
->lcd_fillrect(NUM_MARGIN_X
+(NUM_BOX_WIDTH
*x
),
860 NUM_MARGIN_Y
+(NUM_BOX_HEIGHT
*y
),
861 NUM_BOX_WIDTH
+1, NUM_BOX_HEIGHT
+1);
862 rb
->lcd_set_drawmode(DRMODE_SOLID
);
865 rb
->lcd_setfont(FONT_UI
);
866 rb
->lcd_stop_scroll();
867 if (ret
== RET_VAL_QUIT_ERR
)
868 rb
->splash(HZ
, "Cancelled");
872 bool tile_has_item(int type
, int x
, int y
) {
875 return (board
[x
][y
].men
> 0);
878 return board
[x
][y
].tank
;
881 return board
[x
][y
].plane
;
884 return board
[x
][y
].farm
;
887 return board
[x
][y
].ind
;
890 return board
[x
][y
].nuke
;
896 int buy_resources(int colour
, int type
, int x
, int y
, int nummen
) {
897 const char *itemnames
[][6] = {
903 "the industrial plant",
910 "build an industrial plant",
917 "an industrial plant",
922 bool human
= (colour
== COLOUR_LIGHT
);
925 struct resources
*res
;
945 case 4: /* Factory */
952 if(res
->cash
< price
) {
954 rb
->splash(HZ
, "Not enough money!");
955 return RET_VAL_QUIT_ERR
;
958 rb
->splashf(HZ
, "Where do you want to place %s?", itemnames
[0][type
]);
959 if((temp
= select_square()) != RET_VAL_OK
)
964 if(board
[x
][y
].colour
!= colour
) {
966 rb
->splashf(HZ
, "Can't %s on enemy territory", itemnames
[1][type
]);
967 return RET_VAL_QUIT_ERR
;
969 if(type
!= 0 && tile_has_item(type
, x
, y
)) {
971 rb
->splashf(HZ
, "There is already %s there", itemnames
[2][type
]);
972 return RET_VAL_QUIT_ERR
;
976 board
[x
][y
].men
+= nummen
;
980 board
[x
][y
].tank
= true;
984 board
[x
][y
].plane
= true;
988 board
[x
][y
].farm
= true;
992 board
[x
][y
].ind
= true;
996 board
[x
][y
].nuke
= true;
1008 int buy_resources_menu(void) {
1009 int selection
= 0,nummen
;
1011 MENUITEM_STRINGLIST(menu
, "Buy Resources", NULL
,
1012 "Buy men ($1)", "Buy tank ($300)", "Buy plane ($600)",
1013 "Buy Farm ($1150)", "Buy Factory ($1300)",
1018 switch(rb
->do_menu(&menu
, &selection
, NULL
, false)) {
1021 if(get_number("How many men would you like?", &nummen
,
1022 humanres
.cash
) == RET_VAL_USB
)
1032 if(buy_resources(COLOUR_LIGHT
, selection
, 0, 0, nummen
)
1039 case MENU_ATTACHED_USB
:
1042 case GO_TO_PREVIOUS
:
1050 int move_unit(int colour
, int type
, int fromx
, int fromy
,
1051 int tox
, int toy
, int nummen
) {
1052 const char *itemnames
[][3] = {
1067 bool human
= (colour
== COLOUR_LIGHT
);
1071 rb
->splashf(HZ
, "Select where you want to move %s from",
1072 itemnames
[0][type
]);
1073 if((temp
= select_square()) != RET_VAL_OK
)
1078 if(board
[fromx
][fromy
].colour
!= colour
) {
1080 rb
->splash(HZ
, "That isn't your territory");
1081 return RET_VAL_QUIT_ERR
;
1083 if(!tile_has_item(type
, fromx
, fromy
)) {
1085 rb
->splashf(HZ
, "You don't have %s there", itemnames
[1][type
]);
1086 return RET_VAL_QUIT_ERR
;
1090 nummen
= board
[fromx
][fromy
].men
;
1091 if((temp
= get_number("How many men do you want to move?", &nummen
,
1092 nummen
)) != RET_VAL_OK
)
1095 if(nummen
> board
[fromx
][fromy
].men
) {
1097 rb
->splash(HZ
, "You don't have that many troops.");
1098 return RET_VAL_QUIT_ERR
;
1102 rb
->splashf(HZ
, "Select where you want to move %s to",
1103 itemnames
[2][type
]);
1104 if((temp
= select_square()) != RET_VAL_OK
)
1109 if((tox
== fromx
&& toy
== fromy
) ||
1110 board
[tox
][toy
].colour
!= colour
||
1111 (type
!= 2 && (abs(tox
- fromx
) > 1 || abs(toy
- fromy
) > 1))) {
1113 rb
->splash(HZ
, "Invalid move");
1114 return RET_VAL_QUIT_ERR
;
1116 if(type
!= 0 && tile_has_item(type
, tox
, toy
)) {
1118 rb
->splashf(HZ
, "There is already %s there", itemnames
[1][type
]);
1119 return RET_VAL_QUIT_ERR
;
1123 board
[fromx
][fromy
].men
-= nummen
;
1124 board
[tox
][toy
].men
+= nummen
;
1127 board
[fromx
][fromy
].tank
= false;
1128 board
[tox
][toy
].tank
= true;
1131 board
[fromx
][fromy
].plane
= false;
1132 board
[tox
][toy
].plane
= true;
1138 int move_unit_menu(void) {
1141 MENUITEM_STRINGLIST(menu
, "Move unit", NULL
,
1142 "Move men", "Move tank", "Move plane");
1143 switch(rb
->do_menu(&menu
, &selection
, NULL
, false)) {
1147 switch(move_unit(COLOUR_LIGHT
, selection
, 0, 0, 0, 0, 0)) {
1156 case MENU_ATTACHED_USB
:
1162 int launch_nuke(int colour
, int nukex
, int nukey
, int targetx
, int targety
) {
1163 bool human
= (colour
== COLOUR_LIGHT
);
1165 struct resources
*res
;
1167 if(board
[nukex
][nukey
].colour
!= colour
) {
1169 rb
->splash(HZ
, "That isn't your territory");
1170 return RET_VAL_QUIT_ERR
;
1172 if(! board
[nukex
][nukey
].nuke
) {
1174 rb
->splashf(HZ
, "You don't have %s there", "a nuke");
1175 return RET_VAL_QUIT_ERR
;
1178 rb
->splash(HZ
, "Select place to target with nuke");
1179 if((temp
= select_square()) != RET_VAL_OK
)
1189 board
[nukex
][nukey
].nuke
= false;
1191 if(board
[targetx
][targety
].colour
== COLOUR_LIGHT
) {
1196 res
->men
-= board
[targetx
][targety
].men
;
1197 res
->tanks
-= board
[targetx
][targety
].tank
;
1198 res
->planes
-= board
[targetx
][targety
].plane
;
1199 res
->nukes
-= board
[targetx
][targety
].nuke
;
1200 res
->farms
-= board
[targetx
][targety
].farm
;
1201 res
->inds
-= board
[targetx
][targety
].ind
;
1202 board
[targetx
][targety
].men
= 0;
1203 board
[targetx
][targety
].tank
= false;
1204 board
[targetx
][targety
].plane
= false;
1205 board
[targetx
][targety
].ind
= false;
1206 board
[targetx
][targety
].nuke
= false;
1207 board
[targetx
][targety
].farm
= false;
1208 /* TODO: Fallout carried by wind */
1213 int movement_menu(void) {
1214 int selection
= 0, temp
;
1216 MENUITEM_STRINGLIST(menu
, "Movement", NULL
,
1217 "Move unit", "Buy additional moves ($100)",
1218 "Launch nuclear missile", "Check map",
1219 "Finish moving", "Game menu");
1222 switch(rb
->do_menu(&menu
, &selection
, NULL
, false)) {
1224 if(humanres
.moves
) {
1225 if(move_unit_menu()==RET_VAL_USB
)
1228 rb
->splash(HZ
, "You have no more moves left."
1229 " You can buy more for $100 each.");
1233 if(humanres
.cash
> 100) {
1235 humanres
.cash
-= 100;
1236 rb
->snprintf(buf
, sizeof(buf
), "You now have %d moves",
1238 rb
->splash(HZ
, buf
);
1242 if(humanres
.nukes
==0) {
1243 rb
->splash(HZ
, "You do not have any nukes to launch");
1245 rb
->splash(HZ
, "Select place to launch nuke from");
1246 switch(select_square()) {
1248 if(launch_nuke(COLOUR_LIGHT
, cursor
.x
, cursor
.y
,
1249 0, 0) == RET_VAL_USB
)
1259 if(select_square() == RET_VAL_USB
)
1266 if((temp
= ingame_menu()) != RET_VAL_OK
)
1269 case MENU_ATTACHED_USB
:
1277 static const char* inventory_data(int selected_item
, void * data
,
1278 char * buffer
, size_t buffer_len
) {
1280 switch(selected_item
) {
1282 rb
->snprintf(buffer
,buffer_len
,"Men: %d", humanres
.men
);
1285 rb
->snprintf(buffer
,buffer_len
,"Tanks: %d", humanres
.tanks
);
1288 rb
->snprintf(buffer
,buffer_len
,"Planes: %d", humanres
.planes
);
1291 rb
->snprintf(buffer
,buffer_len
,"Factories: %d", humanres
.inds
);
1294 rb
->snprintf(buffer
,buffer_len
,"Farms: %d", humanres
.farms
);
1297 rb
->snprintf(buffer
,buffer_len
,"Nukes: %d", humanres
.nukes
);
1300 rb
->snprintf(buffer
,buffer_len
,"Cash: %d", humanres
.cash
);
1303 rb
->snprintf(buffer
,buffer_len
,"Food: %d", humanres
.food
);
1306 rb
->snprintf(buffer
,buffer_len
,"Bank: %d", humanres
.bank
);
1314 int show_inventory(void) {
1315 struct simplelist_info info
;
1316 rb
->simplelist_info_init(&info
, "Inventory", 9, NULL
);
1317 info
.hide_selection
= true;
1318 info
.get_name
= inventory_data
;
1319 if(rb
->simplelist_show_list(&info
)) {
1326 int production_menu(void) {
1327 int selection
= 0, temp
;
1329 MENUITEM_STRINGLIST(menu
, "Production", NULL
,
1330 "Buy resources", "Show inventory", "Check map",
1331 "Invest money", "Withdraw money",
1332 "Finish turn", "Game menu");
1335 switch(rb
->do_menu(&menu
, &selection
, NULL
, false)) {
1337 if(buy_resources_menu() == RET_VAL_USB
)
1341 if(show_inventory() == RET_VAL_USB
)
1345 if(select_square() == RET_VAL_USB
)
1349 temp
= humanres
.cash
;
1350 if(get_number("How much do you want to invest?", &temp
,
1351 humanres
.cash
) == RET_VAL_USB
)
1353 if(temp
> humanres
.cash
) {
1354 rb
->splash(HZ
, "You don't have that much cash to invest");
1356 humanres
.cash
-= temp
;
1357 humanres
.bank
+= temp
;
1361 temp
= humanres
.bank
;
1362 if(get_number("How much do you want to withdraw?", &temp
,
1363 humanres
.bank
) == RET_VAL_USB
)
1365 if(temp
> humanres
.bank
) {
1366 rb
->splash(HZ
, "You don't have that much cash to withdraw");
1368 humanres
.cash
+= temp
;
1369 humanres
.bank
-= temp
;
1376 if((temp
= ingame_menu()) != RET_VAL_OK
)
1379 case MENU_ATTACHED_USB
:
1387 void init_resources(void) {
1388 humanres
.cash
= superdom_settings
.startcash
;
1389 humanres
.food
= superdom_settings
.startfood
;
1391 humanres
.planes
= 0;
1398 compres
.cash
= superdom_settings
.startcash
;
1399 compres
.food
= superdom_settings
.startfood
;
1410 int select_square(void) {
1415 #if LCD_WIDTH >= 220
1416 rb
->lcd_setfont(FONT_SYSFIXED
);
1417 rb
->lcd_putsxyf(125, LCD_HEIGHT
-20,"Cash: %d", humanres
.cash
);
1418 rb
->lcd_putsxyf(125, LCD_HEIGHT
-10,"Food: %d", humanres
.food
);
1419 rb
->lcd_setfont(FONT_UI
);
1423 button
= rb
->button_get(true);
1425 case SUPERDOM_CANCEL
:
1426 rb
->splash(HZ
, "Cancelled");
1427 return RET_VAL_QUIT_ERR
;
1432 #if CONFIG_KEYPAD != IRIVER_H10_PAD
1434 case (SUPERDOM_LEFT
|BUTTON_REPEAT
):
1435 draw_cursor(); /* Deselect the current tile */
1450 case SUPERDOM_RIGHT
:
1451 case (SUPERDOM_RIGHT
|BUTTON_REPEAT
):
1452 draw_cursor(); /* Deselect the current tile */
1470 case (SUPERDOM_UP
|BUTTON_REPEAT
):
1471 draw_cursor(); /* Deselect the current tile */
1475 #if CONFIG_KEYPAD == IRIVER_H10_PAD
1487 case (SUPERDOM_DOWN
|BUTTON_REPEAT
):
1488 draw_cursor(); /* Deselect the current tile */
1492 #if CONFIG_KEYPAD == IRIVER_H10_PAD
1505 if (rb
->default_event_handler(button
) == SYS_USB_CONNECTED
)
1513 int killmen(int colour
) {
1514 bool human
= (colour
== COLOUR_LIGHT
);
1518 percent
= (humanres
.food
*1000)/humanres
.men
;
1521 percent
= (compres
.food
*1000)/compres
.men
;
1527 if(board
[i
][j
].colour
== colour
) {
1528 int nummen
= ((board
[i
][j
].men
* percent
)/1000);
1529 menkilled
+= board
[i
][j
].men
- nummen
;
1530 board
[i
][j
].men
= nummen
;
1536 humanres
.men
-= menkilled
;
1538 compres
.men
-= menkilled
;
1542 /* return -1 if error, 1 if attack is succeeded, 0 otherwise */
1543 int attack_territory(int colour
, int x
, int y
) {
1544 bool human
= (colour
== COLOUR_LIGHT
);
1547 if(board
[x
][y
].colour
== colour
) {
1549 rb
->splash(HZ
, "You can't attack your own territory");
1552 str_diff
= calc_strength(COLOUR_DARK
, x
, y
) -
1553 calc_strength(COLOUR_LIGHT
, x
, y
);
1555 str_diff
= -str_diff
;
1557 rb
->srand(*rb
->current_tick
);
1558 if(str_diff
> 0 || (str_diff
== 0 && rb
->rand()%2)) {
1559 struct resources
*offres
, *defres
;
1567 defres
->men
-= board
[x
][y
].men
;
1568 defres
->tanks
-= board
[x
][y
].tank
;
1569 defres
->planes
-= board
[x
][y
].plane
;
1570 defres
->nukes
-= board
[x
][y
].nuke
;
1571 defres
->farms
-= board
[x
][y
].farm
;
1572 defres
->inds
-= board
[x
][y
].ind
;
1573 offres
->farms
+= board
[x
][y
].farm
;
1574 offres
->inds
+= board
[x
][y
].ind
;
1575 board
[x
][y
].colour
= colour
;
1576 board
[x
][y
].men
= 0;
1577 board
[x
][y
].tank
= false;
1578 board
[x
][y
].plane
= false;
1579 board
[x
][y
].nuke
= false;
1588 rb
->splash(HZ
, "Your troops were unable to overcome"
1589 " the enemy troops");
1591 rb
->splash(HZ
*2, "The computer attempted to "
1592 "attack, but the invasion was"
1599 int war_menu(void) {
1600 int selection
= 0, temp
;
1602 MENUITEM_STRINGLIST(menu
, "War!", NULL
,
1603 "Select territory to attack",
1604 "Finish turn", "Game menu");
1606 while(humanres
.moves
) {
1607 switch(rb
->do_menu(&menu
, &selection
, NULL
, false)) {
1609 switch(select_square()) {
1611 if(attack_territory(COLOUR_LIGHT
, cursor
.x
, cursor
.y
)
1624 if((temp
= ingame_menu()) != RET_VAL_OK
)
1638 bool place_adjacent(bool tank
, int x
, int y
) {
1639 int type
= (tank
? 1: 2);
1640 if(!buy_resources(COLOUR_DARK
, type
, x
, y
, 0)) {
1643 if(!buy_resources(COLOUR_DARK
, type
, x
-1, y
, 0)) {
1646 if(!buy_resources(COLOUR_DARK
, type
, x
+1, y
, 0)) {
1649 if(!buy_resources(COLOUR_DARK
, type
, x
, y
-1, 0)) {
1652 if(!buy_resources(COLOUR_DARK
, type
, x
, y
+1, 0)) {
1658 bool has_adjacent(int x
, int y
) {
1659 if((board
[x
][y
].colour
== COLOUR_LIGHT
) &&
1660 ((board
[x
-1][y
].colour
== COLOUR_DARK
) ||
1661 (board
[x
+1][y
].colour
== COLOUR_DARK
) ||
1662 (board
[x
][y
+1].colour
== COLOUR_DARK
) ||
1663 (board
[x
][y
-1].colour
== COLOUR_DARK
)))
1669 void find_adjacent(int x
, int y
, int* adj_x
, int* adj_y
) {
1670 /* Finds adjacent squares, returning squares without tanks on them
1671 * in preference to those with them */
1672 if(board
[x
-1][y
].colour
== COLOUR_DARK
) {
1677 if(board
[x
+1][y
].colour
== COLOUR_DARK
) {
1682 if(board
[x
][y
-1].colour
== COLOUR_DARK
) {
1687 if(board
[x
][y
+1].colour
== COLOUR_DARK
) {
1694 void computer_allocate(void) {
1695 /* Firstly, decide whether to go offensive or defensive.
1696 * This is primarily decided by the human player posing a threat to either
1697 * the computer's farms or factories */
1699 bool offensive
= true;
1700 struct threat threats
[4];
1702 int total_str_diff
= 0;
1703 int numterritory
= 0;
1706 struct threat targets
[2];
1710 compres
.cash
+= compres
.bank
;
1714 if(board
[i
][j
].colour
== COLOUR_DARK
) {
1716 str_diff
= calc_strength(COLOUR_LIGHT
,i
,j
) -
1717 calc_strength(COLOUR_DARK
,i
,j
);
1718 if(str_diff
> 0 && (board
[i
][j
].ind
|| board
[i
][j
].farm
)) {
1719 if(numthreats
< 3) {
1721 threats
[numthreats
].x
= i
;
1722 threats
[numthreats
].y
= j
;
1723 threats
[numthreats
].str_diff
= str_diff
;
1732 /* The AI is going to go straight for the throat here and attack
1733 * the player's farms and factories. The amount of cash
1734 * the AI has to spend will determine how many targets there are */
1735 if(compres
.cash
> 1200) {
1736 /* 1200 is a figure I pulled out of nowhere. Adjust as needed */
1741 /* Work out which target(s) to attack. They must have adjacent squares
1742 * owned by the computer. If none are found just place troops in
1743 * random places around the map until we run out of money */
1747 if(has_adjacent(i
,j
) &&
1748 (board
[i
][j
].ind
|| board
[i
][j
].farm
)) {
1752 targets
[k
].str_diff
=
1753 calc_strength(COLOUR_LIGHT
, i
, j
) -
1754 calc_strength(COLOUR_DARK
, i
, j
);
1762 /* No targets found! Randomly pick squares and if they're owned
1763 * by the computer then stick a tank on it. */
1764 rb
->srand(*rb
->current_tick
);
1765 while(compres
.cash
>= 300 && compres
.tanks
< numterritory
) {
1766 i
= rb
->rand()%10 + 1;
1767 j
= rb
->rand()%10 + 1;
1768 if(board
[i
][j
].colour
== COLOUR_DARK
) {
1769 buy_resources(COLOUR_DARK
, 1, i
, j
, 0);
1775 str_diff
= targets
[i
].str_diff
;
1776 while(str_diff
+ 20 > 0 && compres
.cash
> 0) {
1777 /* While we still need them keep placing men */
1778 if(!place_adjacent(true, targets
[i
].x
, targets
[i
].y
)) {
1779 find_adjacent(targets
[i
].x
, targets
[i
].y
,
1781 men_needed
= (str_diff
+ 20)*1000/133;
1782 if(compres
.cash
< men_needed
) {
1783 men_needed
= compres
.cash
;
1785 buy_resources(COLOUR_DARK
, 0, adj
.x
, adj
.y
,
1789 str_diff
= calc_strength(COLOUR_LIGHT
,
1790 targets
[i
].x
, targets
[i
].y
) -
1791 calc_strength(COLOUR_DARK
,
1792 targets
[i
].x
, targets
[i
].y
);
1797 /* Work out what to place on each square to defend it.
1798 * Tanks are preferential because they do not require food,
1799 * but if the budget is tight then we fall back onto troops.
1800 * Conversely if cash is not an issue and there are already tanks in
1801 * place planes will be deployed. We would like a margin of at least
1802 * 20 points to be safe. */
1804 for(i
=0;i
<numthreats
;i
++) {
1805 total_str_diff
+= threats
[i
].str_diff
;
1807 if((total_str_diff
+20)*10 > compres
.cash
) {
1808 /* Not enough cash to accomodate all threats using tanks alone -
1809 * use men as a backup */
1810 for(i
=0;i
<numthreats
;i
++) {
1811 men_needed
= ((threats
[i
].str_diff
+ 20)*1000)/133;
1812 if(compres
.cash
< men_needed
) {
1813 men_needed
= compres
.cash
;
1815 buy_resources(COLOUR_DARK
, 0, threats
[i
].x
, threats
[i
].y
,
1820 /* Enough money to pay their way by planes? */
1821 bool tank
= ((total_str_diff
+20)*15 >= compres
.cash
);
1822 for(i
=0;i
<numthreats
;i
++) {
1823 str_diff
= threats
[i
].str_diff
;
1824 while(str_diff
+ 20 > 0) {
1825 if(!place_adjacent(tank
, threats
[i
].x
, threats
[i
].y
)) {
1826 /* No room for any more planes or tanks, revert to
1828 find_adjacent(threats
[i
].x
, threats
[i
].y
,
1830 men_needed
= (str_diff
+ 20)*1000/133;
1831 if(compres
.cash
< men_needed
) {
1832 men_needed
= compres
.cash
;
1834 buy_resources(COLOUR_DARK
, 0, threats
[i
].x
,
1835 threats
[i
].y
, men_needed
);
1838 str_diff
= calc_strength(COLOUR_LIGHT
,
1839 threats
[i
].x
, threats
[i
].y
) -
1840 calc_strength(COLOUR_DARK
,
1841 threats
[i
].x
, threats
[i
].y
);
1846 compres
.bank
+= compres
.cash
;
1850 int find_adj_target(int x
, int y
, struct cursor
* adj
) {
1851 /* Find a square next to a computer's farm or factory owned by the player
1852 * that is vulnerable. Return 1 on success, 0 otherwise */
1853 if(board
[x
+1][y
].colour
== COLOUR_LIGHT
&&
1854 calc_strength(COLOUR_LIGHT
,x
+1,y
)<=calc_strength(COLOUR_DARK
,x
+1,y
)) {
1859 if(board
[x
-1][y
].colour
== COLOUR_LIGHT
&&
1860 calc_strength(COLOUR_LIGHT
,x
-1,y
)<=calc_strength(COLOUR_DARK
,x
-1,y
)) {
1865 if(board
[x
][y
+1].colour
== COLOUR_LIGHT
&&
1866 calc_strength(COLOUR_LIGHT
,x
,y
+1)<=calc_strength(COLOUR_DARK
,x
,y
+1)) {
1871 if(board
[x
][y
-1].colour
== COLOUR_LIGHT
&&
1872 calc_strength(COLOUR_LIGHT
,x
,y
-1)<=calc_strength(COLOUR_DARK
,x
,y
-1)) {
1880 void computer_war(void) {
1881 /* Work out where to attack - prioritise the defence of buildings */
1883 bool found_target
= true;
1886 while(found_target
) {
1887 found_target
= false;
1890 if((board
[i
][j
].colour
== COLOUR_DARK
) &&
1891 (board
[i
][j
].farm
|| board
[i
][j
].ind
) &&
1892 find_adj_target(i
, j
, &adj
)) {
1893 found_target
= true;
1894 if(attack_territory(COLOUR_DARK
, adj
.x
, adj
.y
) >= 0) {
1904 /* Defence stage done, move on to OFFENCE */
1905 found_target
= true;
1906 while(found_target
) {
1907 found_target
= false;
1910 if(board
[i
][j
].colour
== COLOUR_LIGHT
&&
1911 (board
[i
][j
].ind
|| board
[i
][j
].farm
) &&
1912 (calc_strength(COLOUR_DARK
, i
, j
) >=
1913 calc_strength(COLOUR_LIGHT
, i
, j
))) {
1914 found_target
= true;
1915 if(attack_territory(COLOUR_DARK
, i
, j
) >= 0) {
1925 /* Spend leftover moves wherever attacking randomly */
1926 found_target
= true;
1927 while(found_target
) {
1928 found_target
= false;
1931 if(board
[i
][j
].colour
== COLOUR_LIGHT
&&
1932 (calc_strength(COLOUR_DARK
, i
, j
) >=
1933 calc_strength(COLOUR_LIGHT
, i
, j
))) {
1934 found_target
= true;
1935 if(attack_territory(COLOUR_DARK
, i
, j
) >= 0) {
1947 static int load_game(const char* file
) {
1950 fd
= rb
->open(file
, O_RDONLY
);
1952 DEBUGF("Couldn't open savegame\n");
1955 rb
->read(fd
, buf
, 5);
1956 if(rb
->strcmp(buf
, "SSGv3")) {
1957 rb
->splash(HZ
, "Invalid/incompatible savegame");
1960 rb
->read(fd
, &gamestate
, sizeof(gamestate
));
1961 rb
->read(fd
, &humanres
.cash
, sizeof(humanres
.cash
));
1962 rb
->read(fd
, &humanres
.food
, sizeof(humanres
.food
));
1963 rb
->read(fd
, &humanres
.bank
, sizeof(humanres
.bank
));
1964 rb
->read(fd
, &humanres
.planes
, sizeof(humanres
.planes
));
1965 rb
->read(fd
, &humanres
.tanks
, sizeof(humanres
.tanks
));
1966 rb
->read(fd
, &humanres
.men
, sizeof(humanres
.men
));
1967 rb
->read(fd
, &humanres
.nukes
, sizeof(humanres
.nukes
));
1968 rb
->read(fd
, &humanres
.inds
, sizeof(humanres
.inds
));
1969 rb
->read(fd
, &humanres
.farms
, sizeof(humanres
.farms
));
1970 rb
->read(fd
, &humanres
.moves
, sizeof(humanres
.moves
));
1971 rb
->read(fd
, &compres
.cash
, sizeof(humanres
.cash
));
1972 rb
->read(fd
, &compres
.food
, sizeof(humanres
.food
));
1973 rb
->read(fd
, &compres
.bank
, sizeof(humanres
.bank
));
1974 rb
->read(fd
, &compres
.planes
, sizeof(humanres
.planes
));
1975 rb
->read(fd
, &compres
.tanks
, sizeof(humanres
.tanks
));
1976 rb
->read(fd
, &compres
.men
, sizeof(humanres
.men
));
1977 rb
->read(fd
, &compres
.nukes
, sizeof(humanres
.nukes
));
1978 rb
->read(fd
, &compres
.inds
, sizeof(humanres
.inds
));
1979 rb
->read(fd
, &compres
.farms
, sizeof(humanres
.farms
));
1980 rb
->read(fd
, &compres
.moves
, sizeof(humanres
.moves
));
1981 rb
->read(fd
, board
, sizeof(board
));
1982 rb
->read(fd
, &superdom_settings
.compstartfarms
, sizeof(int));
1983 rb
->read(fd
, &superdom_settings
.compstartinds
, sizeof(int));
1984 rb
->read(fd
, &superdom_settings
.humanstartfarms
, sizeof(int));
1985 rb
->read(fd
, &superdom_settings
.humanstartinds
, sizeof(int));
1986 rb
->read(fd
, &superdom_settings
.startcash
, sizeof(int));
1987 rb
->read(fd
, &superdom_settings
.startfood
, sizeof(int));
1988 rb
->read(fd
, &superdom_settings
.movesperturn
, sizeof(int));
1993 void default_settings(void) {
1994 superdom_settings
.compstartfarms
= 1;
1995 superdom_settings
.compstartinds
= 1;
1996 superdom_settings
.humanstartfarms
= 2;
1997 superdom_settings
.humanstartinds
= 2;
1998 superdom_settings
.startcash
= 0;
1999 superdom_settings
.startfood
= 0;
2000 superdom_settings
.movesperturn
= 2;
2003 int average_strength(int colour
) {
2004 /* This function calculates the average strength of the given player,
2005 * used to determine when the computer wins or loses. */
2010 if(board
[i
][j
].colour
!= -1) {
2011 totalpower
+= calc_strength(colour
, i
, j
);
2015 return totalpower
/100;
2018 enum plugin_status
plugin_start(const void* parameter
)
2021 rb
->lcd_set_backdrop(NULL
);
2022 rb
->lcd_set_foreground(LCD_BLACK
);
2023 rb
->lcd_set_background(LCD_WHITE
);
2030 if(load_game(parameter
) != 0) {
2031 DEBUGF("Loading failed, generating new game\n");
2050 switch(start_menu()) {
2051 case RET_VAL_OK
: /* start playing */
2053 case RET_VAL_QUIT_ERR
: /* quit */
2057 return PLUGIN_USB_CONNECTED
;
2066 int avg_str_diff
= (average_strength(COLOUR_LIGHT
) -
2067 average_strength(COLOUR_DARK
));
2068 if(avg_str_diff
> 15) {
2069 rb
->splash(HZ
*4, "The computer has surrendered. You win.");
2072 if(-avg_str_diff
> 15) {
2073 rb
->splash(HZ
*4, "Your army have suffered terrible morale from"
2074 " the bleak prospects of winning. You lose.");
2080 gamestate
= GS_PROD
;
2081 switch(production_menu()) {
2083 return PLUGIN_USB_CONNECTED
;
2085 case RET_VAL_QUIT_ERR
:
2089 computer_allocate();
2092 humanres
.moves
= superdom_settings
.movesperturn
;
2094 gamestate
= GS_MOVE
;
2095 switch(movement_menu()) {
2097 return PLUGIN_USB_CONNECTED
;
2099 case RET_VAL_QUIT_ERR
:
2105 if(humanres
.food
> humanres
.men
) {
2106 rb
->snprintf(buf
, sizeof(buf
), "Your men ate %d units of food",
2108 humanres
.food
-= humanres
.men
;
2110 rb
->snprintf(buf
, sizeof(buf
), "There was not enough food"
2111 " to feed all your men, %d men have died of starvation",
2112 killmen(COLOUR_LIGHT
));
2114 rb
->splash(HZ
*2, buf
);
2117 if(compres
.food
> compres
.men
) {
2118 compres
.food
-= compres
.men
;
2120 rb
->snprintf(buf
, sizeof(buf
), "The computer does not have"
2121 " enough food to feed its men. %d have died of starvation",
2122 killmen(COLOUR_DARK
));
2123 rb
->splash(HZ
, buf
);
2127 humanres
.moves
= superdom_settings
.movesperturn
;
2130 switch(war_menu()) {
2132 return PLUGIN_USB_CONNECTED
;
2134 case RET_VAL_QUIT_ERR
:
2138 compres
.moves
= superdom_settings
.movesperturn
;