Minor corrections to the .colours file editing; added .colours to the list of support...
[kugel-rb.git] / apps / plugins / superdom.c
blob31f04b3b02d2a36936f90b25b31d177876887c49
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
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 ****************************************************************************/
21 #include "plugin.h"
22 #include "lib/playback_control.h"
23 PLUGIN_HEADER
25 extern const fb_data superdom_boarditems[];
26 char buf[255];
28 #define COLOUR_DARK 0
29 #define COLOUR_LIGHT 1
31 #define MARGIN 5
33 #if LCD_WIDTH > LCD_HEIGHT
34 #define BOX_WIDTH ((LCD_WIDTH-(MARGIN*2))/10)
35 #define BOX_HEIGHT ((BOX_WIDTH*2)/3)
37 #else
38 #define BOX_HEIGHT ((LCD_HEIGHT-(MARGIN*2)-15)/10)
39 #define BOX_WIDTH ((BOX_HEIGHT*2)/3)
41 #endif
43 #if LCD_WIDTH == 220 && LCD_HEIGHT == 176
44 #define NUM_BOX_HEIGHT 25
45 #define NUM_BOX_WIDTH 30
46 #define STRIDE 14
47 #define ICON_HEIGHT 7
48 #define ICON_WIDTH 7
50 #elif (LCD_WIDTH == 160 && LCD_HEIGHT == 128) || \
51 (LCD_WIDTH == 176 && LCD_HEIGHT == 132) || \
52 (LCD_WIDTH == 176 && LCD_HEIGHT == 220)
53 #define NUM_BOX_HEIGHT 20
54 #define NUM_BOX_WIDTH 24
55 #define STRIDE 8
56 #define ICON_HEIGHT 4
57 #define ICON_WIDTH 4
59 #elif (LCD_WIDTH == 320 && LCD_HEIGHT == 240)
60 #define NUM_BOX_HEIGHT 25
61 #define NUM_BOX_WIDTH 30
62 #define STRIDE 20
63 #define ICON_HEIGHT 10
64 #define ICON_WIDTH 10
66 #elif (LCD_WIDTH == 240 && LCD_HEIGHT == 320)
67 #define NUM_BOX_HEIGHT 25
68 #define NUM_BOX_WIDTH 30
69 #define STRIDE 18
70 #define ICON_HEIGHT 9
71 #define ICON_WIDTH 9
73 #endif
75 #define NUM_MARGIN_X (LCD_WIDTH-3*NUM_BOX_WIDTH)/2
76 #define NUM_MARGIN_Y (LCD_HEIGHT-4*NUM_BOX_HEIGHT)/2
78 #if (CONFIG_KEYPAD == IPOD_4G_PAD) || (CONFIG_KEYPAD == IPOD_3G_PAD) || \
79 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
80 #define SUPERDOM_OK BUTTON_SELECT
81 #define SUPERDOM_CANCEL BUTTON_MENU
82 #define SUPERDOM_LEFT BUTTON_LEFT
83 #define SUPERDOM_RIGHT BUTTON_RIGHT
84 #define IPOD_STYLE
86 #elif CONFIG_KEYPAD == IRIVER_H300_PAD || CONFIG_KEYPAD == IRIVER_H100_PAD
87 #define SUPERDOM_OK BUTTON_SELECT
88 #define SUPERDOM_LEFT BUTTON_LEFT
89 #define SUPERDOM_RIGHT BUTTON_RIGHT
90 #define SUPERDOM_UP BUTTON_UP
91 #define SUPERDOM_DOWN BUTTON_DOWN
92 #define SUPERDOM_CANCEL BUTTON_OFF
94 #elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
95 #define SUPERDOM_OK BUTTON_SELECT
96 #define SUPERDOM_LEFT BUTTON_LEFT
97 #define SUPERDOM_RIGHT BUTTON_RIGHT
98 #define SUPERDOM_UP BUTTON_UP
99 #define SUPERDOM_DOWN BUTTON_DOWN
100 #define SUPERDOM_CANCEL BUTTON_REC
102 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
103 #define SUPERDOM_OK BUTTON_RIGHT
104 #define SUPERDOM_UP BUTTON_SCROLL_UP
105 #define SUPERDOM_DOWN BUTTON_SCROLL_DOWN
106 #define SUPERDOM_CANCEL BUTTON_LEFT
108 #elif CONFIG_KEYPAD == GIGABEAT_PAD
109 #define SUPERDOM_OK BUTTON_SELECT
110 #define SUPERDOM_UP BUTTON_UP
111 #define SUPERDOM_DOWN BUTTON_DOWN
112 #define SUPERDOM_LEFT BUTTON_LEFT
113 #define SUPERDOM_RIGHT BUTTON_RIGHT
114 #define SUPERDOM_CANCEL BUTTON_POWER
116 #elif CONFIG_KEYPAD == SANSA_E200_PAD || \
117 CONFIG_KEYPAD == SANSA_FUZE_PAD
118 #define SUPERDOM_OK BUTTON_SELECT
119 #define SUPERDOM_UP BUTTON_SCROLL_BACK
120 #define SUPERDOM_DOWN BUTTON_SCROLL_FWD
121 #define SUPERDOM_LEFT BUTTON_LEFT
122 #define SUPERDOM_RIGHT BUTTON_RIGHT
123 #define SUPERDOM_CANCEL BUTTON_POWER
125 #elif CONFIG_KEYPAD == GIGABEAT_S_PAD
126 #define SUPERDOM_OK BUTTON_SELECT
127 #define SUPERDOM_UP BUTTON_UP
128 #define SUPERDOM_DOWN BUTTON_DOWN
129 #define SUPERDOM_LEFT BUTTON_LEFT
130 #define SUPERDOM_RIGHT BUTTON_RIGHT
131 #define SUPERDOM_CANCEL BUTTON_BACK
133 #elif CONFIG_KEYPAD == COWOND2_PAD
134 #define SUPERDOM_CANCEL BUTTON_POWER
136 #elif CONFIG_KEYPAD == CREATIVEZVM_PAD
137 #define SUPERDOM_OK BUTTON_SELECT
138 #define SUPERDOM_UP BUTTON_UP
139 #define SUPERDOM_DOWN BUTTON_DOWN
140 #define SUPERDOM_LEFT BUTTON_LEFT
141 #define SUPERDOM_RIGHT BUTTON_RIGHT
142 #define SUPERDOM_CANCEL BUTTON_BACK
144 #endif
146 #ifdef HAVE_TOUCHSCREEN
147 #ifndef SUPERDOM_OK
148 #define SUPERDOM_OK BUTTON_CENTER
149 #endif
150 #ifndef SUPERDOM_UP
151 #define SUPERDOM_UP BUTTON_TOPMIDDLE
152 #endif
153 #ifndef SUPERDOM_LEFT
154 #define SUPERDOM_LEFT BUTTON_MIDLEFT
155 #endif
156 #ifndef SUPERDOM_RIGHT
157 #define SUPERDOM_RIGHT BUTTON_MIDRIGHT
158 #endif
159 #ifndef SUPERDOM_DOWN
160 #define SUPERDOM_DOWN BUTTON_BOTTOMMIDDLE
161 #endif
162 #ifndef SUPERDOM_CANCEL
163 #define SUPERDOM_CANCEL BUTTON_TOPLEFT
164 #endif
165 #endif
167 #define SUPERDOM_QUIT 23
169 void gen_interest(void);
170 int production_menu(void);
171 void init_resources(void);
172 int select_square(void);
173 void update_score(void);
174 void gen_resources(void);
175 void draw_cursor(void);
176 int calc_strength(bool colour, int x, int y);
177 void draw_board(void);
179 struct tile{
180 signed int colour; /* -1 = Unset */
181 bool tank;
182 bool plane;
183 bool nuke;
184 bool ind;
185 bool farm;
186 int men;
189 struct resources {
190 int cash;
191 int food;
192 int farms;
193 int inds;
194 int men;
195 int tanks;
196 int planes;
197 int nukes;
198 int bank;
199 int moves;
202 struct settings {
203 int compstartfarms;
204 int compstartinds;
205 int humanstartfarms;
206 int humanstartinds;
207 int startcash;
208 int startfood;
209 int movesperturn;
210 } superdom_settings;
212 struct resources humanres;
213 struct resources compres;
215 struct cursor{
216 int x;
217 int y;
218 } cursor;
220 struct tile board[12][12];
222 void init_board(void) {
223 rb->srand(*rb->current_tick);
224 int i,j;
225 for(i=0;i<12;i++) { /* Hopefully about 50% each colour */
226 for(j=0;j<12;j++) {
227 if((i<1)||(j<1)||(i>10)||(j>10))
228 board[i][j].colour = -1; /* Unset */
229 else
230 board[i][j].colour = rb->rand()%2;
231 board[i][j].tank = false;
232 board[i][j].plane = false;
233 board[i][j].nuke = false;
234 board[i][j].ind = false;
235 board[i][j].farm = false;
236 board[i][j].men = 0;
240 while(compres.farms < superdom_settings.compstartfarms) {
241 i = rb->rand()%10 + 1;
242 j = rb->rand()%10 + 1;
243 if((board[i][j].colour == COLOUR_DARK) && (board[i][j].farm == false)) {
244 board[i][j].farm = true;
245 compres.farms++;
246 break;
249 while(compres.inds < superdom_settings.compstartinds) {
250 i = rb->rand()%10 + 1;
251 j = rb->rand()%10 + 1;
252 if((board[i][j].colour == COLOUR_DARK) && (board[i][j].ind == false)) {
253 board[i][j].ind = true;
254 compres.inds++;
255 break;
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;
263 humanres.farms++;
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;
271 humanres.inds++;
276 void draw_board(void) {
277 rb->lcd_clear_display();
278 int i,j;
279 for(i=1;i<11;i++) {
280 for(j=1;j<11;j++) {
281 if(board[i][j].colour == COLOUR_DARK) {
282 rb->lcd_set_foreground(LCD_DARKGRAY);
283 } else {
284 rb->lcd_set_foreground(LCD_LIGHTGRAY);
286 rb->lcd_fillrect(MARGIN+(BOX_WIDTH*(i-1)),
287 MARGIN+(BOX_HEIGHT*(j-1)), BOX_WIDTH,
288 BOX_HEIGHT);
289 #if LCD_DEPTH != 16
290 rb->lcd_set_drawmode(DRMODE_BG | DRMODE_INVERSEVID);
291 #endif
292 if(board[i][j].ind) {
293 #if (LCD_DEPTH == 16)
294 rb->lcd_bitmap_transparent_part(superdom_boarditems,
295 #else
296 rb->lcd_mono_bitmap_part(superdom_boarditems,
297 #endif
298 board[i][j].colour?ICON_WIDTH:0, 0, STRIDE,
299 #if LCD_WIDTH > LCD_HEIGHT
300 MARGIN+(BOX_WIDTH*(i-1))+1,
301 MARGIN+(BOX_HEIGHT*(j-1))+ICON_HEIGHT+1,
302 #else
303 MARGIN+(BOX_WIDTH*(i-1))+1+ICON_WIDTH,
304 MARGIN+(BOX_HEIGHT*(j-1))+1,
305 #endif
306 ICON_WIDTH, ICON_HEIGHT);
308 if(board[i][j].farm) {
309 #if (LCD_DEPTH == 16)
310 rb->lcd_bitmap_transparent_part(superdom_boarditems,
311 #else
312 rb->lcd_mono_bitmap_part(superdom_boarditems,
313 #endif
314 board[i][j].colour?ICON_WIDTH:0, ICON_HEIGHT,
315 STRIDE, MARGIN+(BOX_WIDTH*(i-1))+1,
316 MARGIN+(BOX_HEIGHT*(j-1))+1,
317 ICON_WIDTH, ICON_HEIGHT);
319 if(board[i][j].tank) {
320 #if (LCD_DEPTH == 16)
321 rb->lcd_bitmap_transparent_part(superdom_boarditems,
322 #else
323 rb->lcd_mono_bitmap_part(superdom_boarditems,
324 #endif
325 board[i][j].colour?ICON_WIDTH:0, ICON_HEIGHT*2,
326 STRIDE, MARGIN+(BOX_WIDTH*(i-1))+ICON_WIDTH+1,
327 MARGIN+(BOX_HEIGHT*(j-1))+ICON_HEIGHT+1,
328 ICON_WIDTH, ICON_HEIGHT);
330 if(board[i][j].men) {
331 #if (LCD_DEPTH == 16)
332 rb->lcd_bitmap_transparent_part(superdom_boarditems,
333 #else
334 rb->lcd_mono_bitmap_part(superdom_boarditems,
335 #endif
336 board[i][j].colour?ICON_WIDTH:0, ICON_HEIGHT*3,
337 #if LCD_WIDTH > LCD_HEIGHT
338 STRIDE, MARGIN+(BOX_WIDTH*(i-1))+ICON_WIDTH+1,
339 MARGIN+(BOX_HEIGHT*(j-1))+1,
340 #else
341 STRIDE, MARGIN+(BOX_WIDTH*(i-1))+1,
342 MARGIN+(BOX_HEIGHT*(j-1))+1+ICON_HEIGHT,
343 #endif
344 ICON_WIDTH, ICON_HEIGHT);
346 if(board[i][j].plane) {
347 #if (LCD_DEPTH == 16)
348 rb->lcd_bitmap_transparent_part(superdom_boarditems,
349 #else
350 rb->lcd_mono_bitmap_part(superdom_boarditems,
351 #endif
352 board[i][j].colour?ICON_WIDTH:0, ICON_HEIGHT*4,
353 #if LCD_WIDTH > LCD_HEIGHT
354 STRIDE,MARGIN+(BOX_WIDTH*(i-1))+ICON_WIDTH*2+1,
355 MARGIN+(BOX_HEIGHT*(j-1))+ICON_HEIGHT+1,
356 #else
357 STRIDE,MARGIN+(BOX_WIDTH*(i-1))+ICON_WIDTH+1,
358 MARGIN+(BOX_HEIGHT*(j-1))+ICON_HEIGHT*2+1,
359 #endif
360 ICON_WIDTH, ICON_HEIGHT);
362 if(board[i][j].nuke) {
363 #if (LCD_DEPTH == 16)
364 rb->lcd_bitmap_transparent_part(superdom_boarditems,
365 #else
366 rb->lcd_mono_bitmap_part(superdom_boarditems,
367 #endif
368 board[i][j].colour?ICON_WIDTH:0, ICON_HEIGHT*5,
369 #if LCD_WIDTH > LCD_HEIGHT
370 STRIDE,MARGIN+(BOX_WIDTH*(i-1))+ICON_WIDTH*2+1,
371 MARGIN+(BOX_HEIGHT*(j-1))+1,
372 #else
373 STRIDE,MARGIN+(BOX_WIDTH*(i-1))+1,
374 MARGIN+(BOX_HEIGHT*(j-1))+ICON_HEIGHT*2+1,
375 #endif
376 ICON_WIDTH, ICON_HEIGHT);
378 #if LCD_DEPTH != 16
379 rb->lcd_set_drawmode(DRMODE_SOLID);
380 #endif
383 rb->lcd_set_foreground(LCD_BLACK);
384 for(i=0;i<=10;i++) { /* Draw Horizontal lines */
385 rb->lcd_hline(MARGIN, MARGIN+(BOX_WIDTH*10), MARGIN+(BOX_HEIGHT*i));
387 for(i=0;i<=10;i++) { /* Draw Vertical lines */
388 rb->lcd_vline(MARGIN+(BOX_WIDTH*i), MARGIN, MARGIN+(BOX_HEIGHT*10));
390 rb->lcd_update();
393 int calc_strength(bool colour, int x, int y) {
394 int a, b, score=0;
395 for (a = -1; a < 2; a++){
396 for (b = -1; b < 2; b++){
397 if (b == 0){
398 if(board[x + a][y].colour == colour)
399 score+=10;
400 if(((board[x + a][y].colour == colour) && board[x + a][y].tank) || ((board[x + a][y].colour == colour) && board[x + a][y].farm))
401 score+=30;
402 if(((board[x + a][y].colour == colour) && board[x + a][y].plane) || ((board[x + a][y].colour == colour) && board[x + a][y].ind))
403 score+=40;
404 if((board[x + a][y].colour == colour) && board[x + a][y].nuke)
405 score+=20;
406 if((board[x + a][y].colour == colour) && board[x + a][y].men)
407 score+=(board[x + a][y].men*133/1000);
408 } else if (a == 0){
409 if(board[x][y + b].colour == colour)
410 score+=10;
411 if(((board[x][y + b].colour == colour) && board[x][y + b].tank) || ((board[x][y + b].colour == colour) && board[x][y + b].farm))
412 score+=30;
413 if(((board[x][y + b].colour == colour) && board[x][y + b].plane) || ((board[x][y + b].colour == colour) && board[x][y + b].ind))
414 score+=40;
415 if((board[x][y + b].colour == colour) && board[x][y + b].nuke)
416 score+=20;
417 if((board[x][y + b].colour == colour) && board[x][y + b].men)
418 score+=(board[x][y + b].men*133/1000);
422 return score;
425 void gen_interest(void) {
426 /* Interest should be around 10% */
427 rb->srand(*rb->current_tick);
428 int interest = 7+rb->rand()%6;
429 humanres.bank = humanres.bank+(interest*humanres.bank/100);
432 void draw_cursor(void) {
433 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
434 rb->lcd_fillrect(MARGIN+((cursor.x-1)*BOX_WIDTH),
435 MARGIN+((cursor.y-1)*BOX_HEIGHT), BOX_WIDTH+1, BOX_HEIGHT+1);
436 rb->lcd_set_drawmode(DRMODE_SOLID);
437 rb->lcd_update();
440 void gen_resources(void) {
441 gen_interest();
442 int inccash = 0;
443 int incfood = 0;
444 int i;
445 rb->srand(*rb->current_tick);
446 /* Generate Human's resources */
447 for(i=0;i<humanres.inds;i++) {
448 inccash += (300+rb->rand()%200);
450 for(i=0;i<humanres.farms;i++) {
451 incfood += (200+rb->rand()%200);
453 if(inccash/humanres.inds > 450) {
454 if(incfood/humanres.farms > 350) {
455 rb->splash(HZ*2, "Patriotism sweeps the land, all production"
456 " is up this year!");
457 } else {
458 rb->splash(HZ*2, "Factories working at maximum efficiency,"
459 " cash production up this year!");
461 } else if((inccash/humanres.inds>350)&&(inccash/humanres.inds<=450)) {
462 if(incfood/humanres.farms > 350) {
463 rb->splash(HZ*2, "Record crop harvest this year!");
464 } else if((incfood/humanres.farms > 250) &&
465 (incfood/humanres.farms <= 350)) {
466 rb->splash(HZ*2, "Production continues as normal");
467 } else {
468 rb->splash(HZ*2, "Spoilage of crops leads to reduced farm"
469 " output this year");
471 } else {
472 if(incfood/humanres.farms > 350) {
473 rb->splash(HZ*2, "Record crop harvest this year!");
474 } else if((incfood/humanres.farms > 250) &&
475 (incfood/humanres.farms <= 350)) {
476 rb->splash(HZ*2, "Factory unions introduced. Industrial"
477 " production is down this year.");
478 } else {
479 rb->splash(HZ*2, "Internet created. All production is down"
480 " due to time wasted.");
483 humanres.cash += inccash;
484 humanres.food += incfood;
486 /* Generate Computer's resources */
487 inccash = 0;
488 incfood = 0;
489 for(i=0;i<compres.inds;i++) {
490 inccash += (300+rb->rand()%200);
492 for(i=0;i<compres.farms;i++) {
493 incfood += (200+rb->rand()%200);
495 compres.cash += inccash;
496 compres.food += incfood;
499 void update_score(void) {
500 rb->lcd_set_drawmode(DRMODE_BG|DRMODE_INVERSEVID);
501 rb->lcd_fillrect(5,LCD_HEIGHT-20,105,20);
502 rb->lcd_set_drawmode(DRMODE_SOLID);
503 rb->snprintf(buf, sizeof(buf), "Your power: %d.%d",
504 calc_strength(COLOUR_LIGHT, cursor.x, cursor.y)/10,
505 calc_strength(COLOUR_LIGHT, cursor.x, cursor.y)%10);
506 rb->lcd_putsxy(5,LCD_HEIGHT-20, buf);
507 rb->snprintf(buf, sizeof(buf), "Comp power: %d.%d",
508 calc_strength(COLOUR_DARK, cursor.x, cursor.y)/10,
509 calc_strength(COLOUR_DARK, cursor.x, cursor.y)%10);
510 rb->lcd_putsxy(5,LCD_HEIGHT-10, buf);
513 int settings_menu_function(void) {
514 int selection = 0;
516 MENUITEM_STRINGLIST(settings_menu,"Super Domination Settings",NULL,
517 "Computer starting farms","Computer starting factories",
518 "Human starting farms","Human starting factories",
519 "Starting cash","Starting food","Moves per turn");
520 settings_menu:
521 selection=rb->do_menu(&settings_menu,&selection, NULL, false);
522 switch(selection) {
523 case 0:
524 rb->set_int("Computer starting farms", "", UNIT_INT,
525 &superdom_settings.compstartfarms, NULL,
526 1, 0, 5, NULL);
527 goto settings_menu;
528 break;
529 case 1:
530 rb->set_int("Computer starting factories", "", UNIT_INT,
531 &superdom_settings.compstartinds, NULL,
532 1, 0, 5, NULL);
533 goto settings_menu;
534 break;
535 case 2:
536 rb->set_int("Human starting farms", "", UNIT_INT,
537 &superdom_settings.humanstartfarms, NULL,
538 1, 0, 5, NULL);
539 goto settings_menu;
540 break;
541 case 3:
542 superdom_settings.humanstartinds =
543 rb->set_int("Human starting factories", "", UNIT_INT,
544 &superdom_settings.humanstartinds, NULL,
545 1, 0, 5, NULL);
546 goto settings_menu;
547 break;
548 case 4:
549 rb->set_int("Starting cash", "", UNIT_INT,
550 &superdom_settings.startcash, NULL,
551 250, 0, 5000, NULL);
552 goto settings_menu;
553 break;
554 case 5:
555 rb->set_int("Starting food", "", UNIT_INT,
556 &superdom_settings.startfood, NULL,
557 250, 0, 5000, NULL);
558 goto settings_menu;
559 break;
560 case 6:
561 rb->set_int("Moves per turn", "", UNIT_INT,
562 &superdom_settings.movesperturn, NULL,
563 1, 1, 5, NULL);
564 goto settings_menu;
565 break;
566 case MENU_ATTACHED_USB:
567 return PLUGIN_USB_CONNECTED;
568 break;
570 return 0;
573 static int do_help(void) {
574 int button;
575 int y = MARGIN, space_w, width, height;
576 unsigned short x = MARGIN, i = 0;
577 #define WORDS (sizeof instructions / sizeof (char*))
578 static char* instructions[] = {
579 "Super", "domination", "is", "a", "turn", "based", "strategy", "game,",
580 "where", "the", "aim", "is", "to", "overpower", "the", "computer",
581 "player", "by", "taking", "their", "territory.", "",
582 "Each", "year", "you", "are", "allocated", "an", "amount", "of", "cash",
583 "and", "food,", "depending", "on", "how", "many", "farms", "and",
584 "factories", "you", "control.", "",
585 "Use", "this", "cash", "and", "food", "to", "buy", "and", "feed", "your",
586 "army.", "Each", "tile", "has", "a", "strength,", "calculated", "by",
587 "the", "ownership", "of", "adjacent", "tiles,", "and", "the", "type",
588 "and", "number", "of", "troops", "on", "them.",
590 rb->lcd_clear_display();
591 rb->lcd_getstringsize(" ", &space_w, &height);
592 for (i = 0; i < WORDS; i++) {
593 rb->lcd_getstringsize(instructions[i], &width, NULL);
594 /* Skip to next line if the current one can't fit the word */
595 if (x + width > LCD_WIDTH - MARGIN) {
596 x = MARGIN;
597 y += height;
599 /* .. or if the word is the empty string */
600 if (rb->strcmp(instructions[i], "") == 0) {
601 x = MARGIN;
602 y += height;
603 continue;
605 /* We filled the screen */
606 if (y + height > LCD_HEIGHT - MARGIN) {
607 y = MARGIN;
608 rb->lcd_update();
609 do {
610 button = rb->button_get(true);
611 if (button == SYS_USB_CONNECTED) {
612 return PLUGIN_USB_CONNECTED;
614 } while( ( button == BUTTON_NONE )
615 || ( button & (BUTTON_REL|BUTTON_REPEAT) ) );
618 rb->lcd_clear_display();
620 rb->lcd_putsxy(x, y, instructions[i]);
621 x += width + space_w;
623 rb->lcd_update();
624 do {
625 button = rb->button_get(true);
626 if (button == SYS_USB_CONNECTED) {
627 return PLUGIN_USB_CONNECTED;
629 } while( ( button == BUTTON_NONE )
630 || ( button & (BUTTON_REL|BUTTON_REPEAT) ) );
632 return 0;
635 int menu(void) {
636 int selection = 0;
638 MENUITEM_STRINGLIST(main_menu,"Super Domination Menu",NULL,
639 "Play Super Domination","Settings","Help","Quit");
641 while(1) {
642 selection=rb->do_menu(&main_menu,&selection, NULL, false);
643 switch(selection) {
644 case 0:
645 return 0; /* start playing */
646 break;
647 case 1:
648 if(settings_menu_function()==PLUGIN_USB_CONNECTED)
649 return PLUGIN_USB_CONNECTED;
650 break;
651 case 2:
652 if(do_help()==PLUGIN_USB_CONNECTED)
653 return PLUGIN_USB_CONNECTED;
654 break;
655 default:
656 return 2; /* quit program */
657 break;
661 return 3;
664 int save_game(void) {
665 int fd;
666 char savepath[MAX_PATH];
668 rb->snprintf(savepath, sizeof(savepath), "/Savegame.ssg");
669 if(rb->kbd_input(savepath, MAX_PATH)) {
670 DEBUGF("Keyboard input failed\n");
671 return -1;
674 fd = rb->open(savepath, O_WRONLY|O_CREAT);
675 DEBUGF("savepath: %s\n", savepath);
676 if(fd < 0) {
677 DEBUGF("Couldn't create/open file\n");
678 return -1;
681 rb->write(fd, "SSGv2", 5);
682 rb->write(fd, &humanres.cash, sizeof(humanres.cash));
683 rb->write(fd, &humanres.food, sizeof(humanres.food));
684 rb->write(fd, &humanres.bank, sizeof(humanres.bank));
685 rb->write(fd, &humanres.planes, sizeof(humanres.planes));
686 rb->write(fd, &humanres.tanks, sizeof(humanres.tanks));
687 rb->write(fd, &humanres.men, sizeof(humanres.men));
688 rb->write(fd, &humanres.nukes, sizeof(humanres.nukes));
689 rb->write(fd, &humanres.inds, sizeof(humanres.inds));
690 rb->write(fd, &humanres.farms, sizeof(humanres.farms));
691 rb->write(fd, &humanres.moves, sizeof(humanres.moves));
692 rb->write(fd, &compres.cash, sizeof(compres.cash));
693 rb->write(fd, &compres.food, sizeof(compres.food));
694 rb->write(fd, &compres.bank, sizeof(compres.bank));
695 rb->write(fd, &compres.planes, sizeof(compres.planes));
696 rb->write(fd, &compres.tanks, sizeof(compres.tanks));
697 rb->write(fd, &compres.men, sizeof(compres.men));
698 rb->write(fd, &compres.nukes, sizeof(compres.nukes));
699 rb->write(fd, &compres.inds, sizeof(compres.inds));
700 rb->write(fd, &compres.farms, sizeof(compres.farms));
701 rb->write(fd, &compres.moves, sizeof(compres.moves));
702 rb->write(fd, board, sizeof(board));
703 rb->write(fd, &superdom_settings.compstartfarms, sizeof(int));
704 rb->write(fd, &superdom_settings.compstartinds, sizeof(int));
705 rb->write(fd, &superdom_settings.humanstartfarms, sizeof(int));
706 rb->write(fd, &superdom_settings.humanstartfarms, sizeof(int));
707 rb->write(fd, &superdom_settings.startcash, sizeof(int));
708 rb->write(fd, &superdom_settings.startfood, sizeof(int));
709 rb->write(fd, &superdom_settings.movesperturn, sizeof(int));
710 rb->close(fd);
711 return 0;
714 int ingame_menu(void) {
715 int selection = 0;
717 MENUITEM_STRINGLIST(ingame_menu,"Super Domination Menu",NULL,
718 "Return to game","Save Game","Playback Control", "Quit");
720 selection=rb->do_menu(&ingame_menu,&selection, NULL, false);
721 switch(selection) {
722 case 0:
723 return 0;
724 break;
725 case 1:
726 if(!save_game())
727 rb->splash(HZ, "Game saved");
728 else
729 rb->splash(HZ, "Error in save");
730 break;
731 case 2:
732 playback_control(NULL);
733 break;
734 case 3:
735 return SUPERDOM_QUIT;
736 break;
737 case MENU_ATTACHED_USB:
738 return PLUGIN_USB_CONNECTED;
739 break;
741 return 0;
744 int get_number(char* param, int* value) {
745 //int numbers[3][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
746 int numbers[3][3];
747 numbers[0][0] = 1;
748 numbers[0][1] = 2;
749 numbers[0][2] = 3;
750 numbers[1][0] = 4;
751 numbers[1][1] = 5;
752 numbers[1][2] = 6;
753 numbers[2][0] = 7;
754 numbers[2][1] = 8;
755 numbers[2][2] = 9;
756 rb->lcd_clear_display();
757 /* Draw a 3x4 grid */
758 int i,j,x=0,y=0;
759 for(i=0;i<=3;i++) { /* Vertical lines */
760 rb->lcd_vline(NUM_MARGIN_X+(NUM_BOX_WIDTH*i), NUM_MARGIN_Y,
761 NUM_MARGIN_Y+(4*NUM_BOX_HEIGHT));
763 for(i=0;i<=4;i++) { /* Horizontal lines */
764 rb->lcd_hline(NUM_MARGIN_X, NUM_MARGIN_X+(3*NUM_BOX_WIDTH),
765 NUM_MARGIN_Y+(NUM_BOX_HEIGHT*i));
767 int temp = 1;
768 for(i=0;i<3;i++) {
769 for(j=0;j<3;j++) {
770 rb->snprintf(buf, sizeof(buf), "%d", temp);
771 rb->lcd_putsxy(NUM_MARGIN_X+(j*NUM_BOX_WIDTH)+10,
772 NUM_MARGIN_Y+(i*NUM_BOX_HEIGHT)+8, buf);
773 temp++;
776 rb->lcd_putsxy(NUM_MARGIN_X+5, NUM_MARGIN_Y+(3*NUM_BOX_HEIGHT)+8, "CLR");
777 rb->lcd_putsxy(NUM_MARGIN_X+NUM_BOX_WIDTH+10,
778 NUM_MARGIN_Y+(3*NUM_BOX_HEIGHT)+8, "0");
779 rb->lcd_putsxy(NUM_MARGIN_X+2*NUM_BOX_WIDTH+8,
780 NUM_MARGIN_Y+(3*NUM_BOX_HEIGHT)+8, "OK");
781 rb->snprintf(buf,sizeof(buf), "%d", *value);
782 rb->lcd_putsxy(NUM_MARGIN_X+10, NUM_MARGIN_Y+4*NUM_BOX_HEIGHT+10, buf);
783 int height, width;
784 rb->lcd_getstringsize(param, &width, &height);
785 rb->lcd_putsxy((LCD_WIDTH-width)/2, (NUM_MARGIN_Y-height)/2, param);
786 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
787 rb->lcd_fillrect(NUM_MARGIN_X+(NUM_BOX_WIDTH*x),
788 NUM_MARGIN_Y+(NUM_BOX_HEIGHT*y), NUM_BOX_WIDTH+1,
789 NUM_BOX_HEIGHT+1);
790 rb->lcd_set_drawmode(DRMODE_SOLID);
791 int button = 0;
792 rb->lcd_update();
793 while(1) {
794 button = rb->button_get(true);
795 switch(button) {
796 case SUPERDOM_OK:
797 *value *= 10;
798 if(y!=3) {
799 *value += numbers[y][x];
800 } else if(y==3 && x==0) {
801 *value /= 100;
802 } else if(y==3 && x==2) {
803 *value /= 10;
804 return 0;
806 rb->lcd_set_drawmode(DRMODE_BG|DRMODE_INVERSEVID);
807 rb->lcd_fillrect(0, NUM_MARGIN_Y+4*NUM_BOX_HEIGHT+10,
808 LCD_WIDTH, 30);
809 rb->lcd_set_drawmode(DRMODE_SOLID);
810 rb->snprintf(buf,sizeof(buf), "%d", *value);
811 rb->lcd_putsxy(NUM_MARGIN_X+10,
812 NUM_MARGIN_Y+4*NUM_BOX_HEIGHT+10, buf);
813 break;
814 case SUPERDOM_CANCEL:
815 return 0;
816 break;
817 #if CONFIG_KEYPAD != IRIVER_H10_PAD
818 case SUPERDOM_LEFT:
819 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
820 rb->lcd_fillrect(NUM_MARGIN_X+(NUM_BOX_WIDTH*x),
821 NUM_MARGIN_Y+(NUM_BOX_HEIGHT*y),
822 NUM_BOX_WIDTH+1, NUM_BOX_HEIGHT+1);
823 rb->lcd_set_drawmode(DRMODE_SOLID);
824 if(x==0) {
825 #ifdef IPOD_STYLE
826 if(y>0)
827 y--;
828 else
829 y=3;
830 #endif
831 x=2;
832 } else {
833 x--;
835 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
836 rb->lcd_fillrect(NUM_MARGIN_X+(NUM_BOX_WIDTH*x),
837 NUM_MARGIN_Y+(NUM_BOX_HEIGHT*y),
838 NUM_BOX_WIDTH+1, NUM_BOX_HEIGHT+1);
839 rb->lcd_set_drawmode(DRMODE_SOLID);
840 break;
841 case SUPERDOM_RIGHT:
842 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
843 rb->lcd_fillrect(NUM_MARGIN_X+(NUM_BOX_WIDTH*x),
844 NUM_MARGIN_Y+(NUM_BOX_HEIGHT*y),
845 NUM_BOX_WIDTH+1, NUM_BOX_HEIGHT+1);
846 rb->lcd_set_drawmode(DRMODE_SOLID);
847 if(x==2) {
848 #ifdef IPOD_STYLE
849 if(y==3)
850 y=0;
851 else
852 y++;
853 #endif
854 x=0;
855 } else {
856 x++;
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);
863 break;
864 #endif
865 #ifndef IPOD_STYLE
866 case SUPERDOM_UP:
867 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
868 rb->lcd_fillrect(NUM_MARGIN_X+(NUM_BOX_WIDTH*x),
869 NUM_MARGIN_Y+(NUM_BOX_HEIGHT*y),
870 NUM_BOX_WIDTH+1, NUM_BOX_HEIGHT+1);
871 rb->lcd_set_drawmode(DRMODE_SOLID);
872 if(y==0) {
873 #if CONFIG_KEYPAD == IRIVER_H10_PAD
874 if(x > 0)
875 x--;
876 else
877 x=2;
878 #endif
879 y=3;
880 } else {
881 y--;
883 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
884 rb->lcd_fillrect(NUM_MARGIN_X+(NUM_BOX_WIDTH*x),
885 NUM_MARGIN_Y+(NUM_BOX_HEIGHT*y),
886 NUM_BOX_WIDTH+1, NUM_BOX_HEIGHT+1);
887 rb->lcd_set_drawmode(DRMODE_SOLID);
888 break;
889 case SUPERDOM_DOWN:
890 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
891 rb->lcd_fillrect(NUM_MARGIN_X+(NUM_BOX_WIDTH*x),
892 NUM_MARGIN_Y+(NUM_BOX_HEIGHT*y),
893 NUM_BOX_WIDTH+1, NUM_BOX_HEIGHT+1);
894 rb->lcd_set_drawmode(DRMODE_SOLID);
895 if(y==3) {
896 #if CONFIG_KEYPAD == IRIVER_H10_PAD
897 if(x < 2)
898 x++;
899 else
900 x=0;
901 #endif
902 y=0;
903 } else {
904 y++;
906 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
907 rb->lcd_fillrect(NUM_MARGIN_X+(NUM_BOX_WIDTH*x),
908 NUM_MARGIN_Y+(NUM_BOX_HEIGHT*y),
909 NUM_BOX_WIDTH+1, NUM_BOX_HEIGHT+1);
910 rb->lcd_set_drawmode(DRMODE_SOLID);
911 break;
912 #endif
913 default:
914 if (rb->default_event_handler(button) == SYS_USB_CONNECTED)
916 return PLUGIN_USB_CONNECTED;
918 break;
920 rb->lcd_update();
922 return 0;
925 int buy_resources_menu(void) {
926 int selection,tempmenu,nummen;
928 MENUITEM_STRINGLIST(res_menu, "Buy Resources", NULL, "Buy men ($1)",
929 "Buy tank ($300)", "Buy plane ($600)", "Buy Farm ($1150)",
930 "Buy Factory ($1300)", "Buy Nuke ($2000)",
931 "Finish buying", "Game menu");
933 resources_menu:
934 selection=rb->do_menu(&res_menu,&selection, NULL, false);
935 switch(selection) {
936 case 0:
937 nummen = 0;
938 if(get_number("How many men would you like?", &nummen)
939 == PLUGIN_USB_CONNECTED)
940 return PLUGIN_USB_CONNECTED;
941 if(humanres.cash>=nummen) {
942 rb->splash(HZ, "Where do you want to place them?");
943 tempmenu = select_square();
944 switch(tempmenu) {
945 case 0:
946 rb->splash(HZ, "Cancelled");
947 break;
948 case 2:
949 if(board[cursor.x][cursor.y].colour == COLOUR_LIGHT) {
950 humanres.men += nummen;
951 board[cursor.x][cursor.y].men += nummen;
952 humanres.cash -= nummen;
953 } else {
954 rb->splash(HZ,"Can't place men on enemy territory");
956 break;
957 case PLUGIN_USB_CONNECTED:
958 return PLUGIN_USB_CONNECTED;
959 break;
961 } else {
962 rb->splash(HZ, "Not enough money!");
964 goto resources_menu;
965 break;
966 case 1:
967 if(humanres.cash>=300) {
968 rb->splash(HZ, "Where do you want to place the tank?");
969 tempmenu = select_square();
970 switch(tempmenu) {
971 case 0:
972 rb->splash(HZ, "Cancelled");
973 goto resources_menu;
974 break;
975 case PLUGIN_USB_CONNECTED:
976 return PLUGIN_USB_CONNECTED;
977 break;
979 if(board[cursor.x][cursor.y].colour == COLOUR_LIGHT) {
980 if(board[cursor.x][cursor.y].tank) {
981 rb->splash(HZ, "There is already a tank there");
982 } else {
983 board[cursor.x][cursor.y].tank = true;
984 humanres.cash -= 300;
985 humanres.tanks++;
987 } else {
988 rb->splash(HZ, "Can't place men on enemy territory");
990 } else {
991 rb->splash(HZ, "Not enough money!");
993 goto resources_menu;
994 break;
995 case 2:
996 if(humanres.cash>=600) {
997 rb->splash(HZ, "Where do you want to place the plane?");
998 tempmenu = select_square();
999 switch(tempmenu) {
1000 case 0:
1001 rb->splash(HZ, "Cancelled");
1002 goto resources_menu;
1003 break;
1004 case PLUGIN_USB_CONNECTED:
1005 return PLUGIN_USB_CONNECTED;
1006 break;
1008 if(board[cursor.x][cursor.y].colour == COLOUR_LIGHT) {
1009 if(board[cursor.x][cursor.y].plane) {
1010 rb->splash(HZ, "There is already a plane there");
1011 } else {
1012 board[cursor.x][cursor.y].plane = true;
1013 humanres.cash -= 600;
1014 humanres.planes++;
1016 } else {
1017 rb->splash(HZ, "Can't place men on enemy territory");
1019 } else {
1020 rb->splash(HZ, "Not enough money!");
1022 goto resources_menu;
1023 break;
1024 case 3:
1025 if(humanres.cash>=1150) {
1026 rb->splash(HZ, "Where do you want to place the farm?");
1027 tempmenu = select_square();
1028 switch(tempmenu) {
1029 case 0:
1030 rb->splash(HZ, "Cancelled");
1031 goto resources_menu;
1032 break;
1033 case PLUGIN_USB_CONNECTED:
1034 return PLUGIN_USB_CONNECTED;
1035 break;
1037 if(board[cursor.x][cursor.y].colour == COLOUR_LIGHT) {
1038 if(board[cursor.x][cursor.y].farm) {
1039 rb->splash(HZ, "There is already a farm there");
1040 } else {
1041 board[cursor.x][cursor.y].farm = true;
1042 humanres.cash -= 1150;
1043 humanres.farms++;
1045 } else {
1046 rb->splash(HZ, "Can't build on enemy territory");
1048 } else {
1049 rb->splash(HZ, "Not enough money!");
1051 goto resources_menu;
1052 break;
1053 case 4:
1054 if(humanres.cash>=1300) {
1055 rb->splash(HZ, "Where do you want to place the industrial"
1056 " plant?");
1057 tempmenu = select_square();
1058 switch(tempmenu) {
1059 case 0:
1060 rb->splash(HZ, "Cancelled");
1061 goto resources_menu;
1062 break;
1063 case PLUGIN_USB_CONNECTED:
1064 return PLUGIN_USB_CONNECTED;
1065 break;
1067 if(board[cursor.x][cursor.y].colour == COLOUR_LIGHT) {
1068 if(board[cursor.x][cursor.y].ind) {
1069 rb->splash(HZ, "There is already an industrial"
1070 " plant there");
1071 } else {
1072 board[cursor.x][cursor.y].ind = true;
1073 humanres.cash -= 1300;
1074 humanres.inds++;
1076 } else {
1077 rb->splash(HZ, "Can't build on enemy territory");
1079 } else {
1080 rb->splash(HZ, "Not enough money!");
1082 goto resources_menu;
1083 break;
1084 case 5:
1085 if(humanres.cash>=2000) {
1086 rb->splash(HZ, "Where do you want to place the nuke?");
1087 tempmenu = select_square();
1088 switch(tempmenu) {
1089 case 0:
1090 rb->splash(HZ, "Cancelled");
1091 goto resources_menu;
1092 break;
1093 case PLUGIN_USB_CONNECTED:
1094 return PLUGIN_USB_CONNECTED;
1095 break;
1097 if(board[cursor.x][cursor.y].colour == COLOUR_LIGHT) {
1098 if(board[cursor.x][cursor.y].nuke) {
1099 rb->splash(HZ, "There is already a nuke there");
1100 } else {
1101 board[cursor.x][cursor.y].nuke = true;
1102 humanres.cash -= 2000;
1103 humanres.nukes++;
1105 } else {
1106 rb->splash(HZ, "Can't place a nuke on enemy territory");
1108 } else {
1109 rb->splash(HZ, "Not enough money!");
1111 goto resources_menu;
1112 break;
1113 case 6:
1114 return 0;
1115 break;
1116 case MENU_ATTACHED_USB:
1117 return PLUGIN_USB_CONNECTED;
1118 break;
1120 return 0;
1123 int move_unit(void) {
1124 int selection, nummen;
1125 struct cursor from;
1127 MENUITEM_STRINGLIST(move_unit_menu, "Move unit", NULL, "Move men",
1128 "Move tank", "Move plane");
1129 selection=rb->do_menu(&move_unit_menu,&selection, NULL, false);
1130 switch(selection) {
1131 case 0:
1132 rb->splash(HZ, "Select where to move troops from");
1133 if(select_square() == PLUGIN_USB_CONNECTED)
1134 return PLUGIN_USB_CONNECTED;
1135 if(board[cursor.x][cursor.y].colour == COLOUR_LIGHT) {
1136 if(board[cursor.x][cursor.y].men) {
1137 from.x = cursor.x;
1138 from.y = cursor.y;
1139 nummen = board[from.x][from.y].men;
1140 if(get_number("How many men do you want to move?",
1141 &nummen) == PLUGIN_USB_CONNECTED)
1142 return PLUGIN_USB_CONNECTED;
1143 if(nummen > board[from.x][from.y].men) {
1144 rb->splash(HZ, "You don't have that many troops.");
1145 } else {
1146 rb->splash(HZ,"Select where to move the troops to");
1147 if(select_square() == PLUGIN_USB_CONNECTED)
1148 return PLUGIN_USB_CONNECTED;
1149 if((board[cursor.x][cursor.y].colour == COLOUR_LIGHT) &&
1150 (abs(cursor.x - from.x) <= 1) &&
1151 abs(cursor.y - from.y) <= 1) {
1152 board[from.x][from.y].men -= nummen;
1153 board[cursor.x][cursor.y].men += nummen;
1154 humanres.moves--;
1155 return 0;
1158 } else {
1159 rb->splash(HZ, "You don't have any troops there");
1161 } else {
1162 rb->splash(HZ, "Can't move enemy troops");
1164 break;
1165 case 1:
1166 rb->splash(HZ, "Select where you want to move the tank from");
1167 if(select_square() == PLUGIN_USB_CONNECTED)
1168 return PLUGIN_USB_CONNECTED;
1169 if(board[cursor.x][cursor.y].colour == COLOUR_LIGHT) {
1170 if(board[cursor.x][cursor.y].tank) {
1171 from.x = cursor.x;
1172 from.y = cursor.y;
1173 rb->splash(HZ, "Select where you want"
1174 " to move the tank to");
1175 if(select_square() == PLUGIN_USB_CONNECTED)
1176 return PLUGIN_USB_CONNECTED;
1177 if((board[cursor.x][cursor.y].colour == COLOUR_LIGHT)&&
1178 (abs(cursor.x-from.x) <= 1) &&
1179 (abs(cursor.y-from.y) <= 1)) {
1180 if(board[cursor.x][cursor.y].tank) {
1181 rb->splash(HZ, "There is already a tank there");
1182 } else {
1183 board[from.x][from.y].tank = false;
1184 board[cursor.x][cursor.y].tank = true;
1185 humanres.moves--;
1186 return 0;
1188 } else {
1189 rb->splash(HZ, "Invalid move");
1191 } else {
1192 rb->splash(HZ, "You don't have a tank there");
1194 } else {
1195 rb->splash(HZ, "That isn't your territory");
1197 break;
1198 case 2:
1199 rb->splash(HZ, "Select where you want"
1200 " to move the plane from");
1201 if(select_square() == PLUGIN_USB_CONNECTED)
1202 return PLUGIN_USB_CONNECTED;
1203 if(board[cursor.x][cursor.y].colour == COLOUR_LIGHT) {
1204 if(board[cursor.x][cursor.y].plane) {
1205 from.x = cursor.x;
1206 from.y = cursor.y;
1207 rb->splash(HZ, "Select where you want"
1208 " to move the plane to");
1209 if(select_square() == PLUGIN_USB_CONNECTED)
1210 return PLUGIN_USB_CONNECTED;
1211 if(board[cursor.x][cursor.y].colour == COLOUR_LIGHT) {
1212 if(board[cursor.x][cursor.y].plane) {
1213 rb->splash(HZ,"There is already a plane there");
1214 } else {
1215 board[from.x][from.y].plane = false;
1216 board[cursor.x][cursor.y].plane = true;
1217 humanres.moves--;
1218 return 0;
1220 } else {
1221 rb->splash(HZ, "Invalid move");
1223 } else {
1224 rb->splash(HZ, "You don't have a plane there");
1226 } else {
1227 rb->splash(HZ, "That isn't your territory");
1229 break;
1231 return 0;
1234 int movement_menu(void) {
1235 int selection, tempmenu;
1236 bool menu_quit = false;
1238 MENUITEM_STRINGLIST(move_menu, "Movement", NULL, "Move unit",
1239 "Buy additional moves ($100)", "Launch nuclear missile",
1240 "Check map", "Finish moving", "Game menu");
1242 while(!menu_quit) {
1243 selection=rb->do_menu(&move_menu,&selection, NULL, false);
1244 switch(selection) {
1245 case 0:
1246 if(humanres.moves) {
1247 if(move_unit()==PLUGIN_USB_CONNECTED)
1248 return PLUGIN_USB_CONNECTED;
1249 } else {
1250 rb->splash(HZ, "You have no more moves left."
1251 " You can buy more for $100 each.");
1253 break;
1254 case 1:
1255 if(humanres.cash > 100) {
1256 humanres.moves++;
1257 humanres.cash -= 100;
1258 rb->snprintf(buf, sizeof(buf), "You now have %d moves",
1259 humanres.moves);
1260 rb->splash(HZ, buf);
1262 break;
1263 case 2:
1264 if(humanres.nukes==0) {
1265 rb->splash(HZ, "You do not have any nukes to launch");
1266 } else {
1267 rb->splash(HZ, "Select place to launch nuke from");
1268 if(select_square() == PLUGIN_USB_CONNECTED) {
1269 return PLUGIN_USB_CONNECTED;
1271 if(board[cursor.x][cursor.y].nuke) {
1272 rb->splash(HZ, "Select place to target with nuke");
1273 if(select_square() == PLUGIN_USB_CONNECTED) {
1274 return PLUGIN_USB_CONNECTED;
1276 board[cursor.x][cursor.y].men = 0;
1277 board[cursor.x][cursor.y].tank = 0;
1278 board[cursor.x][cursor.y].plane = 0;
1279 board[cursor.x][cursor.y].ind = 0;
1280 board[cursor.x][cursor.y].nuke = 0;
1281 board[cursor.x][cursor.y].farm = 0;
1282 /* TODO: Fallout carried by wind */
1285 break;
1286 case 3:
1287 if(select_square() == PLUGIN_USB_CONNECTED)
1288 return PLUGIN_USB_CONNECTED;
1289 break;
1290 case 4:
1291 return 0;
1292 break;
1293 case 5:
1294 tempmenu = ingame_menu();
1295 switch(tempmenu) {
1296 case PLUGIN_USB_CONNECTED:
1297 return PLUGIN_USB_CONNECTED;
1298 break;
1299 case SUPERDOM_QUIT:
1300 return SUPERDOM_QUIT;
1301 break;
1303 break;
1304 case MENU_ATTACHED_USB:
1305 return PLUGIN_USB_CONNECTED;
1306 break;
1309 return 0;
1312 int show_inventory(void) {
1313 rb->lcd_clear_display();
1314 rb->lcd_puts(1, 0, "Inventory");
1315 char men[20], tanks[20], planes[20], inds[20], farms[20], nukes[20],
1316 cash[20], food[20], bank[20];
1317 rb->snprintf(men, sizeof(men), "Men: %d", humanres.men);
1318 rb->snprintf(tanks, sizeof(tanks), "Tanks: %d", humanres.tanks);
1319 rb->snprintf(planes, sizeof(planes), "Planes: %d", humanres.planes);
1320 rb->snprintf(inds, sizeof(inds), "Factories: %d", humanres.inds);
1321 rb->snprintf(farms, sizeof(farms), "Farms: %d", humanres.farms);
1322 rb->snprintf(nukes, sizeof(nukes), "Nukes: %d", humanres.nukes);
1323 rb->snprintf(cash, sizeof(cash), "Cash: %d", humanres.cash);
1324 rb->snprintf(food, sizeof(food), "Food: %d", humanres.food);
1325 rb->snprintf(bank, sizeof(bank), "Bank: %d", humanres.bank);
1326 rb->lcd_puts(2, 1, men);
1327 rb->lcd_puts(2, 2, tanks);
1328 rb->lcd_puts(2, 3, planes);
1329 rb->lcd_puts(2, 4, inds);
1330 rb->lcd_puts(2, 5, farms);
1331 rb->lcd_puts(2, 6, nukes);
1332 rb->lcd_puts(2, 7, cash);
1333 rb->lcd_puts(2, 8, food);
1334 rb->lcd_puts(2, 9, bank);
1335 rb->lcd_update();
1336 if(rb->default_event_handler(rb->button_get(true)) == SYS_USB_CONNECTED) {
1337 return PLUGIN_USB_CONNECTED;
1338 } else {
1339 return 0;
1343 int production_menu(void) {
1344 int selection, tempbank, tempmenu;
1346 MENUITEM_STRINGLIST(prod_menu, "Production", NULL, "Buy resources",
1347 "Show inventory", "Check map", "Invest money",
1348 "Withdraw money", "Finish turn", "Game menu");
1350 while(1) {
1351 selection=rb->do_menu(&prod_menu,&selection, NULL, false);
1352 switch(selection) {
1353 case 0:
1354 tempmenu = buy_resources_menu();
1355 switch(tempmenu) {
1356 case PLUGIN_USB_CONNECTED:
1357 return PLUGIN_USB_CONNECTED;
1358 break;
1359 case SUPERDOM_QUIT:
1360 return SUPERDOM_QUIT;
1361 break;
1363 break;
1364 case 1:
1365 tempmenu = show_inventory();
1366 switch(tempmenu) {
1367 case 0:
1368 break;
1369 case PLUGIN_USB_CONNECTED:
1370 return PLUGIN_USB_CONNECTED;
1371 break;
1373 break;
1374 case 2:
1375 tempmenu = select_square();
1376 switch(tempmenu) {
1377 case PLUGIN_USB_CONNECTED:
1378 return PLUGIN_USB_CONNECTED;
1379 break;
1380 case SUPERDOM_QUIT:
1381 return SUPERDOM_QUIT;
1382 break;
1383 case 0:
1384 break;
1386 break;
1387 case 3:
1388 tempbank = humanres.cash;
1389 if(get_number("How much do you want to invest?", &tempbank)
1390 == PLUGIN_USB_CONNECTED)
1391 return PLUGIN_USB_CONNECTED;
1392 if(tempbank>humanres.cash) {
1393 rb->splash(HZ, "You don't have that much cash to invest");
1394 } else {
1395 humanres.cash -= tempbank;
1396 humanres.bank += tempbank;
1398 break;
1399 case 4:
1400 tempbank = 0;
1401 if(get_number("How much do you want to withdraw?", &tempbank)
1402 == PLUGIN_USB_CONNECTED)
1403 return PLUGIN_USB_CONNECTED;
1404 if(tempbank>humanres.bank) {
1405 rb->splash(HZ, "You don't have that much cash to withdraw");
1406 } else {
1407 humanres.cash += tempbank;
1408 humanres.bank -= tempbank;
1410 break;
1411 case 5:
1412 return 0;
1413 break;
1414 case 6:
1415 tempmenu = ingame_menu();
1416 switch(tempmenu) {
1417 case PLUGIN_USB_CONNECTED:
1418 return PLUGIN_USB_CONNECTED;
1419 break;
1420 case SUPERDOM_QUIT:
1421 return SUPERDOM_QUIT;
1422 break;
1424 break;
1425 case MENU_ATTACHED_USB:
1426 return PLUGIN_USB_CONNECTED;
1427 break;
1430 return 0;
1433 void init_resources(void) {
1434 humanres.cash = superdom_settings.startcash;
1435 humanres.food = superdom_settings.startfood;
1436 humanres.tanks = 0;
1437 humanres.planes = 0;
1438 humanres.nukes = 0;
1439 humanres.inds = 0;
1440 humanres.farms = 0;
1441 humanres.men = 0;
1442 humanres.bank = 0;
1443 humanres.moves = 0;
1444 compres.cash = superdom_settings.startcash;
1445 compres.food = superdom_settings.startfood;
1446 compres.tanks = 0;
1447 compres.planes = 0;
1448 compres.nukes = 0;
1449 compres.inds = 0;
1450 compres.farms = 0;
1451 compres.men = 0;
1452 compres.bank = 0;
1453 compres.moves = 0;
1456 int select_square(void) {
1457 draw_board();
1458 draw_cursor();
1459 update_score();
1460 #if LCD_WIDTH >= 220
1461 rb->snprintf(buf, sizeof(buf), "Cash: %d", humanres.cash);
1462 rb->lcd_putsxy(125, LCD_HEIGHT-20, buf);
1463 rb->snprintf(buf, sizeof(buf), "Food: %d", humanres.food);
1464 rb->lcd_putsxy(125, LCD_HEIGHT-10, buf);
1465 #endif
1466 rb->lcd_update();
1467 int button = 0;
1468 while(1) {
1469 button = rb->button_get(true);
1470 switch(button) {
1471 case SUPERDOM_CANCEL:
1472 return 0;
1473 break;
1474 case SUPERDOM_OK:
1475 return 2;
1476 break;
1477 #if CONFIG_KEYPAD != IRIVER_H10_PAD
1478 case SUPERDOM_LEFT:
1479 case (SUPERDOM_LEFT|BUTTON_REPEAT):
1480 draw_cursor(); /* Deselect the current tile */
1481 if(cursor.x>1) {
1482 cursor.x--;
1483 } else {
1484 #ifdef IPOD_STYLE
1485 if(cursor.y>1)
1486 cursor.y--;
1487 else
1488 cursor.y = 10;
1489 #endif
1490 cursor.x = 10;
1492 update_score();
1493 draw_cursor();
1494 break;
1495 case SUPERDOM_RIGHT:
1496 case (SUPERDOM_RIGHT|BUTTON_REPEAT):
1497 draw_cursor(); /* Deselect the current tile */
1498 if(cursor.x<10) {
1499 cursor.x++;
1500 } else {
1501 #ifdef IPOD_STYLE
1502 if(cursor.y<10)
1503 cursor.y++;
1504 else
1505 cursor.y = 1;
1506 #endif
1507 cursor.x = 1;
1509 update_score();
1510 draw_cursor();
1511 break;
1512 #endif
1513 #ifndef IPOD_STYLE
1514 case SUPERDOM_UP:
1515 case (SUPERDOM_UP|BUTTON_REPEAT):
1516 draw_cursor(); /* Deselect the current tile */
1517 if(cursor.y>1) {
1518 cursor.y--;
1519 } else {
1520 #if CONFIG_KEYPAD == IRIVER_H10_PAD
1521 if(cursor.x > 1)
1522 cursor.x--;
1523 else
1524 cursor.x = 10;
1525 #endif
1526 cursor.y = 10;
1528 update_score();
1529 draw_cursor();
1530 break;
1531 case SUPERDOM_DOWN:
1532 case (SUPERDOM_DOWN|BUTTON_REPEAT):
1533 draw_cursor(); /* Deselect the current tile */
1534 if(cursor.y<10) {
1535 cursor.y++;
1536 } else {
1537 #if CONFIG_KEYPAD == IRIVER_H10_PAD
1538 if(cursor.x < 10)
1539 cursor.x++;
1540 else
1541 cursor.x = 1;
1542 #endif
1543 cursor.y = 1;
1545 update_score();
1546 draw_cursor();
1547 break;
1548 #endif
1549 default:
1550 if (rb->default_event_handler(button) == SYS_USB_CONNECTED)
1552 return PLUGIN_USB_CONNECTED;
1558 int killmen(bool human) {
1559 int menkilled,i,j;
1560 int percent;
1561 if(human) {
1562 percent = (humanres.food*1000)/humanres.men;
1563 humanres.food = 0;
1564 } else {
1565 percent = (compres.food*1000)/compres.men;
1566 compres.food = 0;
1568 menkilled = 0;
1569 for(i=1;i<12;i++) {
1570 for(j=1;j<12;j++) {
1571 if(board[i][j].colour == human) {
1572 menkilled += ((board[i][j].men * percent)/1000);
1573 board[i][j].men = (board[i][j].men * percent)/1000;
1578 if(human)
1579 humanres.men -= menkilled;
1580 else
1581 compres.men -= menkilled;
1582 return menkilled;
1585 int war_menu(void) {
1586 int selection, tempmenu;
1588 MENUITEM_STRINGLIST(wartime_menu, "War!", NULL,
1589 "Select territory to attack", "Finish turn", "Game menu");
1591 humanres.moves = superdom_settings.movesperturn;
1592 while(humanres.moves) {
1593 selection=rb->do_menu(&wartime_menu,&selection, NULL, false);
1594 switch(selection) {
1595 case 0:
1596 if(select_square() == PLUGIN_USB_CONNECTED)
1597 return PLUGIN_USB_CONNECTED;
1598 if(board[cursor.x][cursor.y].colour == COLOUR_DARK) {
1599 if(calc_strength(COLOUR_LIGHT, cursor.x,
1600 cursor.y) > calc_strength(COLOUR_DARK,
1601 cursor.x, cursor.y)) {
1602 board[cursor.x][cursor.y].colour = COLOUR_LIGHT;
1603 board[cursor.x][cursor.y].tank = 0;
1604 board[cursor.x][cursor.y].men = 0;
1605 board[cursor.x][cursor.y].plane = 0;
1606 board[cursor.x][cursor.y].nuke = 0;
1607 draw_board();
1608 rb->sleep(HZ*2);
1609 humanres.moves--;
1610 } else if(calc_strength(COLOUR_LIGHT, cursor.x, cursor.y)==
1611 calc_strength(COLOUR_DARK, cursor.x, cursor.y)) {
1612 if(rb->rand()%2) {
1613 board[cursor.x][cursor.y].colour = COLOUR_LIGHT;
1614 board[cursor.x][cursor.y].tank = 0;
1615 board[cursor.x][cursor.y].men = 0;
1616 board[cursor.x][cursor.y].plane = 0;
1617 board[cursor.x][cursor.y].nuke = 0;
1618 draw_board();
1619 rb->sleep(HZ*2);
1620 humanres.moves--;
1621 } else {
1622 rb->splash(HZ, "Your troops were unable to"
1623 " overcome the enemy troops");
1624 humanres.moves--;
1626 } else {
1627 rb->splash(HZ, "Your troops were unable to overcome"
1628 " the enemy troops");
1629 humanres.moves--;
1631 } else {
1632 rb->splash(HZ, "You can't attack your own territory");
1634 break;
1635 case 1:
1636 return 0;
1637 break;
1638 case 2:
1639 tempmenu = ingame_menu();
1640 switch(tempmenu) {
1641 case PLUGIN_USB_CONNECTED:
1642 return PLUGIN_USB_CONNECTED;
1643 break;
1644 case SUPERDOM_QUIT:
1645 return SUPERDOM_QUIT;
1646 break;
1648 break;
1651 return 0;
1654 struct threat {
1655 int x;
1656 int y;
1657 int str_diff;
1660 bool place_adjacent(bool tank, int x, int y) {
1661 if(tank) {
1662 if(!board[x-1][y].tank && (board[x][y].colour==board[x-1][y].colour)) {
1663 compres.cash -= 300;
1664 board[x-1][y].tank = true;
1665 compres.tanks++;
1666 return 0;
1668 if(!board[x+1][y].tank && (board[x][y].colour==board[x+1][y].colour)) {
1669 compres.cash -= 300;
1670 board[x+1][y].tank = true;
1671 compres.tanks++;
1672 return 0;
1674 if(!board[x][y-1].tank && (board[x][y].colour==board[x][y-1].colour)) {
1675 compres.cash -= 300;
1676 board[x][y-1].tank = true;
1677 compres.tanks++;
1678 return 0;
1680 if(!board[x][y+1].tank && (board[x][y].colour==board[x][y+1].colour)) {
1681 compres.cash -= 300;
1682 board[x][y+1].tank = true;
1683 compres.tanks++;
1684 return 0;
1686 } else {
1687 if(!board[x-1][y].plane && (board[x][y].colour==board[x-1][y].colour)) {
1688 compres.cash -= 600;
1689 board[x-1][y].plane = true;
1690 compres.planes++;
1691 return 0;
1693 if(!board[x+1][y].plane && (board[x][y].colour==board[x+1][y].colour)) {
1694 compres.cash -= 600;
1695 board[x+1][y].plane = true;
1696 compres.planes++;
1697 return 0;
1699 if(!board[x][y-1].plane && (board[x][y].colour==board[x][y-1].colour)) {
1700 compres.cash -= 600;
1701 board[x][y-1].plane = true;
1702 compres.planes++;
1703 return 0;
1705 if(!board[x][y+1].plane && (board[x][y].colour==board[x][y+1].colour)) {
1706 compres.cash -= 600;
1707 board[x][y+1].plane = true;
1708 compres.planes++;
1709 return 0;
1712 return 1;
1715 bool has_adjacent(int x, int y) {
1716 if((board[x][y].colour == COLOUR_LIGHT) &&
1717 ((board[x-1][y].colour == COLOUR_DARK) ||
1718 (board[x+1][y].colour == COLOUR_DARK) ||
1719 (board[x][y+1].colour == COLOUR_DARK) ||
1720 (board[x][y-1].colour == COLOUR_DARK)))
1721 return 1;
1722 else
1723 return 0;
1726 void find_adjacent(int x, int y, int* adj_x, int* adj_y, bool* full) {
1727 /* Finds adjacent squares, returning squares without tanks on them
1728 * in preference to those with them */
1729 if(((board[x-1][y].tank && (board[x-1][y].colour == COLOUR_DARK)) ||
1730 board[x-1][y].colour != COLOUR_DARK) &&
1731 ((board[x+1][y].tank && (board[x+1][y].colour == COLOUR_DARK)) ||
1732 board[x+1][y].colour != COLOUR_DARK) &&
1733 ((board[x][y-1].tank && (board[x][y-1].colour == COLOUR_DARK)) ||
1734 board[x][y-1].colour != COLOUR_DARK) &&
1735 ((board[x][y+1].tank && (board[x][y+1].colour == COLOUR_DARK)) ||
1736 board[x][y+1].colour != COLOUR_DARK)) {
1737 *full = true;
1738 } else {
1739 *full = false;
1742 if(board[x-1][y].colour == COLOUR_DARK) {
1743 *adj_x = x-1;
1744 *adj_y = y;
1745 if(board[x-1][y].tank) {
1746 if(*full)
1747 return;
1748 } else {
1749 return;
1752 if(board[x+1][y].colour == COLOUR_DARK) {
1753 *adj_x = x+1;
1754 *adj_y = y;
1755 if(board[x+1][y].tank) {
1756 if(*full)
1757 return;
1758 } else {
1759 return;
1762 if(board[x][y-1].colour == COLOUR_DARK) {
1763 *adj_x = x;
1764 *adj_y = y-1;
1765 if(board[x][y-1].tank) {
1766 if(*full)
1767 return;
1768 } else {
1769 return;
1772 if(board[x][y+1].colour == COLOUR_DARK) {
1773 *adj_x = x;
1774 *adj_y = y+1;
1775 if(board[x][y+1].tank) {
1776 if(*full)
1777 return;
1778 } else {
1779 return;
1784 void computer_allocate(void) {
1785 /* Firstly, decide whether to go offensive or defensive.
1786 * This is primarily decided by the human player posing a threat to either
1787 * the computer's farms or factories */
1788 int i, j, k;
1789 bool offensive = true;
1790 struct threat threats[4];
1791 int numthreats = 0;
1792 int total_str_diff = 0;
1793 int men_needed;
1794 struct threat targets[2];
1795 int numtargets;
1796 struct cursor adj;
1797 bool full = false;
1798 for(i=1;i<12;i++) {
1799 for(j=1;j<12;j++) {
1800 if((board[i][j].colour == COLOUR_DARK) &&
1801 (calc_strength(COLOUR_DARK,i,j) <
1802 calc_strength(COLOUR_LIGHT,i,j))) {
1803 if(board[i][j].ind || board[i][j].farm) {
1804 if(numthreats < 3) {
1805 offensive = false;
1806 threats[numthreats].x = i;
1807 threats[numthreats].y = j;
1808 threats[numthreats].str_diff =
1809 calc_strength(COLOUR_LIGHT,i,j) -
1810 calc_strength(COLOUR_DARK,i,j);
1811 numthreats++;
1815 rb->yield();
1818 if(offensive) {
1819 /* The AI is going to go straight for the throat here and attack
1820 * the player's farms and factories. The amount of cash
1821 * the AI has to spend will determine how many targets there are */
1822 if(compres.cash > 1200) {
1823 /* 1200 is a figure I pulled out of nowhere. Adjust as needed */
1824 numtargets = 2;
1825 } else {
1826 numtargets = 1;
1828 /* Work out which target(s) to attack. They must have adjacent squares
1829 * owned by the computer. If none are found just place troops in
1830 * random places around the map until we run out of money */
1831 k = 0;
1832 while(k<numtargets) {
1833 for(i=1;i<12;i++) {
1834 for(j=1;j<12;j++) {
1835 if((board[i][j].colour == COLOUR_LIGHT) &&
1836 (board[i][j].ind || board[i][j].farm) &&
1837 has_adjacent(i,j)) {
1838 targets[k].x = i;
1839 targets[k].y = j;
1840 targets[k].str_diff = abs(calc_strength(COLOUR_LIGHT,
1841 i, j) - calc_strength(COLOUR_DARK,
1842 i, j));
1843 k++;
1845 rb->yield();
1849 if(k == 0) {
1850 /* No targets found! Randomly pick squares and if they're owned
1851 * by the computer then stick a tank on it. */
1852 rb->srand(*rb->current_tick);
1853 while(compres.cash >= 300) {
1854 i = rb->rand()%11 + 1;
1855 j = rb->rand()%11 + 1;
1856 if(board[i][j].colour == COLOUR_DARK) {
1857 if(compres.cash >= 300) {
1858 if(!board[i][j].tank) {
1859 board[i][j].tank = true;
1860 compres.tanks++;
1861 compres.cash -= 300;
1862 draw_board();
1863 rb->sleep(HZ);
1868 compres.bank += compres.cash;
1869 compres.cash = 0;
1870 } else {
1871 for(i=0;i<k;i++) {
1872 men_needed = targets[i].str_diff + 20;
1873 find_adjacent(targets[i].x,targets[i].y, &adj.x, &adj.y, &full);
1874 while(((calc_strength(COLOUR_LIGHT, targets[i].x, targets[i].y)
1875 + 20) > calc_strength(COLOUR_DARK, targets[i].x,
1876 targets[i].y)) && compres.cash > 0) {
1877 /* While we still need them keep placing men */
1878 if(compres.cash >= 300 && !full) {
1879 if(board[adj.x][adj.y].tank) {
1880 find_adjacent(targets[i].x, targets[i].y,
1881 &adj.x, &adj.y, &full);
1882 } else {
1883 board[adj.x][adj.y].tank = true;
1884 compres.tanks++;
1885 compres.cash -= 300;
1886 draw_board();
1887 rb->sleep(HZ);
1889 } else {
1890 men_needed = (calc_strength(COLOUR_LIGHT, targets[i].x,
1891 targets[i].y) + 20 -
1892 calc_strength(COLOUR_DARK, targets[i].x,
1893 targets[i].y))*1000/133;
1894 if(compres.cash >= men_needed) {
1895 board[adj.x][adj.y].men += men_needed;
1896 compres.men += men_needed;
1897 compres.cash -= men_needed;
1898 compres.bank += compres.cash;
1899 compres.cash = 0;
1900 } else {
1901 board[adj.x][adj.y].men += compres.cash;
1902 compres.men += compres.cash;
1903 compres.cash = 0;
1905 draw_board();
1906 rb->sleep(HZ);
1910 compres.bank += compres.cash;
1911 compres.cash = 0;
1912 rb->yield();
1914 } else {
1915 /* Work out what to place on each square to defend it.
1916 * Tanks are preferential because they do not require food,
1917 * but if the budget is tight then we fall back onto troops.
1918 * Conversely if cash is not an issue and there are already tanks in
1919 * place planes will be deployed. We would like a margin of at least
1920 * 20 points to be safe. */
1922 for(i=0;i<numthreats;i++) {
1923 total_str_diff += threats[i].str_diff;
1925 if((total_str_diff+20)*10 > compres.cash) {
1926 /* Not enough cash to accomodate all threats using tanks alone -
1927 * use men as a backup */
1928 for(i=0;i<numthreats;i++) {
1929 men_needed = ((threats[i].str_diff + 20)*1000)/133;
1930 if(compres.cash >= men_needed) {
1931 board[threats[i].x][threats[i].y].men += men_needed;
1932 compres.cash -= men_needed;
1933 compres.men += men_needed;
1934 draw_board();
1935 rb->sleep(HZ);
1936 } else {
1937 board[threats[i].x][threats[i].y].men += compres.cash;
1938 compres.men += compres.cash;
1939 compres.cash = 0;
1940 draw_board();
1941 rb->sleep(HZ);
1943 rb->yield();
1945 } else if((total_str_diff+20)*15 < compres.cash) {
1946 /* Enough money to pay their way by planes */
1947 for(i=0;i<numthreats;i++) {
1948 while(calc_strength(COLOUR_DARK,threats[i].x, threats[i].y) <
1949 (calc_strength(COLOUR_LIGHT,threats[i].x, threats[i].y) +
1950 20)) {
1951 if(board[threats[i].x][threats[i].y].plane) {
1952 if(place_adjacent(0, threats[i].x, threats[i].y)) {
1953 /* No room for any more planes, revert to men */
1954 men_needed = (calc_strength(COLOUR_LIGHT,
1955 threats[i].x, threats[i].y) + 20 -
1956 calc_strength(COLOUR_DARK,
1957 threats[i].x, threats[i].y)*1000/133);
1958 if(compres.cash >= men_needed) {
1959 compres.cash -= men_needed;
1960 compres.men += men_needed;
1961 board[threats[i].x][threats[i].y].men +=
1962 men_needed;
1963 draw_board();
1964 rb->sleep(HZ);
1967 } else {
1968 if(compres.cash >= 600) {
1969 board[threats[i].x][threats[i].y].plane = true;
1970 compres.cash -= 600;
1971 compres.planes++;
1972 draw_board();
1973 rb->sleep(HZ);
1977 rb->yield();
1979 } else {
1980 /* Tanks it is */
1981 for(i=0;i<numthreats;i++) {
1982 while(calc_strength(COLOUR_DARK,threats[i].x, threats[i].y) <
1983 (calc_strength(COLOUR_LIGHT,threats[i].x, threats[i].y) +
1984 20) && compres.cash > 0) {
1985 if(board[threats[i].x][threats[i].y].tank) {
1986 if(place_adjacent(1, threats[i].x, threats[i].y)) {
1987 /* No room for any more tanks, revert to men */
1988 men_needed = (calc_strength(COLOUR_LIGHT,
1989 threats[i].x, threats[i].y) + 20 -
1990 calc_strength(COLOUR_DARK,
1991 threats[i].x, threats[i].y)*1000/133);
1992 if(compres.cash >= men_needed) {
1993 compres.cash -= men_needed;
1994 compres.men += men_needed;
1995 board[threats[i].x][threats[i].y].men +=
1996 men_needed;
1997 draw_board();
1998 rb->sleep(HZ);
2001 } else {
2002 if(compres.cash >= 300) {
2003 board[threats[i].x][threats[i].y].tank = true;
2004 compres.tanks++;
2005 compres.cash -= 300;
2006 draw_board();
2007 rb->sleep(HZ);
2011 rb->yield();
2014 compres.bank += compres.cash;
2015 compres.cash = 0;
2019 int find_adj_target(int x, int y, struct cursor* adj) {
2020 /* Find a square next to a computer's farm or factory owned by the player
2021 * that is vulnerable. Return 1 on success, 0 otherwise */
2022 if(board[x+1][y].colour == COLOUR_LIGHT &&
2023 calc_strength(COLOUR_LIGHT,x+1,y)<=calc_strength(COLOUR_DARK,x+1,y)) {
2024 adj->x = x+1;
2025 adj->y = y;
2026 return 1;
2028 if(board[x-1][y].colour == COLOUR_LIGHT &&
2029 calc_strength(COLOUR_LIGHT,x-1,y)<=calc_strength(COLOUR_DARK,x-1,y)) {
2030 adj->x = x-1;
2031 adj->y = y;
2032 return 1;
2034 if(board[x][y+1].colour == COLOUR_LIGHT &&
2035 calc_strength(COLOUR_LIGHT,x,y+1)<=calc_strength(COLOUR_DARK,x,y+1)) {
2036 adj->x = x;
2037 adj->y = y+1;
2038 return 1;
2040 if(board[x][y-1].colour == COLOUR_LIGHT &&
2041 calc_strength(COLOUR_LIGHT,x,y-1)<=calc_strength(COLOUR_DARK,x,y-1)) {
2042 adj->x = x;
2043 adj->y = y-1;
2044 return 1;
2046 return 0;
2049 void computer_war(void) {
2050 /* Work out where to attack - prioritise the defence of buildings */
2051 int i, j;
2052 struct cursor adj;
2054 while(compres.moves) {
2055 for(i=1;i<12;i++) {
2056 for(j=1;j<12;j++) {
2057 if((board[i][j].colour == COLOUR_DARK) &&
2058 (board[i][j].farm || board[i][j].ind)) {
2059 if(find_adj_target(i, j, &adj) && compres.moves) {
2060 if(calc_strength(COLOUR_LIGHT, adj.x, adj.y) ==
2061 calc_strength(COLOUR_DARK, adj.x, adj.y)) {
2062 rb->srand(*rb->current_tick);
2063 if(rb->rand()%2) {
2064 board[adj.x][adj.y].colour = COLOUR_DARK;
2065 board[adj.x][adj.y].tank = false;
2066 board[adj.x][adj.y].plane = false;
2067 board[adj.x][adj.y].nuke = false;
2068 humanres.men -= board[adj.x][adj.y].men;
2069 board[adj.x][adj.y].men = 0;
2070 draw_board();
2071 rb->sleep(HZ);
2072 compres.moves--;
2073 } else {
2074 rb->splash(HZ*2, "The computer attempted"
2075 " to attack, but the"
2076 " invasion was pushed"
2077 " back");
2078 compres.moves--;
2080 } else {
2081 if(compres.moves) {
2082 board[adj.x][adj.y].colour = COLOUR_DARK;
2083 board[adj.x][adj.y].tank = false;
2084 board[adj.x][adj.y].plane = false;
2085 board[adj.x][adj.y].nuke = false;
2086 humanres.men -= board[adj.x][adj.y].men;
2087 board[adj.x][adj.y].men = 0;
2088 draw_board();
2089 rb->sleep(HZ);
2090 compres.moves--;
2095 rb->yield();
2098 if(compres.moves) {
2099 /* Defence stage done, move on to OFFENCE */
2100 for(i=1;i<12;i++) {
2101 for(j=1;j<12;j++) {
2102 if(board[i][j].colour == COLOUR_LIGHT && compres.moves &&
2103 (board[i][j].ind || board[i][j].farm) &&
2104 (calc_strength(COLOUR_DARK, i, j) >=
2105 calc_strength(COLOUR_LIGHT, i, j))) {
2106 if(calc_strength(COLOUR_DARK, i, j) ==
2107 calc_strength(COLOUR_LIGHT, i, j)) {
2108 if(rb->rand()%2) {
2109 board[i][j].colour = COLOUR_DARK;
2110 board[i][j].tank = false;
2111 board[i][j].plane = false;
2112 board[i][j].nuke = false;
2113 board[i][j].men = 0;
2114 draw_board();
2115 rb->sleep(HZ);
2116 compres.moves--;
2117 } else {
2118 rb->splash(HZ*2, "The computer attempted to "
2119 "attack, but the invasion was"
2120 " pushed back");
2121 compres.moves--;
2123 } else {
2124 board[i][j].colour = COLOUR_DARK;
2125 board[i][j].tank = false;
2126 board[i][j].plane = false;
2127 board[i][j].nuke = false;
2128 board[i][j].men = 0;
2129 draw_board();
2130 rb->sleep(HZ);
2131 compres.moves--;
2134 rb->yield();
2137 while(compres.moves > 0) {
2138 /* Spend leftover moves wherever attacking randomly */
2139 rb->srand(*rb->current_tick);
2140 i = (rb->rand()%10)+1;
2141 j = (rb->rand()%10)+1;
2142 if(board[i][j].colour == COLOUR_LIGHT &&
2143 (calc_strength(COLOUR_DARK, i, j) >=
2144 calc_strength(COLOUR_LIGHT, i, j))) {
2145 if(calc_strength(COLOUR_DARK, i, j) ==
2146 calc_strength(COLOUR_LIGHT, i, j)) {
2147 if(rb->rand()%2) {
2148 board[i][j].colour = COLOUR_DARK;
2149 board[i][j].tank = false;
2150 board[i][j].plane = false;
2151 board[i][j].nuke = false;
2152 board[i][j].men = 0;
2153 draw_board();
2154 rb->sleep(HZ);
2155 compres.moves--;
2156 } else {
2157 rb->splash(HZ*2, "The computer attempted to"
2158 " attack, but the invasion was"
2159 " pushed back");
2160 compres.moves--;
2162 } else {
2163 board[i][j].colour = COLOUR_DARK;
2164 board[i][j].tank = false;
2165 board[i][j].plane = false;
2166 board[i][j].nuke = false;
2167 board[i][j].men = 0;
2168 draw_board();
2169 rb->sleep(HZ);
2170 compres.moves--;
2178 static int load_game(const char* file) {
2179 int fd;
2181 fd = rb->open(file, O_RDONLY);
2182 if(fd == 0) {
2183 DEBUGF("Couldn't open savegame\n");
2184 return -1;
2186 rb->read(fd, buf, 5);
2187 if(rb->strcmp(buf, "SSGv2")) {
2188 rb->splash(HZ, "Invalid/incompatible savegame\n");
2189 return -1;
2191 rb->read(fd, &humanres.cash, sizeof(humanres.cash));
2192 rb->read(fd, &humanres.food, sizeof(humanres.food));
2193 rb->read(fd, &humanres.bank, sizeof(humanres.bank));
2194 rb->read(fd, &humanres.planes, sizeof(humanres.planes));
2195 rb->read(fd, &humanres.tanks, sizeof(humanres.tanks));
2196 rb->read(fd, &humanres.men, sizeof(humanres.men));
2197 rb->read(fd, &humanres.nukes, sizeof(humanres.nukes));
2198 rb->read(fd, &humanres.inds, sizeof(humanres.inds));
2199 rb->read(fd, &humanres.farms, sizeof(humanres.farms));
2200 rb->read(fd, &humanres.moves, sizeof(humanres.moves));
2201 rb->read(fd, &compres.cash, sizeof(humanres.cash));
2202 rb->read(fd, &compres.food, sizeof(humanres.food));
2203 rb->read(fd, &compres.bank, sizeof(humanres.bank));
2204 rb->read(fd, &compres.planes, sizeof(humanres.planes));
2205 rb->read(fd, &compres.tanks, sizeof(humanres.tanks));
2206 rb->read(fd, &compres.men, sizeof(humanres.men));
2207 rb->read(fd, &compres.nukes, sizeof(humanres.nukes));
2208 rb->read(fd, &compres.inds, sizeof(humanres.inds));
2209 rb->read(fd, &compres.farms, sizeof(humanres.farms));
2210 rb->read(fd, &compres.moves, sizeof(humanres.moves));
2211 rb->read(fd, board, sizeof(board));
2212 rb->read(fd, &superdom_settings.compstartfarms, sizeof(int));
2213 rb->read(fd, &superdom_settings.compstartinds, sizeof(int));
2214 rb->read(fd, &superdom_settings.humanstartfarms, sizeof(int));
2215 rb->read(fd, &superdom_settings.humanstartfarms, sizeof(int));
2216 rb->read(fd, &superdom_settings.startcash, sizeof(int));
2217 rb->read(fd, &superdom_settings.startfood, sizeof(int));
2218 rb->read(fd, &superdom_settings.movesperturn, sizeof(int));
2219 return 0;
2222 void default_settings(void) {
2223 superdom_settings.compstartfarms = 1;
2224 superdom_settings.compstartinds = 1;
2225 superdom_settings.humanstartfarms = 2;
2226 superdom_settings.humanstartinds = 2;
2227 superdom_settings.startcash = 0;
2228 superdom_settings.startfood = 0;
2229 superdom_settings.movesperturn = 2;
2232 int average_strength(bool colour) {
2233 /* This function calculates the average strength of the given player,
2234 * used to determine when the computer wins or loses. */
2235 int i,j;
2236 int totalpower = 0;
2237 for(i=0;i<12;i++) {
2238 for(j=0;j<12;j++) {
2239 if(board[i][j].colour != -1) {
2240 totalpower += calc_strength(colour, i, j);
2244 return totalpower/100;
2247 enum plugin_status plugin_start(const void* parameter)
2249 int tempmenu;
2250 bool statusbar_setting;
2252 #if LCD_DEPTH > 1
2253 rb->lcd_set_backdrop(NULL);
2254 rb->lcd_set_foreground(LCD_BLACK);
2255 rb->lcd_set_background(LCD_WHITE);
2256 #endif
2258 statusbar_setting = rb->global_settings->statusbar;
2259 rb->global_settings->statusbar = false;
2260 cursor.x = 1;
2261 cursor.y = 1;
2262 default_settings();
2263 if(parameter) {
2264 if(load_game(parameter) != 0) {
2265 DEBUGF("Loading failed, generating new game\n");
2266 init_resources();
2267 init_board();
2268 } else {
2269 goto startyear;
2271 } else {
2272 init_resources();
2273 init_board();
2276 bool play = false;
2277 while(!play) {
2278 switch(menu()) {
2279 case 0:
2280 play = true;
2281 break;
2282 case 2:
2283 rb->global_settings->statusbar = statusbar_setting;
2284 return PLUGIN_OK;
2285 break;
2288 gen_resources();
2289 startyear:
2290 if((average_strength(COLOUR_LIGHT) - average_strength(COLOUR_DARK)) > 15) {
2291 rb->splash(HZ*4, "The computer has surrendered. You win.");
2292 rb->global_settings->statusbar = statusbar_setting;
2293 return PLUGIN_OK;
2295 if((average_strength(COLOUR_DARK) - average_strength(COLOUR_LIGHT)) > 15) {
2296 rb->splash(HZ*4, "Your army have suffered terrible morale from the bleak prospects of winning. You lose");
2297 rb->global_settings->statusbar = statusbar_setting;
2298 return PLUGIN_OK;
2300 tempmenu = production_menu();
2301 switch(tempmenu) {
2302 case PLUGIN_USB_CONNECTED:
2303 rb->global_settings->statusbar = statusbar_setting;
2304 return PLUGIN_USB_CONNECTED;
2305 break;
2306 case SUPERDOM_QUIT:
2307 rb->global_settings->statusbar = statusbar_setting;
2308 return PLUGIN_OK;
2309 break;
2311 computer_allocate();
2312 humanres.moves += superdom_settings.movesperturn;
2313 tempmenu = movement_menu();
2314 switch(tempmenu) {
2315 case PLUGIN_USB_CONNECTED:
2316 rb->global_settings->statusbar = statusbar_setting;
2317 return PLUGIN_USB_CONNECTED;
2318 break;
2319 case SUPERDOM_QUIT:
2320 rb->global_settings->statusbar = statusbar_setting;
2321 return PLUGIN_OK;
2322 break;
2324 if(humanres.men) {
2325 if(humanres.food > humanres.men) {
2326 rb->snprintf(buf, sizeof(buf), "Your men ate %d units of food",
2327 humanres.men);
2328 humanres.food -= humanres.men;
2329 } else {
2330 rb->snprintf(buf, sizeof(buf), "There was not enough food to feed"
2331 " all your men, %d men have died of starvation",
2332 killmen(COLOUR_LIGHT));
2334 rb->splash(HZ*2, buf);
2336 if(compres.men) {
2337 if(compres.food < compres.men) {
2338 rb->snprintf(buf, sizeof(buf), "The computer does not have enough"
2339 " food to feed its men. %d have ided of starvation",
2340 killmen(COLOUR_DARK));
2341 rb->splash(HZ, buf);
2344 tempmenu = war_menu();
2345 switch(tempmenu) {
2346 case PLUGIN_USB_CONNECTED:
2347 rb->global_settings->statusbar = statusbar_setting;
2348 return PLUGIN_USB_CONNECTED;
2349 break;
2350 case SUPERDOM_QUIT:
2351 rb->global_settings->statusbar = statusbar_setting;
2352 return PLUGIN_OK;
2353 break;
2355 compres.moves += superdom_settings.movesperturn;
2356 computer_war();
2357 gen_resources();
2358 goto startyear;
2359 rb->global_settings->statusbar = statusbar_setting;
2360 return PLUGIN_OK;