1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2006 Will Robertson
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
22 #include "lib/playback_control.h"
23 #include "lib/display_text.h"
24 #include "pluginbitmaps/superdom_boarditems.h"
27 extern const fb_data superdom_boarditems
[];
31 #define COLOUR_LIGHT 1
36 #define MY_BITMAP_PART rb->lcd_bitmap_transparent_part
38 #define MY_BITMAP_PART rb->lcd_mono_bitmap_part
41 #if LCD_WIDTH > LCD_HEIGHT
42 #define BOX_WIDTH ((LCD_WIDTH-(MARGIN*2))/10)
43 #define BOX_HEIGHT ((BOX_WIDTH*2)/3)
46 #define BOX_HEIGHT ((LCD_HEIGHT-(MARGIN*2)-15)/10)
47 #define BOX_WIDTH ((BOX_HEIGHT*2)/3)
51 /* NUM_BOX HEIGHT and WIDTH are used for the number pad in the game. The height
52 * calculation includes spacing for the text placed above and below the number
53 * pad (it divides by 6 instead of just 4). The width calculation gives extra
54 * spacing on the sides of the pad too (divides by 5 instead of 3).
56 #define NUM_BOX_HEIGHT (LCD_HEIGHT/6)
57 #define NUM_BOX_WIDTH (LCD_WIDTH/5)
59 #define NUM_MARGIN_X (LCD_WIDTH-3*NUM_BOX_WIDTH)/2
60 #define NUM_MARGIN_Y (LCD_HEIGHT-4*NUM_BOX_HEIGHT)/2
62 /* These parameters define the piece image dimensions, Stride is the total width
65 #define STRIDE BMPWIDTH_superdom_boarditems
66 #define ICON_HEIGHT (BMPHEIGHT_superdom_boarditems/6)
67 #define ICON_WIDTH (BMPWIDTH_superdom_boarditems/2)
69 #if (CONFIG_KEYPAD == IPOD_4G_PAD) || (CONFIG_KEYPAD == IPOD_3G_PAD) || \
70 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
71 #define SUPERDOM_OK BUTTON_SELECT
72 #define SUPERDOM_CANCEL BUTTON_MENU
73 #define SUPERDOM_LEFT BUTTON_LEFT
74 #define SUPERDOM_RIGHT BUTTON_RIGHT
77 #elif CONFIG_KEYPAD == IRIVER_H300_PAD || CONFIG_KEYPAD == IRIVER_H100_PAD
78 #define SUPERDOM_OK BUTTON_SELECT
79 #define SUPERDOM_LEFT BUTTON_LEFT
80 #define SUPERDOM_RIGHT BUTTON_RIGHT
81 #define SUPERDOM_UP BUTTON_UP
82 #define SUPERDOM_DOWN BUTTON_DOWN
83 #define SUPERDOM_CANCEL BUTTON_OFF
85 #elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
86 #define SUPERDOM_OK BUTTON_SELECT
87 #define SUPERDOM_LEFT BUTTON_LEFT
88 #define SUPERDOM_RIGHT BUTTON_RIGHT
89 #define SUPERDOM_UP BUTTON_UP
90 #define SUPERDOM_DOWN BUTTON_DOWN
91 #define SUPERDOM_CANCEL BUTTON_REC
93 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
94 #define SUPERDOM_OK BUTTON_RIGHT
95 #define SUPERDOM_UP BUTTON_SCROLL_UP
96 #define SUPERDOM_DOWN BUTTON_SCROLL_DOWN
97 #define SUPERDOM_CANCEL BUTTON_LEFT
99 #elif CONFIG_KEYPAD == GIGABEAT_PAD
100 #define SUPERDOM_OK BUTTON_SELECT
101 #define SUPERDOM_UP BUTTON_UP
102 #define SUPERDOM_DOWN BUTTON_DOWN
103 #define SUPERDOM_LEFT BUTTON_LEFT
104 #define SUPERDOM_RIGHT BUTTON_RIGHT
105 #define SUPERDOM_CANCEL BUTTON_POWER
107 #elif CONFIG_KEYPAD == SANSA_E200_PAD
108 #define SUPERDOM_OK BUTTON_SELECT
109 #define SUPERDOM_UP BUTTON_SCROLL_BACK
110 #define SUPERDOM_DOWN BUTTON_SCROLL_FWD
111 #define SUPERDOM_LEFT BUTTON_LEFT
112 #define SUPERDOM_RIGHT BUTTON_RIGHT
113 #define SUPERDOM_CANCEL BUTTON_POWER
115 #elif CONFIG_KEYPAD == SANSA_FUZE_PAD
116 #define SUPERDOM_OK BUTTON_SELECT
117 #define SUPERDOM_UP BUTTON_SCROLL_BACK
118 #define SUPERDOM_DOWN BUTTON_SCROLL_FWD
119 #define SUPERDOM_LEFT BUTTON_LEFT
120 #define SUPERDOM_RIGHT BUTTON_RIGHT
121 #define SUPERDOM_CANCEL (BUTTON_HOME|BUTTON_REPEAT)
123 #elif CONFIG_KEYPAD == GIGABEAT_S_PAD
124 #define SUPERDOM_OK BUTTON_SELECT
125 #define SUPERDOM_UP BUTTON_UP
126 #define SUPERDOM_DOWN BUTTON_DOWN
127 #define SUPERDOM_LEFT BUTTON_LEFT
128 #define SUPERDOM_RIGHT BUTTON_RIGHT
129 #define SUPERDOM_CANCEL BUTTON_BACK
131 #elif CONFIG_KEYPAD == COWOND2_PAD
132 #define SUPERDOM_CANCEL BUTTON_POWER
134 #elif CONFIG_KEYPAD == CREATIVEZVM_PAD
135 #define SUPERDOM_OK BUTTON_SELECT
136 #define SUPERDOM_UP BUTTON_UP
137 #define SUPERDOM_DOWN BUTTON_DOWN
138 #define SUPERDOM_LEFT BUTTON_LEFT
139 #define SUPERDOM_RIGHT BUTTON_RIGHT
140 #define SUPERDOM_CANCEL BUTTON_BACK
142 #elif (CONFIG_KEYPAD == ONDAVX747_PAD) || (CONFIG_KEYPAD == MROBE500_PAD)
143 #define SUPERDOM_CANCEL BUTTON_POWER
147 #ifdef HAVE_TOUCHSCREEN
149 #define SUPERDOM_OK BUTTON_CENTER
152 #define SUPERDOM_UP BUTTON_TOPMIDDLE
154 #ifndef SUPERDOM_LEFT
155 #define SUPERDOM_LEFT BUTTON_MIDLEFT
157 #ifndef SUPERDOM_RIGHT
158 #define SUPERDOM_RIGHT BUTTON_MIDRIGHT
160 #ifndef SUPERDOM_DOWN
161 #define SUPERDOM_DOWN BUTTON_BOTTOMMIDDLE
163 #ifndef SUPERDOM_CANCEL
164 #define SUPERDOM_CANCEL BUTTON_TOPLEFT
168 #define SUPERDOM_QUIT 23
170 void gen_interest(void);
171 int production_menu(void);
172 void init_resources(void);
173 int select_square(void);
174 void update_score(void);
175 void gen_resources(void);
176 void draw_cursor(void);
177 int calc_strength(int colour
, int x
, int y
);
178 void draw_board(void);
181 signed int colour
; /* -1 = Unset */
213 struct resources humanres
;
214 struct resources compres
;
215 enum { GS_PROD
, GS_MOVE
, GS_WAR
} gamestate
;
222 struct tile board
[12][12];
224 void init_board(void) {
226 rb
->srand(*rb
->current_tick
);
227 for(i
=0;i
<12;i
++) { /* Hopefully about 50% each colour */
229 if((i
<1)||(j
<1)||(i
>10)||(j
>10))
230 board
[i
][j
].colour
= -1; /* Unset */
232 board
[i
][j
].colour
= rb
->rand()%2;
233 board
[i
][j
].tank
= false;
234 board
[i
][j
].plane
= false;
235 board
[i
][j
].nuke
= false;
236 board
[i
][j
].ind
= false;
237 board
[i
][j
].farm
= false;
242 while(compres
.farms
< superdom_settings
.compstartfarms
) {
243 i
= rb
->rand()%10 + 1;
244 j
= rb
->rand()%10 + 1;
245 if((board
[i
][j
].colour
== COLOUR_DARK
) && (board
[i
][j
].farm
== false)) {
246 board
[i
][j
].farm
= true;
250 while(compres
.inds
< superdom_settings
.compstartinds
) {
251 i
= rb
->rand()%10 + 1;
252 j
= rb
->rand()%10 + 1;
253 if((board
[i
][j
].colour
== COLOUR_DARK
) && (board
[i
][j
].ind
== false)) {
254 board
[i
][j
].ind
= true;
258 while(humanres
.farms
<superdom_settings
.humanstartfarms
) {
259 i
= rb
->rand()%10 + 1;
260 j
= rb
->rand()%10 + 1;
261 if((board
[i
][j
].colour
== COLOUR_LIGHT
)&&(board
[i
][j
].farm
== false)) {
262 board
[i
][j
].farm
= true;
266 while(humanres
.inds
<superdom_settings
.humanstartfarms
) {
267 i
= rb
->rand()%10 + 1;
268 j
= rb
->rand()%10 + 1;
269 if((board
[i
][j
].colour
== COLOUR_LIGHT
) && (board
[i
][j
].ind
== false)) {
270 board
[i
][j
].ind
= true;
276 void draw_board(void) {
278 rb
->lcd_clear_display();
281 if(board
[i
][j
].colour
== COLOUR_DARK
) {
282 rb
->lcd_set_foreground(LCD_DARKGRAY
);
284 rb
->lcd_set_foreground(LCD_LIGHTGRAY
);
286 rb
->lcd_fillrect(MARGIN
+(BOX_WIDTH
*(i
-1)),
287 MARGIN
+(BOX_HEIGHT
*(j
-1)), BOX_WIDTH
,
290 rb
->lcd_set_drawmode(DRMODE_BG
| DRMODE_INVERSEVID
);
292 if(board
[i
][j
].ind
) {
293 MY_BITMAP_PART(superdom_boarditems
,
294 board
[i
][j
].colour
?ICON_WIDTH
:0, 0, STRIDE
,
295 #if LCD_WIDTH > LCD_HEIGHT
296 MARGIN
+(BOX_WIDTH
*(i
-1))+1,
297 MARGIN
+(BOX_HEIGHT
*(j
-1))+ICON_HEIGHT
+1,
299 MARGIN
+(BOX_WIDTH
*(i
-1))+1+ICON_WIDTH
,
300 MARGIN
+(BOX_HEIGHT
*(j
-1))+1,
302 ICON_WIDTH
, ICON_HEIGHT
);
304 if(board
[i
][j
].farm
) {
305 MY_BITMAP_PART(superdom_boarditems
,
306 board
[i
][j
].colour
?ICON_WIDTH
:0, ICON_HEIGHT
,
307 STRIDE
, MARGIN
+(BOX_WIDTH
*(i
-1))+1,
308 MARGIN
+(BOX_HEIGHT
*(j
-1))+1,
309 ICON_WIDTH
, ICON_HEIGHT
);
311 if(board
[i
][j
].tank
) {
312 MY_BITMAP_PART(superdom_boarditems
,
313 board
[i
][j
].colour
?ICON_WIDTH
:0, ICON_HEIGHT
*2,
314 STRIDE
, MARGIN
+(BOX_WIDTH
*(i
-1))+ICON_WIDTH
+1,
315 MARGIN
+(BOX_HEIGHT
*(j
-1))+ICON_HEIGHT
+1,
316 ICON_WIDTH
, ICON_HEIGHT
);
318 if(board
[i
][j
].men
) {
319 MY_BITMAP_PART(superdom_boarditems
,
320 board
[i
][j
].colour
?ICON_WIDTH
:0, ICON_HEIGHT
*3,
321 #if LCD_WIDTH > LCD_HEIGHT
322 STRIDE
, MARGIN
+(BOX_WIDTH
*(i
-1))+ICON_WIDTH
+1,
323 MARGIN
+(BOX_HEIGHT
*(j
-1))+1,
325 STRIDE
, MARGIN
+(BOX_WIDTH
*(i
-1))+1,
326 MARGIN
+(BOX_HEIGHT
*(j
-1))+1+ICON_HEIGHT
,
328 ICON_WIDTH
, ICON_HEIGHT
);
330 if(board
[i
][j
].plane
) {
331 MY_BITMAP_PART(superdom_boarditems
,
332 board
[i
][j
].colour
?ICON_WIDTH
:0, ICON_HEIGHT
*4,
333 #if LCD_WIDTH > LCD_HEIGHT
334 STRIDE
,MARGIN
+(BOX_WIDTH
*(i
-1))+ICON_WIDTH
*2+1,
335 MARGIN
+(BOX_HEIGHT
*(j
-1))+ICON_HEIGHT
+1,
337 STRIDE
,MARGIN
+(BOX_WIDTH
*(i
-1))+ICON_WIDTH
+1,
338 MARGIN
+(BOX_HEIGHT
*(j
-1))+ICON_HEIGHT
*2+1,
340 ICON_WIDTH
, ICON_HEIGHT
);
342 if(board
[i
][j
].nuke
) {
343 MY_BITMAP_PART(superdom_boarditems
,
344 board
[i
][j
].colour
?ICON_WIDTH
:0, ICON_HEIGHT
*5,
345 #if LCD_WIDTH > LCD_HEIGHT
346 STRIDE
,MARGIN
+(BOX_WIDTH
*(i
-1))+ICON_WIDTH
*2+1,
347 MARGIN
+(BOX_HEIGHT
*(j
-1))+1,
349 STRIDE
,MARGIN
+(BOX_WIDTH
*(i
-1))+1,
350 MARGIN
+(BOX_HEIGHT
*(j
-1))+ICON_HEIGHT
*2+1,
352 ICON_WIDTH
, ICON_HEIGHT
);
355 rb
->lcd_set_drawmode(DRMODE_SOLID
);
359 rb
->lcd_set_foreground(LCD_BLACK
);
360 for(i
=0;i
<=10;i
++) { /* Draw Horizontal lines */
361 rb
->lcd_hline(MARGIN
, MARGIN
+(BOX_WIDTH
*10), MARGIN
+(BOX_HEIGHT
*i
));
363 for(i
=0;i
<=10;i
++) { /* Draw Vertical lines */
364 rb
->lcd_vline(MARGIN
+(BOX_WIDTH
*i
), MARGIN
, MARGIN
+(BOX_HEIGHT
*10));
369 int calc_strength(int colour
, int x
, int y
) {
371 for (a
= -1; a
< 2; a
++) {
372 for (b
= -1; b
< 2; b
++) {
373 if ((b
== 0 || a
== 0) &&
374 (board
[x
+ a
][y
+ b
].colour
== colour
)) {
376 if(board
[x
+ a
][y
+ b
].tank
|| board
[x
+ a
][y
+ b
].farm
)
378 if(board
[x
+ a
][y
+ b
].plane
|| board
[x
+ a
][y
+ b
].ind
)
380 if(board
[x
+ a
][y
+ b
].nuke
)
382 if(board
[x
+ a
][y
+ b
].men
)
383 score
+= (board
[x
+ a
][y
+ b
].men
*133/1000);
390 void gen_interest(void) {
391 /* Interest should be around 10% */
392 rb
->srand(*rb
->current_tick
);
393 int interest
= 7+rb
->rand()%6;
394 humanres
.bank
= humanres
.bank
+(interest
*humanres
.bank
/100);
395 compres
.bank
= compres
.bank
+(interest
*compres
.bank
/100);
398 void draw_cursor(void) {
399 rb
->lcd_set_drawmode(DRMODE_COMPLEMENT
);
400 rb
->lcd_fillrect(MARGIN
+((cursor
.x
-1)*BOX_WIDTH
),
401 MARGIN
+((cursor
.y
-1)*BOX_HEIGHT
), BOX_WIDTH
+1, BOX_HEIGHT
+1);
402 rb
->lcd_set_drawmode(DRMODE_SOLID
);
406 void gen_resources(void) {
413 rb
->srand(*rb
->current_tick
);
414 /* Generate Human's resources */
415 for(i
=0;i
<humanres
.inds
;i
++) {
416 inccash
+= (300+rb
->rand()%200);
418 for(i
=0;i
<humanres
.farms
;i
++) {
419 incfood
+= (200+rb
->rand()%200);
422 ratecash
= inccash
/humanres
.inds
;
424 ratefood
= incfood
/humanres
.farms
;
427 rb
->splash(HZ
*2, "Patriotism sweeps the land, all production"
428 " is up this year!");
430 rb
->splash(HZ
*2, "Factories working at maximum efficiency,"
431 " cash production up this year!");
433 } else if(ratecash
> 350) {
435 rb
->splash(HZ
*2, "Record crop harvest this year!");
436 } else if(ratefood
> 250) {
437 rb
->splash(HZ
*2, "Production continues as normal");
439 rb
->splash(HZ
*2, "Spoilage of crops leads to reduced farm"
440 " output this year");
444 rb
->splash(HZ
*2, "Record crop harvest this year!");
445 } else if(ratefood
> 250) {
446 rb
->splash(HZ
*2, "Factory unions introduced. Industrial"
447 " production is down this year.");
449 rb
->splash(HZ
*2, "Internet created. All production is down"
450 " due to time wasted.");
453 humanres
.cash
+= inccash
;
454 humanres
.food
+= incfood
;
456 /* Generate Computer's resources */
459 for(i
=0;i
<compres
.inds
;i
++) {
460 inccash
+= (300+rb
->rand()%200);
462 for(i
=0;i
<compres
.farms
;i
++) {
463 incfood
+= (200+rb
->rand()%200);
465 compres
.cash
+= inccash
;
466 compres
.food
+= incfood
;
469 void update_score(void) {
471 rb
->lcd_setfont(FONT_SYSFIXED
);
472 rb
->lcd_set_drawmode(DRMODE_BG
|DRMODE_INVERSEVID
);
473 rb
->lcd_fillrect(5,LCD_HEIGHT
-20,105,20);
474 rb
->lcd_set_drawmode(DRMODE_SOLID
);
475 strength
= calc_strength(COLOUR_LIGHT
, cursor
.x
, cursor
.y
);
476 rb
->snprintf(buf
, sizeof(buf
), "Your power: %d.%d",
477 strength
/10, strength
%10);
478 rb
->lcd_putsxy(5,LCD_HEIGHT
-20, buf
);
479 strength
= calc_strength(COLOUR_DARK
, cursor
.x
, cursor
.y
);
480 rb
->snprintf(buf
, sizeof(buf
), "Comp power: %d.%d",
481 strength
/10, strength
%10);
482 rb
->lcd_putsxy(5,LCD_HEIGHT
-10, buf
);
483 rb
->lcd_setfont(FONT_UI
);
486 int settings_menu_function(void) {
489 MENUITEM_STRINGLIST(settings_menu
,"Super Domination Settings",NULL
,
490 "Computer starting farms","Computer starting factories",
491 "Human starting farms","Human starting factories",
492 "Starting cash","Starting food","Moves per turn");
495 selection
=rb
->do_menu(&settings_menu
,&selection
, NULL
, false);
498 rb
->set_int("Computer starting farms", "", UNIT_INT
,
499 &superdom_settings
.compstartfarms
, NULL
,
503 rb
->set_int("Computer starting factories", "", UNIT_INT
,
504 &superdom_settings
.compstartinds
, NULL
,
508 rb
->set_int("Human starting farms", "", UNIT_INT
,
509 &superdom_settings
.humanstartfarms
, NULL
,
513 rb
->set_int("Human starting factories", "", UNIT_INT
,
514 &superdom_settings
.humanstartinds
, NULL
,
518 rb
->set_int("Starting cash", "", UNIT_INT
,
519 &superdom_settings
.startcash
, NULL
,
523 rb
->set_int("Starting food", "", UNIT_INT
,
524 &superdom_settings
.startfood
, NULL
,
528 rb
->set_int("Moves per turn", "", UNIT_INT
,
529 &superdom_settings
.movesperturn
, NULL
,
532 case MENU_ATTACHED_USB
:
533 return PLUGIN_USB_CONNECTED
;
543 static int do_help(void) {
545 #define WORDS (sizeof help_text / sizeof (char*))
546 static char* help_text
[] = {
547 "Super", "domination", "is", "a", "turn", "based", "strategy", "game,",
548 "where", "the", "aim", "is", "to", "overpower", "the", "computer",
549 "player", "by", "taking", "their", "territory.", "",
550 "Each", "year", "you", "are", "allocated", "an", "amount", "of", "cash",
551 "and", "food,", "depending", "on", "how", "many", "farms", "and",
552 "factories", "you", "control.", "",
553 "Use", "this", "cash", "and", "food", "to", "buy", "and", "feed", "your",
554 "army.", "Each", "tile", "has", "a", "strength,", "calculated", "by",
555 "the", "ownership", "of", "adjacent", "tiles,", "and", "the", "type",
556 "and", "number", "of", "troops", "on", "them.",
559 if (display_text(WORDS
, help_text
, NULL
, NULL
))
560 return PLUGIN_USB_CONNECTED
;
562 button
= rb
->button_get(true);
563 if ( rb
->default_event_handler( button
) == SYS_USB_CONNECTED
)
564 return PLUGIN_USB_CONNECTED
;
565 } while( ( button
== BUTTON_NONE
)
566 || ( button
& (BUTTON_REL
|BUTTON_REPEAT
) ) );
574 MENUITEM_STRINGLIST(main_menu
,"Super Domination Menu",NULL
,
575 "Play Super Domination","Settings","Help","Quit");
578 selection
=rb
->do_menu(&main_menu
,&selection
, NULL
, false);
581 return 0; /* start playing */
584 if(settings_menu_function()==PLUGIN_USB_CONNECTED
)
585 return PLUGIN_USB_CONNECTED
;
588 if(do_help()==PLUGIN_USB_CONNECTED
)
589 return PLUGIN_USB_CONNECTED
;
592 return 2; /* quit program */
600 int save_game(void) {
602 char savepath
[MAX_PATH
];
604 rb
->snprintf(savepath
, sizeof(savepath
), "/Savegame.ssg");
605 if(rb
->kbd_input(savepath
, MAX_PATH
)) {
606 DEBUGF("Keyboard input failed\n");
610 fd
= rb
->open(savepath
, O_WRONLY
|O_CREAT
);
611 DEBUGF("savepath: %s\n", savepath
);
613 DEBUGF("Couldn't create/open file\n");
617 rb
->write(fd
, "SSGv3", 5);
618 rb
->write(fd
, &gamestate
, sizeof(gamestate
));
619 rb
->write(fd
, &humanres
.cash
, sizeof(humanres
.cash
));
620 rb
->write(fd
, &humanres
.food
, sizeof(humanres
.food
));
621 rb
->write(fd
, &humanres
.bank
, sizeof(humanres
.bank
));
622 rb
->write(fd
, &humanres
.planes
, sizeof(humanres
.planes
));
623 rb
->write(fd
, &humanres
.tanks
, sizeof(humanres
.tanks
));
624 rb
->write(fd
, &humanres
.men
, sizeof(humanres
.men
));
625 rb
->write(fd
, &humanres
.nukes
, sizeof(humanres
.nukes
));
626 rb
->write(fd
, &humanres
.inds
, sizeof(humanres
.inds
));
627 rb
->write(fd
, &humanres
.farms
, sizeof(humanres
.farms
));
628 rb
->write(fd
, &humanres
.moves
, sizeof(humanres
.moves
));
629 rb
->write(fd
, &compres
.cash
, sizeof(compres
.cash
));
630 rb
->write(fd
, &compres
.food
, sizeof(compres
.food
));
631 rb
->write(fd
, &compres
.bank
, sizeof(compres
.bank
));
632 rb
->write(fd
, &compres
.planes
, sizeof(compres
.planes
));
633 rb
->write(fd
, &compres
.tanks
, sizeof(compres
.tanks
));
634 rb
->write(fd
, &compres
.men
, sizeof(compres
.men
));
635 rb
->write(fd
, &compres
.nukes
, sizeof(compres
.nukes
));
636 rb
->write(fd
, &compres
.inds
, sizeof(compres
.inds
));
637 rb
->write(fd
, &compres
.farms
, sizeof(compres
.farms
));
638 rb
->write(fd
, &compres
.moves
, sizeof(compres
.moves
));
639 rb
->write(fd
, board
, sizeof(board
));
640 rb
->write(fd
, &superdom_settings
.compstartfarms
, sizeof(int));
641 rb
->write(fd
, &superdom_settings
.compstartinds
, sizeof(int));
642 rb
->write(fd
, &superdom_settings
.humanstartfarms
, sizeof(int));
643 rb
->write(fd
, &superdom_settings
.humanstartfarms
, sizeof(int));
644 rb
->write(fd
, &superdom_settings
.startcash
, sizeof(int));
645 rb
->write(fd
, &superdom_settings
.startfood
, sizeof(int));
646 rb
->write(fd
, &superdom_settings
.movesperturn
, sizeof(int));
651 int ingame_menu(void) {
654 MENUITEM_STRINGLIST(ingame_menu
,"Super Domination Menu",NULL
,
655 "Return to game","Save Game","Playback Control", "Quit");
657 selection
=rb
->do_menu(&ingame_menu
,&selection
, NULL
, false);
664 rb
->splash(HZ
, "Game saved");
666 rb
->splash(HZ
, "Error in save");
669 playback_control(NULL
);
672 return SUPERDOM_QUIT
;
674 case MENU_ATTACHED_USB
:
675 return PLUGIN_USB_CONNECTED
;
684 int get_number(char* param
, int* value
) {
685 //int numbers[3][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
699 rb
->lcd_clear_display();
700 /* Draw a 3x4 grid */
701 for(i
=0;i
<=3;i
++) { /* Vertical lines */
702 rb
->lcd_vline(NUM_MARGIN_X
+(NUM_BOX_WIDTH
*i
), NUM_MARGIN_Y
,
703 NUM_MARGIN_Y
+(4*NUM_BOX_HEIGHT
));
705 for(i
=0;i
<=4;i
++) { /* Horizontal lines */
706 rb
->lcd_hline(NUM_MARGIN_X
, NUM_MARGIN_X
+(3*NUM_BOX_WIDTH
),
707 NUM_MARGIN_Y
+(NUM_BOX_HEIGHT
*i
));
711 rb
->snprintf(buf
, sizeof(buf
), "%d", numbers
[i
][j
]);
712 rb
->lcd_putsxy(NUM_MARGIN_X
+(j
*NUM_BOX_WIDTH
)+10,
713 NUM_MARGIN_Y
+(i
*NUM_BOX_HEIGHT
)+8, buf
);
716 rb
->lcd_putsxy(NUM_MARGIN_X
+5, NUM_MARGIN_Y
+(3*NUM_BOX_HEIGHT
)+8, "CLR");
717 rb
->lcd_putsxy(NUM_MARGIN_X
+NUM_BOX_WIDTH
+10,
718 NUM_MARGIN_Y
+(3*NUM_BOX_HEIGHT
)+8, "0");
719 rb
->lcd_putsxy(NUM_MARGIN_X
+2*NUM_BOX_WIDTH
+8,
720 NUM_MARGIN_Y
+(3*NUM_BOX_HEIGHT
)+8, "OK");
721 rb
->snprintf(buf
,sizeof(buf
), "%d", *value
);
722 rb
->lcd_putsxy(NUM_MARGIN_X
+10, NUM_MARGIN_Y
+4*NUM_BOX_HEIGHT
+10, buf
);
723 rb
->lcd_getstringsize(param
, &width
, &height
);
724 rb
->lcd_putsxy((LCD_WIDTH
-width
)/2, (NUM_MARGIN_Y
-height
)/2, param
);
725 rb
->lcd_set_drawmode(DRMODE_COMPLEMENT
);
726 rb
->lcd_fillrect(NUM_MARGIN_X
+(NUM_BOX_WIDTH
*x
),
727 NUM_MARGIN_Y
+(NUM_BOX_HEIGHT
*y
), NUM_BOX_WIDTH
+1,
729 rb
->lcd_set_drawmode(DRMODE_SOLID
);
732 button
= rb
->button_get(true);
737 *value
+= numbers
[y
][x
];
745 rb
->lcd_set_drawmode(DRMODE_BG
|DRMODE_INVERSEVID
);
746 rb
->lcd_fillrect(0, NUM_MARGIN_Y
+4*NUM_BOX_HEIGHT
+10,
748 rb
->lcd_set_drawmode(DRMODE_SOLID
);
749 rb
->snprintf(buf
,sizeof(buf
), "%d", *value
);
750 rb
->lcd_putsxy(NUM_MARGIN_X
+10,
751 NUM_MARGIN_Y
+4*NUM_BOX_HEIGHT
+10, buf
);
753 case SUPERDOM_CANCEL
:
755 rb
->splash(HZ
, "Cancelled");
758 #if CONFIG_KEYPAD != IRIVER_H10_PAD
760 rb
->lcd_set_drawmode(DRMODE_COMPLEMENT
);
761 rb
->lcd_fillrect(NUM_MARGIN_X
+(NUM_BOX_WIDTH
*x
),
762 NUM_MARGIN_Y
+(NUM_BOX_HEIGHT
*y
),
763 NUM_BOX_WIDTH
+1, NUM_BOX_HEIGHT
+1);
764 rb
->lcd_set_drawmode(DRMODE_SOLID
);
776 rb
->lcd_set_drawmode(DRMODE_COMPLEMENT
);
777 rb
->lcd_fillrect(NUM_MARGIN_X
+(NUM_BOX_WIDTH
*x
),
778 NUM_MARGIN_Y
+(NUM_BOX_HEIGHT
*y
),
779 NUM_BOX_WIDTH
+1, NUM_BOX_HEIGHT
+1);
780 rb
->lcd_set_drawmode(DRMODE_SOLID
);
783 rb
->lcd_set_drawmode(DRMODE_COMPLEMENT
);
784 rb
->lcd_fillrect(NUM_MARGIN_X
+(NUM_BOX_WIDTH
*x
),
785 NUM_MARGIN_Y
+(NUM_BOX_HEIGHT
*y
),
786 NUM_BOX_WIDTH
+1, NUM_BOX_HEIGHT
+1);
787 rb
->lcd_set_drawmode(DRMODE_SOLID
);
799 rb
->lcd_set_drawmode(DRMODE_COMPLEMENT
);
800 rb
->lcd_fillrect(NUM_MARGIN_X
+(NUM_BOX_WIDTH
*x
),
801 NUM_MARGIN_Y
+(NUM_BOX_HEIGHT
*y
),
802 NUM_BOX_WIDTH
+1, NUM_BOX_HEIGHT
+1);
803 rb
->lcd_set_drawmode(DRMODE_SOLID
);
808 rb
->lcd_set_drawmode(DRMODE_COMPLEMENT
);
809 rb
->lcd_fillrect(NUM_MARGIN_X
+(NUM_BOX_WIDTH
*x
),
810 NUM_MARGIN_Y
+(NUM_BOX_HEIGHT
*y
),
811 NUM_BOX_WIDTH
+1, NUM_BOX_HEIGHT
+1);
812 rb
->lcd_set_drawmode(DRMODE_SOLID
);
814 #if CONFIG_KEYPAD == IRIVER_H10_PAD
824 rb
->lcd_set_drawmode(DRMODE_COMPLEMENT
);
825 rb
->lcd_fillrect(NUM_MARGIN_X
+(NUM_BOX_WIDTH
*x
),
826 NUM_MARGIN_Y
+(NUM_BOX_HEIGHT
*y
),
827 NUM_BOX_WIDTH
+1, NUM_BOX_HEIGHT
+1);
828 rb
->lcd_set_drawmode(DRMODE_SOLID
);
831 rb
->lcd_set_drawmode(DRMODE_COMPLEMENT
);
832 rb
->lcd_fillrect(NUM_MARGIN_X
+(NUM_BOX_WIDTH
*x
),
833 NUM_MARGIN_Y
+(NUM_BOX_HEIGHT
*y
),
834 NUM_BOX_WIDTH
+1, NUM_BOX_HEIGHT
+1);
835 rb
->lcd_set_drawmode(DRMODE_SOLID
);
837 #if CONFIG_KEYPAD == IRIVER_H10_PAD
847 rb
->lcd_set_drawmode(DRMODE_COMPLEMENT
);
848 rb
->lcd_fillrect(NUM_MARGIN_X
+(NUM_BOX_WIDTH
*x
),
849 NUM_MARGIN_Y
+(NUM_BOX_HEIGHT
*y
),
850 NUM_BOX_WIDTH
+1, NUM_BOX_HEIGHT
+1);
851 rb
->lcd_set_drawmode(DRMODE_SOLID
);
855 if (rb
->default_event_handler(button
) == SYS_USB_CONNECTED
)
857 return PLUGIN_USB_CONNECTED
;
866 bool tile_has_item(int type
, int x
, int y
) {
869 return (board
[x
][y
].men
> 0);
872 return board
[x
][y
].tank
;
875 return board
[x
][y
].plane
;
878 return board
[x
][y
].farm
;
881 return board
[x
][y
].ind
;
884 return board
[x
][y
].nuke
;
890 int buy_resources(int colour
, int type
, int x
, int y
, int nummen
) {
891 const char *itemnames
[][6] = {
897 "the industrial plant",
904 "build an industrial plant",
911 "an industrial plant",
916 bool human
= (colour
== COLOUR_LIGHT
);
918 struct resources
*res
;
938 case 4: /* Factory */
945 if(res
->cash
< price
) {
947 rb
->splash(HZ
, "Not enough money!");
951 rb
->splashf(HZ
, "Where do you want to place %s?", itemnames
[0][type
]);
952 switch(select_square()) {
956 case PLUGIN_USB_CONNECTED
:
957 return PLUGIN_USB_CONNECTED
;
963 if(board
[x
][y
].colour
!= colour
) {
965 rb
->splashf(HZ
, "Can't %s on enemy territory", itemnames
[1][type
]);
968 if(type
!= 0 && tile_has_item(type
, x
, y
)) {
970 rb
->splashf(HZ
, "There is already %s there", itemnames
[2][type
]);
975 board
[x
][y
].men
+= nummen
;
979 board
[x
][y
].tank
= true;
983 board
[x
][y
].plane
= true;
987 board
[x
][y
].farm
= true;
991 board
[x
][y
].ind
= true;
995 board
[x
][y
].nuke
= true;
1007 int buy_resources_menu(void) {
1008 int selection
,nummen
;
1010 MENUITEM_STRINGLIST(res_menu
, "Buy Resources", NULL
, "Buy men ($1)",
1011 "Buy tank ($300)", "Buy plane ($600)", "Buy Farm ($1150)",
1012 "Buy Factory ($1300)", "Buy Nuke ($2000)",
1016 selection
=rb
->do_menu(&res_menu
,&selection
, NULL
, false);
1020 if(get_number("How many men would you like?", &nummen
)
1021 == PLUGIN_USB_CONNECTED
)
1022 return PLUGIN_USB_CONNECTED
;
1031 if(buy_resources(COLOUR_LIGHT
, selection
, 0, 0, nummen
)
1032 == PLUGIN_USB_CONNECTED
)
1033 return PLUGIN_USB_CONNECTED
;
1038 case MENU_ATTACHED_USB
:
1039 return PLUGIN_USB_CONNECTED
;
1041 case GO_TO_PREVIOUS
:
1049 int move_unit(int colour
, int type
, int fromx
, int fromy
,
1050 int tox
, int toy
, int nummen
) {
1051 const char *itemnames
[][3] = {
1066 bool human
= (colour
== COLOUR_LIGHT
);
1069 rb
->splashf(HZ
, "Select where you want to move %s from",
1070 itemnames
[0][type
]);
1071 switch(select_square()) {
1075 case PLUGIN_USB_CONNECTED
:
1076 return PLUGIN_USB_CONNECTED
;
1082 if(board
[fromx
][fromy
].colour
!= colour
) {
1084 rb
->splash(HZ
, "That isn't your territory");
1087 if(!tile_has_item(type
, fromx
, fromy
)) {
1089 rb
->splashf(HZ
, "You don't have %s there", itemnames
[1][type
]);
1094 nummen
= board
[fromx
][fromy
].men
;
1095 switch(get_number("How many men do you want to move?", &nummen
)) {
1099 case PLUGIN_USB_CONNECTED
:
1100 return PLUGIN_USB_CONNECTED
;
1104 if(nummen
> board
[fromx
][fromy
].men
) {
1106 rb
->splash(HZ
, "You don't have that many troops.");
1111 rb
->splashf(HZ
, "Select where you want to move %s to",
1112 itemnames
[2][type
]);
1113 switch(select_square()) {
1117 case PLUGIN_USB_CONNECTED
:
1118 return PLUGIN_USB_CONNECTED
;
1124 if((tox
== fromx
&& toy
== fromy
) ||
1125 board
[tox
][toy
].colour
!= colour
||
1126 (type
!= 2 && (abs(tox
- fromx
) > 1 || abs(toy
- fromy
) > 1))) {
1128 rb
->splash(HZ
, "Invalid move");
1131 if(type
!= 0 && tile_has_item(type
, tox
, toy
)) {
1133 rb
->splashf(HZ
, "There is already %s there", itemnames
[1][type
]);
1138 board
[fromx
][fromy
].men
-= nummen
;
1139 board
[tox
][toy
].men
+= nummen
;
1142 board
[fromx
][fromy
].tank
= false;
1143 board
[tox
][toy
].tank
= true;
1146 board
[fromx
][fromy
].plane
= false;
1147 board
[tox
][toy
].plane
= true;
1153 int move_unit_menu(void) {
1156 MENUITEM_STRINGLIST(move_unit_menu
, "Move unit", NULL
, "Move men",
1157 "Move tank", "Move plane");
1158 selection
=rb
->do_menu(&move_unit_menu
,&selection
, NULL
, false);
1163 switch(move_unit(COLOUR_LIGHT
, selection
, 0, 0, 0, 0, 0)) {
1167 case PLUGIN_USB_CONNECTED
:
1168 return PLUGIN_USB_CONNECTED
;
1172 case MENU_ATTACHED_USB
:
1173 return PLUGIN_USB_CONNECTED
;
1178 int launch_nuke(int colour
, int nukex
, int nukey
, int targetx
, int targety
) {
1179 bool human
= (colour
== COLOUR_LIGHT
);
1180 struct resources
*res
;
1182 if(board
[nukex
][nukey
].colour
!= colour
) {
1184 rb
->splash(HZ
, "That isn't your territory");
1187 if(! board
[nukex
][nukey
].nuke
) {
1189 rb
->splashf(HZ
, "You don't have %s there", "a nuke");
1193 rb
->splash(HZ
, "Select place to target with nuke");
1194 switch(select_square()) {
1198 case PLUGIN_USB_CONNECTED
:
1199 return PLUGIN_USB_CONNECTED
;
1210 board
[nukex
][nukey
].nuke
= false;
1212 if(board
[targetx
][targety
].colour
== COLOUR_LIGHT
) {
1217 res
->men
-= board
[targetx
][targety
].men
;
1218 res
->tanks
-= board
[targetx
][targety
].tank
;
1219 res
->planes
-= board
[targetx
][targety
].plane
;
1220 res
->nukes
-= board
[targetx
][targety
].nuke
;
1221 res
->farms
-= board
[targetx
][targety
].farm
;
1222 res
->inds
-= board
[targetx
][targety
].ind
;
1223 board
[targetx
][targety
].men
= 0;
1224 board
[targetx
][targety
].tank
= false;
1225 board
[targetx
][targety
].plane
= false;
1226 board
[targetx
][targety
].ind
= false;
1227 board
[targetx
][targety
].nuke
= false;
1228 board
[targetx
][targety
].farm
= false;
1229 /* TODO: Fallout carried by wind */
1234 int movement_menu(void) {
1235 int selection
, tempmenu
;
1237 MENUITEM_STRINGLIST(move_menu
, "Movement", NULL
, "Move unit",
1238 "Buy additional moves ($100)", "Launch nuclear missile",
1239 "Check map", "Finish moving", "Game menu");
1242 selection
=rb
->do_menu(&move_menu
,&selection
, NULL
, false);
1245 if(humanres
.moves
) {
1246 if(move_unit_menu()==PLUGIN_USB_CONNECTED
)
1247 return PLUGIN_USB_CONNECTED
;
1249 rb
->splash(HZ
, "You have no more moves left."
1250 " You can buy more for $100 each.");
1254 if(humanres
.cash
> 100) {
1256 humanres
.cash
-= 100;
1257 rb
->snprintf(buf
, sizeof(buf
), "You now have %d moves",
1259 rb
->splash(HZ
, buf
);
1263 if(humanres
.nukes
==0) {
1264 rb
->splash(HZ
, "You do not have any nukes to launch");
1266 rb
->splash(HZ
, "Select place to launch nuke from");
1267 switch(select_square()) {
1269 if(launch_nuke(COLOUR_LIGHT
, cursor
.x
, cursor
.y
,
1270 0, 0) == PLUGIN_USB_CONNECTED
)
1271 return PLUGIN_USB_CONNECTED
;
1273 case PLUGIN_USB_CONNECTED
:
1274 return PLUGIN_USB_CONNECTED
;
1280 if(select_square() == PLUGIN_USB_CONNECTED
)
1281 return PLUGIN_USB_CONNECTED
;
1287 tempmenu
= ingame_menu();
1289 case PLUGIN_USB_CONNECTED
:
1290 return PLUGIN_USB_CONNECTED
;
1293 return SUPERDOM_QUIT
;
1297 case MENU_ATTACHED_USB
:
1298 return PLUGIN_USB_CONNECTED
;
1305 int show_inventory(void) {
1306 char men
[20], tanks
[20], planes
[20], inds
[20], farms
[20], nukes
[20],
1307 cash
[20], food
[20], bank
[20];
1308 rb
->snprintf(men
, sizeof(men
), "Men: %d", humanres
.men
);
1309 rb
->snprintf(tanks
, sizeof(tanks
), "Tanks: %d", humanres
.tanks
);
1310 rb
->snprintf(planes
, sizeof(planes
), "Planes: %d", humanres
.planes
);
1311 rb
->snprintf(inds
, sizeof(inds
), "Factories: %d", humanres
.inds
);
1312 rb
->snprintf(farms
, sizeof(farms
), "Farms: %d", humanres
.farms
);
1313 rb
->snprintf(nukes
, sizeof(nukes
), "Nukes: %d", humanres
.nukes
);
1314 rb
->snprintf(cash
, sizeof(cash
), "Cash: %d", humanres
.cash
);
1315 rb
->snprintf(food
, sizeof(food
), "Food: %d", humanres
.food
);
1316 rb
->snprintf(bank
, sizeof(bank
), "Bank: %d", humanres
.bank
);
1317 rb
->lcd_clear_display();
1318 rb
->lcd_puts(1, 0, "Inventory");
1319 rb
->lcd_puts(2, 1, men
);
1320 rb
->lcd_puts(2, 2, tanks
);
1321 rb
->lcd_puts(2, 3, planes
);
1322 rb
->lcd_puts(2, 4, inds
);
1323 rb
->lcd_puts(2, 5, farms
);
1324 rb
->lcd_puts(2, 6, nukes
);
1325 rb
->lcd_puts(2, 7, cash
);
1326 rb
->lcd_puts(2, 8, food
);
1327 rb
->lcd_puts(2, 9, bank
);
1329 if(rb
->default_event_handler(rb
->button_get(true)) == SYS_USB_CONNECTED
) {
1330 return PLUGIN_USB_CONNECTED
;
1336 int production_menu(void) {
1337 int selection
, tempbank
, tempmenu
;
1339 MENUITEM_STRINGLIST(prod_menu
, "Production", NULL
, "Buy resources",
1340 "Show inventory", "Check map", "Invest money",
1341 "Withdraw money", "Finish turn", "Game menu");
1344 selection
=rb
->do_menu(&prod_menu
,&selection
, NULL
, false);
1347 if(buy_resources_menu() == PLUGIN_USB_CONNECTED
)
1348 return PLUGIN_USB_CONNECTED
;
1351 if(show_inventory() == PLUGIN_USB_CONNECTED
)
1352 return PLUGIN_USB_CONNECTED
;
1355 if(select_square() == PLUGIN_USB_CONNECTED
)
1356 return PLUGIN_USB_CONNECTED
;
1359 tempbank
= humanres
.cash
;
1360 if(get_number("How much do you want to invest?", &tempbank
)
1361 == PLUGIN_USB_CONNECTED
)
1362 return PLUGIN_USB_CONNECTED
;
1363 if(tempbank
>humanres
.cash
) {
1364 rb
->splash(HZ
, "You don't have that much cash to invest");
1366 humanres
.cash
-= tempbank
;
1367 humanres
.bank
+= tempbank
;
1372 if(get_number("How much do you want to withdraw?", &tempbank
)
1373 == PLUGIN_USB_CONNECTED
)
1374 return PLUGIN_USB_CONNECTED
;
1375 if(tempbank
>humanres
.bank
) {
1376 rb
->splash(HZ
, "You don't have that much cash to withdraw");
1378 humanres
.cash
+= tempbank
;
1379 humanres
.bank
-= tempbank
;
1386 tempmenu
= ingame_menu();
1388 case PLUGIN_USB_CONNECTED
:
1389 return PLUGIN_USB_CONNECTED
;
1392 return SUPERDOM_QUIT
;
1396 case MENU_ATTACHED_USB
:
1397 return PLUGIN_USB_CONNECTED
;
1404 void init_resources(void) {
1405 humanres
.cash
= superdom_settings
.startcash
;
1406 humanres
.food
= superdom_settings
.startfood
;
1408 humanres
.planes
= 0;
1415 compres
.cash
= superdom_settings
.startcash
;
1416 compres
.food
= superdom_settings
.startfood
;
1427 int select_square(void) {
1432 #if LCD_WIDTH >= 220
1433 rb
->lcd_setfont(FONT_SYSFIXED
);
1434 rb
->snprintf(buf
, sizeof(buf
), "Cash: %d", humanres
.cash
);
1435 rb
->lcd_putsxy(125, LCD_HEIGHT
-20, buf
);
1436 rb
->snprintf(buf
, sizeof(buf
), "Food: %d", humanres
.food
);
1437 rb
->lcd_putsxy(125, LCD_HEIGHT
-10, buf
);
1438 rb
->lcd_setfont(FONT_UI
);
1442 button
= rb
->button_get(true);
1444 case SUPERDOM_CANCEL
:
1445 rb
->splash(HZ
, "Cancelled");
1451 #if CONFIG_KEYPAD != IRIVER_H10_PAD
1453 case (SUPERDOM_LEFT
|BUTTON_REPEAT
):
1454 draw_cursor(); /* Deselect the current tile */
1469 case SUPERDOM_RIGHT
:
1470 case (SUPERDOM_RIGHT
|BUTTON_REPEAT
):
1471 draw_cursor(); /* Deselect the current tile */
1489 case (SUPERDOM_UP
|BUTTON_REPEAT
):
1490 draw_cursor(); /* Deselect the current tile */
1494 #if CONFIG_KEYPAD == IRIVER_H10_PAD
1506 case (SUPERDOM_DOWN
|BUTTON_REPEAT
):
1507 draw_cursor(); /* Deselect the current tile */
1511 #if CONFIG_KEYPAD == IRIVER_H10_PAD
1524 if (rb
->default_event_handler(button
) == SYS_USB_CONNECTED
)
1526 return PLUGIN_USB_CONNECTED
;
1532 int killmen(int colour
) {
1533 bool human
= (colour
== COLOUR_LIGHT
);
1537 percent
= (humanres
.food
*1000)/humanres
.men
;
1540 percent
= (compres
.food
*1000)/compres
.men
;
1546 if(board
[i
][j
].colour
== colour
) {
1547 int nummen
= ((board
[i
][j
].men
* percent
)/1000);
1548 menkilled
+= board
[i
][j
].men
- nummen
;
1549 board
[i
][j
].men
= nummen
;
1555 humanres
.men
-= menkilled
;
1557 compres
.men
-= menkilled
;
1561 /* return -1 if error, 1 if attack is succeeded, 0 otherwise */
1562 int attack_territory(int colour
, int x
, int y
) {
1563 bool human
= (colour
== COLOUR_LIGHT
);
1566 if(board
[x
][y
].colour
== colour
) {
1568 rb
->splash(HZ
, "You can't attack your own territory");
1571 str_diff
= calc_strength(COLOUR_DARK
, x
, y
) -
1572 calc_strength(COLOUR_LIGHT
, x
, y
);
1574 str_diff
= -str_diff
;
1576 rb
->srand(*rb
->current_tick
);
1577 if(str_diff
> 0 || (str_diff
== 0 && rb
->rand()%2)) {
1578 struct resources
*offres
, *defres
;
1586 defres
->men
-= board
[x
][y
].men
;
1587 defres
->tanks
-= board
[x
][y
].tank
;
1588 defres
->planes
-= board
[x
][y
].plane
;
1589 defres
->nukes
-= board
[x
][y
].nuke
;
1590 defres
->farms
-= board
[x
][y
].farm
;
1591 defres
->inds
-= board
[x
][y
].ind
;
1592 offres
->farms
+= board
[x
][y
].farm
;
1593 offres
->inds
+= board
[x
][y
].ind
;
1594 board
[x
][y
].colour
= colour
;
1595 board
[x
][y
].men
= 0;
1596 board
[x
][y
].tank
= false;
1597 board
[x
][y
].plane
= false;
1598 board
[x
][y
].nuke
= false;
1607 rb
->splash(HZ
, "Your troops were unable to overcome"
1608 " the enemy troops");
1610 rb
->splash(HZ
*2, "The computer attempted to "
1611 "attack, but the invasion was"
1618 int war_menu(void) {
1619 int selection
, tempmenu
;
1621 MENUITEM_STRINGLIST(wartime_menu
, "War!", NULL
,
1622 "Select territory to attack", "Finish turn", "Game menu");
1624 while(humanres
.moves
) {
1625 selection
=rb
->do_menu(&wartime_menu
,&selection
, NULL
, false);
1628 switch(select_square()) {
1630 if(attack_territory(COLOUR_LIGHT
, cursor
.x
, cursor
.y
)
1634 case PLUGIN_USB_CONNECTED
:
1635 return PLUGIN_USB_CONNECTED
;
1643 tempmenu
= ingame_menu();
1645 case PLUGIN_USB_CONNECTED
:
1646 return PLUGIN_USB_CONNECTED
;
1649 return SUPERDOM_QUIT
;
1664 bool place_adjacent(bool tank
, int x
, int y
) {
1665 int type
= (tank
? 1: 2);
1666 if(!buy_resources(COLOUR_DARK
, type
, x
, y
, 0)) {
1669 if(!buy_resources(COLOUR_DARK
, type
, x
-1, y
, 0)) {
1672 if(!buy_resources(COLOUR_DARK
, type
, x
+1, y
, 0)) {
1675 if(!buy_resources(COLOUR_DARK
, type
, x
, y
-1, 0)) {
1678 if(!buy_resources(COLOUR_DARK
, type
, x
, y
+1, 0)) {
1684 bool has_adjacent(int x
, int y
) {
1685 if((board
[x
][y
].colour
== COLOUR_LIGHT
) &&
1686 ((board
[x
-1][y
].colour
== COLOUR_DARK
) ||
1687 (board
[x
+1][y
].colour
== COLOUR_DARK
) ||
1688 (board
[x
][y
+1].colour
== COLOUR_DARK
) ||
1689 (board
[x
][y
-1].colour
== COLOUR_DARK
)))
1695 void find_adjacent(int x
, int y
, int* adj_x
, int* adj_y
) {
1696 /* Finds adjacent squares, returning squares without tanks on them
1697 * in preference to those with them */
1698 if(board
[x
-1][y
].colour
== COLOUR_DARK
) {
1703 if(board
[x
+1][y
].colour
== COLOUR_DARK
) {
1708 if(board
[x
][y
-1].colour
== COLOUR_DARK
) {
1713 if(board
[x
][y
+1].colour
== COLOUR_DARK
) {
1720 void computer_allocate(void) {
1721 /* Firstly, decide whether to go offensive or defensive.
1722 * This is primarily decided by the human player posing a threat to either
1723 * the computer's farms or factories */
1725 bool offensive
= true;
1726 struct threat threats
[4];
1728 int total_str_diff
= 0;
1729 int numterritory
= 0;
1732 struct threat targets
[2];
1736 compres
.cash
+= compres
.bank
;
1740 if(board
[i
][j
].colour
== COLOUR_DARK
) {
1742 str_diff
= calc_strength(COLOUR_LIGHT
,i
,j
) -
1743 calc_strength(COLOUR_DARK
,i
,j
);
1744 if(str_diff
> 0 && (board
[i
][j
].ind
|| board
[i
][j
].farm
)) {
1745 if(numthreats
< 3) {
1747 threats
[numthreats
].x
= i
;
1748 threats
[numthreats
].y
= j
;
1749 threats
[numthreats
].str_diff
= str_diff
;
1758 /* The AI is going to go straight for the throat here and attack
1759 * the player's farms and factories. The amount of cash
1760 * the AI has to spend will determine how many targets there are */
1761 if(compres
.cash
> 1200) {
1762 /* 1200 is a figure I pulled out of nowhere. Adjust as needed */
1767 /* Work out which target(s) to attack. They must have adjacent squares
1768 * owned by the computer. If none are found just place troops in
1769 * random places around the map until we run out of money */
1773 if(has_adjacent(i
,j
) &&
1774 (board
[i
][j
].ind
|| board
[i
][j
].farm
)) {
1778 targets
[k
].str_diff
=
1779 calc_strength(COLOUR_LIGHT
, i
, j
) -
1780 calc_strength(COLOUR_DARK
, i
, j
);
1788 /* No targets found! Randomly pick squares and if they're owned
1789 * by the computer then stick a tank on it. */
1790 rb
->srand(*rb
->current_tick
);
1791 while(compres
.cash
>= 300 && compres
.tanks
< numterritory
) {
1792 i
= rb
->rand()%10 + 1;
1793 j
= rb
->rand()%10 + 1;
1794 if(board
[i
][j
].colour
== COLOUR_DARK
) {
1795 buy_resources(COLOUR_DARK
, 1, i
, j
, 0);
1801 str_diff
= targets
[i
].str_diff
;
1802 while(str_diff
+ 20 > 0 && compres
.cash
> 0) {
1803 /* While we still need them keep placing men */
1804 if(!place_adjacent(true, targets
[i
].x
, targets
[i
].y
)) {
1805 find_adjacent(targets
[i
].x
, targets
[i
].y
,
1807 men_needed
= (str_diff
+ 20)*1000/133;
1808 if(compres
.cash
< men_needed
) {
1809 men_needed
= compres
.cash
;
1811 buy_resources(COLOUR_DARK
, 0, adj
.x
, adj
.y
,
1815 str_diff
= calc_strength(COLOUR_LIGHT
,
1816 targets
[i
].x
, targets
[i
].y
) -
1817 calc_strength(COLOUR_DARK
,
1818 targets
[i
].x
, targets
[i
].y
);
1823 /* Work out what to place on each square to defend it.
1824 * Tanks are preferential because they do not require food,
1825 * but if the budget is tight then we fall back onto troops.
1826 * Conversely if cash is not an issue and there are already tanks in
1827 * place planes will be deployed. We would like a margin of at least
1828 * 20 points to be safe. */
1830 for(i
=0;i
<numthreats
;i
++) {
1831 total_str_diff
+= threats
[i
].str_diff
;
1833 if((total_str_diff
+20)*10 > compres
.cash
) {
1834 /* Not enough cash to accomodate all threats using tanks alone -
1835 * use men as a backup */
1836 for(i
=0;i
<numthreats
;i
++) {
1837 men_needed
= ((threats
[i
].str_diff
+ 20)*1000)/133;
1838 if(compres
.cash
< men_needed
) {
1839 men_needed
= compres
.cash
;
1841 buy_resources(COLOUR_DARK
, 0, threats
[i
].x
, threats
[i
].y
,
1846 /* Enough money to pay their way by planes? */
1847 bool tank
= ((total_str_diff
+20)*15 >= compres
.cash
);
1848 for(i
=0;i
<numthreats
;i
++) {
1849 str_diff
= threats
[i
].str_diff
;
1850 while(str_diff
+ 20 > 0) {
1851 if(!place_adjacent(tank
, threats
[i
].x
, threats
[i
].y
)) {
1852 /* No room for any more planes or tanks, revert to
1854 find_adjacent(threats
[i
].x
, threats
[i
].y
,
1856 men_needed
= (str_diff
+ 20)*1000/133;
1857 if(compres
.cash
< men_needed
) {
1858 men_needed
= compres
.cash
;
1860 buy_resources(COLOUR_DARK
, 0, threats
[i
].x
,
1861 threats
[i
].y
, men_needed
);
1864 str_diff
= calc_strength(COLOUR_LIGHT
,
1865 threats
[i
].x
, threats
[i
].y
) -
1866 calc_strength(COLOUR_DARK
,
1867 threats
[i
].x
, threats
[i
].y
);
1872 compres
.bank
+= compres
.cash
;
1876 int find_adj_target(int x
, int y
, struct cursor
* adj
) {
1877 /* Find a square next to a computer's farm or factory owned by the player
1878 * that is vulnerable. Return 1 on success, 0 otherwise */
1879 if(board
[x
+1][y
].colour
== COLOUR_LIGHT
&&
1880 calc_strength(COLOUR_LIGHT
,x
+1,y
)<=calc_strength(COLOUR_DARK
,x
+1,y
)) {
1885 if(board
[x
-1][y
].colour
== COLOUR_LIGHT
&&
1886 calc_strength(COLOUR_LIGHT
,x
-1,y
)<=calc_strength(COLOUR_DARK
,x
-1,y
)) {
1891 if(board
[x
][y
+1].colour
== COLOUR_LIGHT
&&
1892 calc_strength(COLOUR_LIGHT
,x
,y
+1)<=calc_strength(COLOUR_DARK
,x
,y
+1)) {
1897 if(board
[x
][y
-1].colour
== COLOUR_LIGHT
&&
1898 calc_strength(COLOUR_LIGHT
,x
,y
-1)<=calc_strength(COLOUR_DARK
,x
,y
-1)) {
1906 void computer_war(void) {
1907 /* Work out where to attack - prioritise the defence of buildings */
1909 bool found_target
= true;
1912 while(found_target
) {
1913 found_target
= false;
1916 if((board
[i
][j
].colour
== COLOUR_DARK
) &&
1917 (board
[i
][j
].farm
|| board
[i
][j
].ind
) &&
1918 find_adj_target(i
, j
, &adj
)) {
1919 found_target
= true;
1920 if(attack_territory(COLOUR_DARK
, adj
.x
, adj
.y
) >= 0) {
1930 /* Defence stage done, move on to OFFENCE */
1931 found_target
= true;
1932 while(found_target
) {
1933 found_target
= false;
1936 if(board
[i
][j
].colour
== COLOUR_LIGHT
&&
1937 (board
[i
][j
].ind
|| board
[i
][j
].farm
) &&
1938 (calc_strength(COLOUR_DARK
, i
, j
) >=
1939 calc_strength(COLOUR_LIGHT
, i
, j
))) {
1940 found_target
= true;
1941 if(attack_territory(COLOUR_DARK
, i
, j
) >= 0) {
1951 /* Spend leftover moves wherever attacking randomly */
1952 found_target
= true;
1953 while(found_target
) {
1954 found_target
= false;
1957 if(board
[i
][j
].colour
== COLOUR_LIGHT
&&
1958 (calc_strength(COLOUR_DARK
, i
, j
) >=
1959 calc_strength(COLOUR_LIGHT
, i
, j
))) {
1960 found_target
= true;
1961 if(attack_territory(COLOUR_DARK
, i
, j
) >= 0) {
1973 static int load_game(const char* file
) {
1976 fd
= rb
->open(file
, O_RDONLY
);
1978 DEBUGF("Couldn't open savegame\n");
1981 rb
->read(fd
, buf
, 5);
1982 if(rb
->strcmp(buf
, "SSGv3")) {
1983 rb
->splash(HZ
, "Invalid/incompatible savegame");
1986 rb
->read(fd
, &gamestate
, sizeof(gamestate
));
1987 rb
->read(fd
, &humanres
.cash
, sizeof(humanres
.cash
));
1988 rb
->read(fd
, &humanres
.food
, sizeof(humanres
.food
));
1989 rb
->read(fd
, &humanres
.bank
, sizeof(humanres
.bank
));
1990 rb
->read(fd
, &humanres
.planes
, sizeof(humanres
.planes
));
1991 rb
->read(fd
, &humanres
.tanks
, sizeof(humanres
.tanks
));
1992 rb
->read(fd
, &humanres
.men
, sizeof(humanres
.men
));
1993 rb
->read(fd
, &humanres
.nukes
, sizeof(humanres
.nukes
));
1994 rb
->read(fd
, &humanres
.inds
, sizeof(humanres
.inds
));
1995 rb
->read(fd
, &humanres
.farms
, sizeof(humanres
.farms
));
1996 rb
->read(fd
, &humanres
.moves
, sizeof(humanres
.moves
));
1997 rb
->read(fd
, &compres
.cash
, sizeof(humanres
.cash
));
1998 rb
->read(fd
, &compres
.food
, sizeof(humanres
.food
));
1999 rb
->read(fd
, &compres
.bank
, sizeof(humanres
.bank
));
2000 rb
->read(fd
, &compres
.planes
, sizeof(humanres
.planes
));
2001 rb
->read(fd
, &compres
.tanks
, sizeof(humanres
.tanks
));
2002 rb
->read(fd
, &compres
.men
, sizeof(humanres
.men
));
2003 rb
->read(fd
, &compres
.nukes
, sizeof(humanres
.nukes
));
2004 rb
->read(fd
, &compres
.inds
, sizeof(humanres
.inds
));
2005 rb
->read(fd
, &compres
.farms
, sizeof(humanres
.farms
));
2006 rb
->read(fd
, &compres
.moves
, sizeof(humanres
.moves
));
2007 rb
->read(fd
, board
, sizeof(board
));
2008 rb
->read(fd
, &superdom_settings
.compstartfarms
, sizeof(int));
2009 rb
->read(fd
, &superdom_settings
.compstartinds
, sizeof(int));
2010 rb
->read(fd
, &superdom_settings
.humanstartfarms
, sizeof(int));
2011 rb
->read(fd
, &superdom_settings
.humanstartfarms
, sizeof(int));
2012 rb
->read(fd
, &superdom_settings
.startcash
, sizeof(int));
2013 rb
->read(fd
, &superdom_settings
.startfood
, sizeof(int));
2014 rb
->read(fd
, &superdom_settings
.movesperturn
, sizeof(int));
2019 void default_settings(void) {
2020 superdom_settings
.compstartfarms
= 1;
2021 superdom_settings
.compstartinds
= 1;
2022 superdom_settings
.humanstartfarms
= 2;
2023 superdom_settings
.humanstartinds
= 2;
2024 superdom_settings
.startcash
= 0;
2025 superdom_settings
.startfood
= 0;
2026 superdom_settings
.movesperturn
= 2;
2029 int average_strength(int colour
) {
2030 /* This function calculates the average strength of the given player,
2031 * used to determine when the computer wins or loses. */
2036 if(board
[i
][j
].colour
!= -1) {
2037 totalpower
+= calc_strength(colour
, i
, j
);
2041 return totalpower
/100;
2044 enum plugin_status
plugin_start(const void* parameter
)
2047 rb
->lcd_set_backdrop(NULL
);
2048 rb
->lcd_set_foreground(LCD_BLACK
);
2049 rb
->lcd_set_background(LCD_WHITE
);
2056 if(load_game(parameter
) != 0) {
2057 DEBUGF("Loading failed, generating new game\n");
2085 case PLUGIN_USB_CONNECTED
:
2086 return PLUGIN_USB_CONNECTED
;
2095 int avg_str_diff
= (average_strength(COLOUR_LIGHT
) -
2096 average_strength(COLOUR_DARK
));
2097 if(avg_str_diff
> 15) {
2098 rb
->splash(HZ
*4, "The computer has surrendered. You win.");
2101 if(-avg_str_diff
> 15) {
2102 rb
->splash(HZ
*4, "Your army have suffered terrible morale from"
2103 " the bleak prospects of winning. You lose.");
2109 gamestate
= GS_PROD
;
2110 switch(production_menu()) {
2111 case PLUGIN_USB_CONNECTED
:
2112 return PLUGIN_USB_CONNECTED
;
2118 computer_allocate();
2121 humanres
.moves
= superdom_settings
.movesperturn
;
2123 gamestate
= GS_MOVE
;
2124 switch(movement_menu()) {
2125 case PLUGIN_USB_CONNECTED
:
2126 return PLUGIN_USB_CONNECTED
;
2134 if(humanres
.food
> humanres
.men
) {
2135 rb
->snprintf(buf
, sizeof(buf
), "Your men ate %d units of food",
2137 humanres
.food
-= humanres
.men
;
2139 rb
->snprintf(buf
, sizeof(buf
), "There was not enough food"
2140 " to feed all your men, %d men have died of starvation",
2141 killmen(COLOUR_LIGHT
));
2143 rb
->splash(HZ
*2, buf
);
2146 if(compres
.food
> compres
.men
) {
2147 compres
.food
-= compres
.men
;
2149 rb
->snprintf(buf
, sizeof(buf
), "The computer does not have"
2150 " enough food to feed its men. %d have died of starvation",
2151 killmen(COLOUR_DARK
));
2152 rb
->splash(HZ
, buf
);
2156 humanres
.moves
= superdom_settings
.movesperturn
;
2159 switch(war_menu()) {
2160 case PLUGIN_USB_CONNECTED
:
2161 return PLUGIN_USB_CONNECTED
;
2167 compres
.moves
= superdom_settings
.movesperturn
;