Prepare new maemo release
[maemo-rb.git] / apps / plugins / superdom.c
blob1ef99dee30efe1886288a9af4c35a32e4094d9f9
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 #include "lib/display_text.h"
24 #include "pluginbitmaps/superdom_boarditems.h"
27 extern const fb_data superdom_boarditems[];
28 char buf[255];
30 #define COLOUR_DARK 0
31 #define COLOUR_LIGHT 1
33 #define MARGIN 5
35 #if (LCD_DEPTH == 16)
36 #define MY_BITMAP_PART rb->lcd_bitmap_transparent_part
37 #else
38 #define MY_BITMAP_PART rb->lcd_mono_bitmap_part
39 #endif
41 #if LCD_WIDTH > LCD_HEIGHT
42 #define BOX_WIDTH ((LCD_WIDTH-(MARGIN*2))/10)
43 #define BOX_HEIGHT ((BOX_WIDTH*2)/3)
45 #else
46 #define BOX_HEIGHT ((LCD_HEIGHT-(MARGIN*2)-15)/10)
47 #define BOX_WIDTH ((BOX_HEIGHT*2)/3)
49 #endif
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
63 * of the bitmap.
65 #define ICON_STRIDE STRIDE(SCREEN_MAIN, BMPWIDTH_superdom_boarditems, BMPHEIGHT_superdom_boarditems)
66 #define ICON_HEIGHT (BMPHEIGHT_superdom_boarditems/6)
67 #define ICON_WIDTH (BMPWIDTH_superdom_boarditems/2)
69 #if (CONFIG_KEYPAD == IPOD_4G_PAD) || (CONFIG_KEYPAD == IPOD_3G_PAD) || \
70 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
71 #define SUPERDOM_OK BUTTON_SELECT
72 #define SUPERDOM_CANCEL BUTTON_MENU
73 #define SUPERDOM_LEFT BUTTON_LEFT
74 #define SUPERDOM_RIGHT BUTTON_RIGHT
75 #define IPOD_STYLE
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 CONFIG_KEYPAD == SAMSUNG_YPR0_PAD
125 #define SUPERDOM_OK BUTTON_SELECT
126 #define SUPERDOM_UP BUTTON_UP
127 #define SUPERDOM_DOWN BUTTON_DOWN
128 #define SUPERDOM_LEFT BUTTON_LEFT
129 #define SUPERDOM_RIGHT BUTTON_RIGHT
130 #define SUPERDOM_CANCEL BUTTON_BACK
132 #elif CONFIG_KEYPAD == COWON_D2_PAD
133 #define SUPERDOM_CANCEL BUTTON_POWER
135 #elif CONFIG_KEYPAD == CREATIVEZVM_PAD
136 #define SUPERDOM_OK BUTTON_SELECT
137 #define SUPERDOM_UP BUTTON_UP
138 #define SUPERDOM_DOWN BUTTON_DOWN
139 #define SUPERDOM_LEFT BUTTON_LEFT
140 #define SUPERDOM_RIGHT BUTTON_RIGHT
141 #define SUPERDOM_CANCEL BUTTON_BACK
143 #elif CONFIG_KEYPAD == PHILIPS_HDD6330_PAD
144 #define SUPERDOM_OK BUTTON_PLAY
145 #define SUPERDOM_UP BUTTON_UP
146 #define SUPERDOM_DOWN BUTTON_DOWN
147 #define SUPERDOM_LEFT BUTTON_PREV
148 #define SUPERDOM_RIGHT BUTTON_NEXT
149 #define SUPERDOM_CANCEL BUTTON_LEFT
151 #elif CONFIG_KEYPAD == PHILIPS_SA9200_PAD
152 #define SUPERDOM_OK BUTTON_PLAY
153 #define SUPERDOM_UP BUTTON_UP
154 #define SUPERDOM_DOWN BUTTON_DOWN
155 #define SUPERDOM_LEFT BUTTON_PREV
156 #define SUPERDOM_RIGHT BUTTON_NEXT
157 #define SUPERDOM_CANCEL BUTTON_LEFT
159 #elif (CONFIG_KEYPAD == ONDAVX747_PAD) || (CONFIG_KEYPAD == MROBE500_PAD)
160 #define SUPERDOM_CANCEL BUTTON_POWER
162 #elif CONFIG_KEYPAD == SAMSUNG_YH_PAD
163 #define SUPERDOM_OK BUTTON_PLAY
164 #define SUPERDOM_UP BUTTON_UP
165 #define SUPERDOM_DOWN BUTTON_DOWN
166 #define SUPERDOM_LEFT BUTTON_LEFT
167 #define SUPERDOM_RIGHT BUTTON_RIGHT
168 #define SUPERDOM_CANCEL BUTTON_REW
170 #elif CONFIG_KEYPAD == PBELL_VIBE500_PAD
171 #define SUPERDOM_OK BUTTON_OK
172 #define SUPERDOM_UP BUTTON_UP
173 #define SUPERDOM_DOWN BUTTON_DOWN
174 #define SUPERDOM_LEFT BUTTON_PREV
175 #define SUPERDOM_RIGHT BUTTON_NEXT
176 #define SUPERDOM_CANCEL BUTTON_CANCEL
178 #elif CONFIG_KEYPAD == MPIO_HD300_PAD
179 #define SUPERDOM_OK BUTTON_ENTER
180 #define SUPERDOM_UP BUTTON_UP
181 #define SUPERDOM_DOWN BUTTON_DOWN
182 #define SUPERDOM_LEFT BUTTON_REW
183 #define SUPERDOM_RIGHT BUTTON_FF
184 #define SUPERDOM_CANCEL BUTTON_MENU
186 #elif CONFIG_KEYPAD == SANSA_FUZEPLUS_PAD
187 #define SUPERDOM_OK BUTTON_SELECT
188 #define SUPERDOM_UP BUTTON_UP
189 #define SUPERDOM_DOWN BUTTON_DOWN
190 #define SUPERDOM_LEFT BUTTON_LEFT
191 #define SUPERDOM_RIGHT BUTTON_RIGHT
192 #define SUPERDOM_CANCEL BUTTON_BACK
194 #elif CONFIG_KEYPAD == SANSA_CONNECT_PAD
195 #define SUPERDOM_OK BUTTON_SELECT
196 #define SUPERDOM_UP BUTTON_UP
197 #define SUPERDOM_DOWN BUTTON_DOWN
198 #define SUPERDOM_LEFT BUTTON_LEFT
199 #define SUPERDOM_RIGHT BUTTON_RIGHT
200 #define SUPERDOM_CANCEL BUTTON_POWER
202 #elif (CONFIG_KEYPAD == HM60X_PAD) || \
203 (CONFIG_KEYPAD == HM801_PAD)
204 #define SUPERDOM_OK BUTTON_SELECT
205 #define SUPERDOM_UP BUTTON_UP
206 #define SUPERDOM_DOWN BUTTON_DOWN
207 #define SUPERDOM_LEFT BUTTON_LEFT
208 #define SUPERDOM_RIGHT BUTTON_RIGHT
209 #define SUPERDOM_CANCEL BUTTON_POWER
211 #endif
213 #ifdef HAVE_TOUCHSCREEN
214 #ifndef SUPERDOM_OK
215 #define SUPERDOM_OK BUTTON_CENTER
216 #endif
217 #ifndef SUPERDOM_UP
218 #define SUPERDOM_UP BUTTON_TOPMIDDLE
219 #endif
220 #ifndef SUPERDOM_LEFT
221 #define SUPERDOM_LEFT BUTTON_MIDLEFT
222 #endif
223 #ifndef SUPERDOM_RIGHT
224 #define SUPERDOM_RIGHT BUTTON_MIDRIGHT
225 #endif
226 #ifndef SUPERDOM_DOWN
227 #define SUPERDOM_DOWN BUTTON_BOTTOMMIDDLE
228 #endif
229 #ifndef SUPERDOM_CANCEL
230 #define SUPERDOM_CANCEL BUTTON_TOPLEFT
231 #endif
232 #endif
234 enum {
235 RET_VAL_OK,
236 RET_VAL_USB,
237 RET_VAL_QUIT_ERR, /* quit or error */
240 static void gen_interest(void);
241 static void init_resources(void);
242 static int select_square(void);
243 static void update_score(void);
244 static void gen_resources(void);
245 static void draw_cursor(void);
246 static void draw_board(void);
248 struct tile{
249 signed int colour; /* -1 = Unset */
250 bool tank;
251 bool plane;
252 bool nuke;
253 bool ind;
254 bool farm;
255 int men;
258 struct resources {
259 int cash;
260 int food;
261 int farms;
262 int inds;
263 int men;
264 int tanks;
265 int planes;
266 int nukes;
267 int bank;
268 int moves;
271 static struct settings {
272 int compstartfarms;
273 int compstartinds;
274 int humanstartfarms;
275 int humanstartinds;
276 int startcash;
277 int startfood;
278 int movesperturn;
279 } superdom_settings;
281 static struct resources humanres;
282 static struct resources compres;
283 enum { GS_PROD, GS_MOVE, GS_WAR };
284 static int gamestate;
286 static struct cursor{
287 int x;
288 int y;
289 } cursor;
291 static struct tile board[12][12];
293 static void init_board(void) {
294 int i,j;
295 rb->srand(*rb->current_tick);
296 for(i=0;i<12;i++) { /* Hopefully about 50% each colour */
297 for(j=0;j<12;j++) {
298 if((i<1)||(j<1)||(i>10)||(j>10))
299 board[i][j].colour = -1; /* Unset */
300 else
301 board[i][j].colour = rb->rand()%2;
302 board[i][j].tank = false;
303 board[i][j].plane = false;
304 board[i][j].nuke = false;
305 board[i][j].ind = false;
306 board[i][j].farm = false;
307 board[i][j].men = 0;
311 while(compres.farms < superdom_settings.compstartfarms) {
312 i = rb->rand()%10 + 1;
313 j = rb->rand()%10 + 1;
314 if((board[i][j].colour == COLOUR_DARK) && (board[i][j].farm == false)) {
315 board[i][j].farm = true;
316 compres.farms++;
319 while(compres.inds < superdom_settings.compstartinds) {
320 i = rb->rand()%10 + 1;
321 j = rb->rand()%10 + 1;
322 if((board[i][j].colour == COLOUR_DARK) && (board[i][j].ind == false)) {
323 board[i][j].ind = true;
324 compres.inds++;
327 while(humanres.farms < superdom_settings.humanstartfarms) {
328 i = rb->rand()%10 + 1;
329 j = rb->rand()%10 + 1;
330 if((board[i][j].colour == COLOUR_LIGHT)&&(board[i][j].farm == false)) {
331 board[i][j].farm = true;
332 humanres.farms++;
335 while(humanres.inds < superdom_settings.humanstartinds) {
336 i = rb->rand()%10 + 1;
337 j = rb->rand()%10 + 1;
338 if((board[i][j].colour == COLOUR_LIGHT) && (board[i][j].ind == false)) {
339 board[i][j].ind = true;
340 humanres.inds++;
345 void draw_board(void) {
346 int i,j;
347 rb->lcd_clear_display();
348 for(i=1;i<11;i++) {
349 for(j=1;j<11;j++) {
350 if(board[i][j].colour == COLOUR_DARK) {
351 rb->lcd_set_foreground(LCD_DARKGRAY);
352 } else {
353 rb->lcd_set_foreground(LCD_LIGHTGRAY);
355 rb->lcd_fillrect(MARGIN+(BOX_WIDTH*(i-1)),
356 MARGIN+(BOX_HEIGHT*(j-1)), BOX_WIDTH,
357 BOX_HEIGHT);
358 #if LCD_DEPTH != 16
359 rb->lcd_set_drawmode(DRMODE_BG | DRMODE_INVERSEVID);
360 #endif
361 if(board[i][j].ind) {
362 MY_BITMAP_PART(superdom_boarditems,
363 board[i][j].colour?ICON_WIDTH:0, 0, ICON_STRIDE,
364 #if LCD_WIDTH > LCD_HEIGHT
365 MARGIN+(BOX_WIDTH*(i-1))+1,
366 MARGIN+(BOX_HEIGHT*(j-1))+ICON_HEIGHT+1,
367 #else
368 MARGIN+(BOX_WIDTH*(i-1))+1+ICON_WIDTH,
369 MARGIN+(BOX_HEIGHT*(j-1))+1,
370 #endif
371 ICON_WIDTH, ICON_HEIGHT);
373 if(board[i][j].farm) {
374 MY_BITMAP_PART(superdom_boarditems,
375 board[i][j].colour?ICON_WIDTH:0, ICON_HEIGHT,
376 ICON_STRIDE, MARGIN+(BOX_WIDTH*(i-1))+1,
377 MARGIN+(BOX_HEIGHT*(j-1))+1,
378 ICON_WIDTH, ICON_HEIGHT);
380 if(board[i][j].tank) {
381 MY_BITMAP_PART(superdom_boarditems,
382 board[i][j].colour?ICON_WIDTH:0, ICON_HEIGHT*2,
383 ICON_STRIDE, MARGIN+(BOX_WIDTH*(i-1))+ICON_WIDTH+1,
384 MARGIN+(BOX_HEIGHT*(j-1))+ICON_HEIGHT+1,
385 ICON_WIDTH, ICON_HEIGHT);
387 if(board[i][j].men) {
388 MY_BITMAP_PART(superdom_boarditems,
389 board[i][j].colour?ICON_WIDTH:0, ICON_HEIGHT*3,
390 #if LCD_WIDTH > LCD_HEIGHT
391 ICON_STRIDE, MARGIN+(BOX_WIDTH*(i-1))+ICON_WIDTH+1,
392 MARGIN+(BOX_HEIGHT*(j-1))+1,
393 #else
394 ICON_STRIDE, MARGIN+(BOX_WIDTH*(i-1))+1,
395 MARGIN+(BOX_HEIGHT*(j-1))+1+ICON_HEIGHT,
396 #endif
397 ICON_WIDTH, ICON_HEIGHT);
399 if(board[i][j].plane) {
400 MY_BITMAP_PART(superdom_boarditems,
401 board[i][j].colour?ICON_WIDTH:0, ICON_HEIGHT*4,
402 #if LCD_WIDTH > LCD_HEIGHT
403 ICON_STRIDE,MARGIN+(BOX_WIDTH*(i-1))+ICON_WIDTH*2+1,
404 MARGIN+(BOX_HEIGHT*(j-1))+ICON_HEIGHT+1,
405 #else
406 ICON_STRIDE,MARGIN+(BOX_WIDTH*(i-1))+ICON_WIDTH+1,
407 MARGIN+(BOX_HEIGHT*(j-1))+ICON_HEIGHT*2+1,
408 #endif
409 ICON_WIDTH, ICON_HEIGHT);
411 if(board[i][j].nuke) {
412 MY_BITMAP_PART(superdom_boarditems,
413 board[i][j].colour?ICON_WIDTH:0, ICON_HEIGHT*5,
414 #if LCD_WIDTH > LCD_HEIGHT
415 ICON_STRIDE,MARGIN+(BOX_WIDTH*(i-1))+ICON_WIDTH*2+1,
416 MARGIN+(BOX_HEIGHT*(j-1))+1,
417 #else
418 ICON_STRIDE,MARGIN+(BOX_WIDTH*(i-1))+1,
419 MARGIN+(BOX_HEIGHT*(j-1))+ICON_HEIGHT*2+1,
420 #endif
421 ICON_WIDTH, ICON_HEIGHT);
423 #if LCD_DEPTH != 16
424 rb->lcd_set_drawmode(DRMODE_SOLID);
425 #endif
428 rb->lcd_set_foreground(LCD_BLACK);
429 for(i=0;i<=10;i++) { /* Draw Horizontal lines */
430 rb->lcd_hline(MARGIN, MARGIN+(BOX_WIDTH*10), MARGIN+(BOX_HEIGHT*i));
432 for(i=0;i<=10;i++) { /* Draw Vertical lines */
433 rb->lcd_vline(MARGIN+(BOX_WIDTH*i), MARGIN, MARGIN+(BOX_HEIGHT*10));
435 rb->lcd_update();
438 static int calc_strength(int colour, int x, int y) {
439 int a, b, score=0;
440 for (a = -1; a < 2; a++) {
441 for (b = -1; b < 2; b++) {
442 if ((b == 0 || a == 0) &&
443 (board[x + a][y + b].colour == colour)) {
444 score += 10;
445 if(board[x + a][y + b].tank || board[x + a][y + b].farm)
446 score += 30;
447 if(board[x + a][y + b].plane || board[x + a][y + b].ind)
448 score += 40;
449 if(board[x + a][y + b].nuke)
450 score += 20;
451 if(board[x + a][y + b].men)
452 score += (board[x + a][y + b].men*133/1000);
456 return score;
459 void gen_interest(void) {
460 /* Interest should be around 10% */
461 rb->srand(*rb->current_tick);
462 int interest = 7+rb->rand()%6;
463 humanres.bank = humanres.bank+(interest*humanres.bank/100);
464 compres.bank = compres.bank+(interest*compres.bank/100);
467 void draw_cursor(void) {
468 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
469 rb->lcd_fillrect(MARGIN+((cursor.x-1)*BOX_WIDTH),
470 MARGIN+((cursor.y-1)*BOX_HEIGHT), BOX_WIDTH+1, BOX_HEIGHT+1);
471 rb->lcd_set_drawmode(DRMODE_SOLID);
472 rb->lcd_update();
475 void gen_resources(void) {
476 int inccash = 0;
477 int incfood = 0;
478 int ratecash = 0;
479 int ratefood = 0;
480 int i;
481 gen_interest();
482 rb->srand(*rb->current_tick);
483 /* Generate Human's resources */
484 for(i=0;i<humanres.inds;i++) {
485 inccash += (300+rb->rand()%200);
487 for(i=0;i<humanres.farms;i++) {
488 incfood += (200+rb->rand()%200);
490 if(humanres.inds)
491 ratecash = inccash/humanres.inds;
492 if(humanres.farms)
493 ratefood = incfood/humanres.farms;
494 if(ratecash > 450) {
495 if(ratefood > 350) {
496 rb->splash(HZ*2, "Patriotism sweeps the land, all production"
497 " is up this year!");
498 } else {
499 rb->splash(HZ*2, "Factories working at maximum efficiency,"
500 " cash production up this year!");
502 } else if(ratecash > 350) {
503 if(ratefood > 350) {
504 rb->splash(HZ*2, "Record crop harvest this year!");
505 } else if(ratefood > 250) {
506 rb->splash(HZ*2, "Production continues as normal");
507 } else {
508 rb->splash(HZ*2, "Spoilage of crops leads to reduced farm"
509 " output this year");
511 } else {
512 if(ratefood > 350) {
513 rb->splash(HZ*2, "Record crop harvest this year!");
514 } else if(ratefood > 250) {
515 rb->splash(HZ*2, "Factory unions introduced. Industrial"
516 " production is down this year.");
517 } else {
518 rb->splash(HZ*2, "Internet created. All production is down"
519 " due to time wasted.");
522 humanres.cash += inccash;
523 humanres.food += incfood;
525 /* Generate Computer's resources */
526 inccash = 0;
527 incfood = 0;
528 for(i=0;i<compres.inds;i++) {
529 inccash += (300+rb->rand()%200);
531 for(i=0;i<compres.farms;i++) {
532 incfood += (200+rb->rand()%200);
534 compres.cash += inccash;
535 compres.food += incfood;
538 static void update_score(void) {
539 int strength;
540 rb->lcd_setfont(FONT_SYSFIXED);
541 rb->lcd_set_drawmode(DRMODE_BG|DRMODE_INVERSEVID);
542 rb->lcd_fillrect(5,LCD_HEIGHT-20,105,20);
543 rb->lcd_set_drawmode(DRMODE_SOLID);
544 strength = calc_strength(COLOUR_LIGHT, cursor.x, cursor.y);
545 rb->lcd_putsxyf(5,LCD_HEIGHT-20,"Your power: %d.%d",strength/10,strength%10);
546 strength = calc_strength(COLOUR_DARK, cursor.x, cursor.y);
547 rb->lcd_putsxyf(5,LCD_HEIGHT-10,"Comp power: %d.%d",strength/10,strength%10);
548 rb->lcd_setfont(FONT_UI);
551 static int settings_menu(void) {
552 int selection = 0;
554 MENUITEM_STRINGLIST(menu, "Super Domination Settings", NULL,
555 "Computer starting farms", "Computer starting factories",
556 "Human starting farms", "Human starting factories",
557 "Starting cash", "Starting food", "Moves per turn");
559 while(1) {
560 switch(rb->do_menu(&menu, &selection, NULL, false)) {
561 case 0:
562 rb->set_int("Computer starting farms", "", UNIT_INT,
563 &superdom_settings.compstartfarms, NULL,
564 1, 0, 5, NULL);
565 break;
566 case 1:
567 rb->set_int("Computer starting factories", "", UNIT_INT,
568 &superdom_settings.compstartinds, NULL,
569 1, 0, 5, NULL);
570 break;
571 case 2:
572 rb->set_int("Human starting farms", "", UNIT_INT,
573 &superdom_settings.humanstartfarms, NULL,
574 1, 0, 5, NULL);
575 break;
576 case 3:
577 rb->set_int("Human starting factories", "", UNIT_INT,
578 &superdom_settings.humanstartinds, NULL,
579 1, 0, 5, NULL);
580 break;
581 case 4:
582 rb->set_int("Starting cash", "", UNIT_INT,
583 &superdom_settings.startcash, NULL,
584 250, 0, 5000, NULL);
585 break;
586 case 5:
587 rb->set_int("Starting food", "", UNIT_INT,
588 &superdom_settings.startfood, NULL,
589 250, 0, 5000, NULL);
590 break;
591 case 6:
592 rb->set_int("Moves per turn", "", UNIT_INT,
593 &superdom_settings.movesperturn, NULL,
594 1, 1, 5, NULL);
595 break;
596 case MENU_ATTACHED_USB:
597 return RET_VAL_USB;
598 break;
599 case GO_TO_PREVIOUS:
600 return RET_VAL_OK;
601 break;
604 return RET_VAL_OK;
607 static int superdom_help(void) {
608 static char* help_text[] = {
609 "Super", "domination", "is", "a", "turn", "based", "strategy", "game,",
610 "where", "the", "aim", "is", "to", "overpower", "the", "computer",
611 "player", "by", "taking", "their", "territory.", "",
612 "Each", "year", "you", "are", "allocated", "an", "amount", "of", "cash",
613 "and", "food,", "depending", "on", "how", "many", "farms", "and",
614 "factories", "you", "control.", "",
615 "Use", "this", "cash", "and", "food", "to", "buy", "and", "feed", "your",
616 "army.", "Each", "tile", "has", "a", "strength,", "calculated", "by",
617 "the", "ownership", "of", "adjacent", "tiles,", "and", "the", "type",
618 "and", "number", "of", "troops", "on", "them.",
621 if (display_text(ARRAYLEN(help_text), help_text, NULL, NULL, true))
622 return RET_VAL_USB;
623 return RET_VAL_OK;
626 static int start_menu(void) {
627 int selection = 0;
629 MENUITEM_STRINGLIST(menu, "Super Domination Menu", NULL,
630 "Play Super Domination", "Settings",
631 "Help", "Playback Control", "Quit");
633 while(1) {
634 switch(rb->do_menu(&menu, &selection, NULL, false)) {
635 case 0:
636 return RET_VAL_OK; /* start playing */
637 break;
638 case 1:
639 if(settings_menu()==RET_VAL_USB)
640 return RET_VAL_USB;
641 break;
642 case 2:
643 if(superdom_help()==RET_VAL_USB)
644 return RET_VAL_USB;
645 break;
646 case 3:
647 if(playback_control(NULL))
648 return RET_VAL_USB;
649 break;
650 case 4:
651 return RET_VAL_QUIT_ERR;
652 break;
655 return RET_VAL_QUIT_ERR;
658 static int save_game(void) {
659 int fd;
660 char savepath[MAX_PATH];
662 rb->snprintf(savepath, sizeof(savepath), "/Savegame.ssg");
663 if(rb->kbd_input(savepath, MAX_PATH)) {
664 DEBUGF("Keyboard input failed\n");
665 return -1;
668 fd = rb->open(savepath, O_WRONLY|O_CREAT, 0666);
669 DEBUGF("savepath: %s\n", savepath);
670 if(fd < 0) {
671 DEBUGF("Couldn't create/open file\n");
672 return -1;
675 rb->write(fd, "SSGv3", 5);
676 rb->write(fd, &gamestate, sizeof(gamestate));
677 rb->write(fd, &humanres.cash, sizeof(humanres.cash));
678 rb->write(fd, &humanres.food, sizeof(humanres.food));
679 rb->write(fd, &humanres.bank, sizeof(humanres.bank));
680 rb->write(fd, &humanres.planes, sizeof(humanres.planes));
681 rb->write(fd, &humanres.tanks, sizeof(humanres.tanks));
682 rb->write(fd, &humanres.men, sizeof(humanres.men));
683 rb->write(fd, &humanres.nukes, sizeof(humanres.nukes));
684 rb->write(fd, &humanres.inds, sizeof(humanres.inds));
685 rb->write(fd, &humanres.farms, sizeof(humanres.farms));
686 rb->write(fd, &humanres.moves, sizeof(humanres.moves));
687 rb->write(fd, &compres.cash, sizeof(compres.cash));
688 rb->write(fd, &compres.food, sizeof(compres.food));
689 rb->write(fd, &compres.bank, sizeof(compres.bank));
690 rb->write(fd, &compres.planes, sizeof(compres.planes));
691 rb->write(fd, &compres.tanks, sizeof(compres.tanks));
692 rb->write(fd, &compres.men, sizeof(compres.men));
693 rb->write(fd, &compres.nukes, sizeof(compres.nukes));
694 rb->write(fd, &compres.inds, sizeof(compres.inds));
695 rb->write(fd, &compres.farms, sizeof(compres.farms));
696 rb->write(fd, &compres.moves, sizeof(compres.moves));
697 rb->write(fd, board, sizeof(board));
698 rb->write(fd, &superdom_settings.compstartfarms, sizeof(int));
699 rb->write(fd, &superdom_settings.compstartinds, sizeof(int));
700 rb->write(fd, &superdom_settings.humanstartfarms, sizeof(int));
701 rb->write(fd, &superdom_settings.humanstartinds, sizeof(int));
702 rb->write(fd, &superdom_settings.startcash, sizeof(int));
703 rb->write(fd, &superdom_settings.startfood, sizeof(int));
704 rb->write(fd, &superdom_settings.movesperturn, sizeof(int));
705 rb->close(fd);
706 return 0;
709 static int ingame_menu(void) {
710 MENUITEM_STRINGLIST(menu, "Super Domination Menu", NULL,
711 "Return to game", "Save Game",
712 "Playback Control", "Quit");
714 switch(rb->do_menu(&menu, NULL, NULL, false)) {
715 case 0:
716 return RET_VAL_OK;
717 break;
718 case 1:
719 if(!save_game())
720 rb->splash(HZ, "Game saved");
721 else
722 rb->splash(HZ, "Error in save");
723 break;
724 case 2:
725 if(playback_control(NULL))
726 return RET_VAL_USB;
727 break;
728 case 3:
729 return RET_VAL_QUIT_ERR;
730 break;
731 case MENU_ATTACHED_USB:
732 return RET_VAL_USB;
733 break;
734 case GO_TO_PREVIOUS:
735 return RET_VAL_OK;
736 break;
738 return RET_VAL_OK;
741 static int get_number(char* param, int* value, int max) {
742 static const char *button_labels[4][3] = {
743 { "1", "2", "3" },
744 { "4", "5", "6" },
745 { "7", "8", "9" },
746 { "CLR", "0", "OK" }
748 int i,j,x=0,y=0;
749 int height, width;
750 int button = 0, ret = RET_VAL_OK;
751 bool done = false;
752 rb->lcd_clear_display();
753 rb->lcd_getstringsize("CLR", &width, &height);
754 if(width > NUM_BOX_WIDTH || height > NUM_BOX_HEIGHT)
755 rb->lcd_setfont(FONT_SYSFIXED);
756 /* Draw a 3x4 grid */
757 for(i=0;i<=3;i++) { /* Vertical lines */
758 rb->lcd_vline(NUM_MARGIN_X+(NUM_BOX_WIDTH*i), NUM_MARGIN_Y,
759 NUM_MARGIN_Y+(4*NUM_BOX_HEIGHT));
761 for(i=0;i<=4;i++) { /* Horizontal lines */
762 rb->lcd_hline(NUM_MARGIN_X, NUM_MARGIN_X+(3*NUM_BOX_WIDTH),
763 NUM_MARGIN_Y+(NUM_BOX_HEIGHT*i));
765 for(i=0;i<4;i++) {
766 for(j=0;j<3;j++) {
767 rb->lcd_getstringsize(button_labels[i][j], &width, &height);
768 rb->lcd_putsxy(
769 NUM_MARGIN_X+(j*NUM_BOX_WIDTH)+NUM_BOX_WIDTH/2-width/2,
770 NUM_MARGIN_Y+(i*NUM_BOX_HEIGHT)+NUM_BOX_HEIGHT/2-height/2,
771 button_labels[i][j]);
774 rb->lcd_putsxyf(NUM_MARGIN_X+10, NUM_MARGIN_Y+4*NUM_BOX_HEIGHT+10,"%d",*value);
775 rb->lcd_getstringsize(param, &width, &height);
776 if(width < LCD_WIDTH)
777 rb->lcd_putsxy((LCD_WIDTH-width)/2, (NUM_MARGIN_Y-height)/2, param);
778 else
779 rb->lcd_puts_scroll(0, (NUM_MARGIN_Y/height-1)/2, param);
780 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
781 rb->lcd_fillrect(NUM_MARGIN_X+(NUM_BOX_WIDTH*x),
782 NUM_MARGIN_Y+(NUM_BOX_HEIGHT*y),
783 NUM_BOX_WIDTH+1, NUM_BOX_HEIGHT+1);
784 rb->lcd_set_drawmode(DRMODE_SOLID);
785 rb->lcd_update();
786 while(!done) {
787 button = rb->button_get(true);
788 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
789 rb->lcd_fillrect(NUM_MARGIN_X+(NUM_BOX_WIDTH*x),
790 NUM_MARGIN_Y+(NUM_BOX_HEIGHT*y),
791 NUM_BOX_WIDTH+1, NUM_BOX_HEIGHT+1);
792 rb->lcd_set_drawmode(DRMODE_SOLID);
793 switch(button) {
794 case SUPERDOM_OK:
795 if(y!=3) {
796 *value *= 10;
797 *value += button_labels[y][x][0] - '0';
798 } else if(x==0) {
799 *value /= 10;
800 } else if(x==1) {
801 *value *= 10;
802 } else if(x==2) {
803 done = true;
804 break;
806 if ((unsigned) *value > (unsigned) max)
807 *value = max;
808 rb->lcd_set_drawmode(DRMODE_BG|DRMODE_INVERSEVID);
809 rb->lcd_fillrect(0, NUM_MARGIN_Y+4*NUM_BOX_HEIGHT+10,
810 LCD_WIDTH, 30);
811 rb->lcd_set_drawmode(DRMODE_SOLID);
812 rb->lcd_putsxyf(NUM_MARGIN_X+10,NUM_MARGIN_Y+4*NUM_BOX_HEIGHT+10,
813 "%d", *value);
814 break;
815 case SUPERDOM_CANCEL:
816 *value = 0;
817 done = true;
818 ret = RET_VAL_QUIT_ERR;
819 break;
820 #if CONFIG_KEYPAD != IRIVER_H10_PAD
821 case SUPERDOM_LEFT:
822 if(x==0) {
823 #ifdef IPOD_STYLE
824 if(y>0)
825 y--;
826 else
827 y=3;
828 #endif
829 x=2;
830 } else {
831 x--;
833 break;
834 case SUPERDOM_RIGHT:
835 if(x==2) {
836 #ifdef IPOD_STYLE
837 if(y==3)
838 y=0;
839 else
840 y++;
841 #endif
842 x=0;
843 } else {
844 x++;
846 break;
847 #endif
848 #ifndef IPOD_STYLE
849 case SUPERDOM_UP:
850 if(y==0) {
851 #if CONFIG_KEYPAD == IRIVER_H10_PAD
852 if(x > 0)
853 x--;
854 else
855 x=2;
856 #endif
857 y=3;
858 } else {
859 y--;
861 break;
862 case SUPERDOM_DOWN:
863 if(y==3) {
864 #if CONFIG_KEYPAD == IRIVER_H10_PAD
865 if(x < 2)
866 x++;
867 else
868 x=0;
869 #endif
870 y=0;
871 } else {
872 y++;
874 break;
875 #endif
876 default:
877 if (rb->default_event_handler(button) == SYS_USB_CONNECTED)
879 done = true;
880 ret = RET_VAL_USB;
882 break;
884 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
885 rb->lcd_fillrect(NUM_MARGIN_X+(NUM_BOX_WIDTH*x),
886 NUM_MARGIN_Y+(NUM_BOX_HEIGHT*y),
887 NUM_BOX_WIDTH+1, NUM_BOX_HEIGHT+1);
888 rb->lcd_set_drawmode(DRMODE_SOLID);
889 rb->lcd_update();
891 rb->lcd_setfont(FONT_UI);
892 rb->lcd_stop_scroll();
893 if (ret == RET_VAL_QUIT_ERR)
894 rb->splash(HZ, "Cancelled");
895 return ret;
898 static bool tile_has_item(int type, int x, int y) {
899 switch(type) {
900 case 0:
901 return (board[x][y].men > 0);
902 break;
903 case 1:
904 return board[x][y].tank;
905 break;
906 case 2:
907 return board[x][y].plane;
908 break;
909 case 3:
910 return board[x][y].farm;
911 break;
912 case 4:
913 return board[x][y].ind;
914 break;
915 case 5:
916 return board[x][y].nuke;
917 break;
919 return false;
922 static int buy_resources(int colour, int type, int x, int y, int nummen) {
923 const char *itemnames[][6] = {
925 "them",
926 "the tank",
927 "the plane",
928 "the farm",
929 "the industrial plant",
930 "the nuke",
931 }, {
932 "place men",
933 "place a tank",
934 "place a plane",
935 "build a farm",
936 "build an industrial plant",
937 "place a nuke",
938 }, {
939 NULL,
940 "a tank",
941 "a plane",
942 "a farm",
943 "an industrial plant",
944 "a nuke",
948 bool human = (colour == COLOUR_LIGHT);
949 int price = 0;
950 int temp;
951 struct resources *res;
953 if(human) {
954 res = &humanres;
955 } else {
956 res = &compres;
958 switch(type) {
959 case 0: /* men */
960 price = 1*nummen;
961 break;
962 case 1: /* tank */
963 price = 300;
964 break;
965 case 2: /* plane */
966 price = 600;
967 break;
968 case 3: /* Farm */
969 price = 1150;
970 break;
971 case 4: /* Factory */
972 price = 1300;
973 break;
974 case 5: /* nuke */
975 price = 2000;
976 break;
978 if(res->cash < price) {
979 if(human)
980 rb->splash(HZ, "Not enough money!");
981 return RET_VAL_QUIT_ERR;
983 if(human) {
984 rb->splashf(HZ, "Where do you want to place %s?", itemnames[0][type]);
985 if((temp = select_square()) != RET_VAL_OK)
986 return temp;
987 x = cursor.x;
988 y = cursor.y;
990 if(board[x][y].colour != colour) {
991 if(human)
992 rb->splashf(HZ, "Can't %s on enemy territory", itemnames[1][type]);
993 return RET_VAL_QUIT_ERR;
995 if(type != 0 && tile_has_item(type, x, y)) {
996 if(human)
997 rb->splashf(HZ, "There is already %s there", itemnames[2][type]);
998 return RET_VAL_QUIT_ERR;
1000 switch(type) {
1001 case 0:
1002 board[x][y].men += nummen;
1003 res->men += nummen;
1004 break;
1005 case 1:
1006 board[x][y].tank = true;
1007 res->tanks++;
1008 break;
1009 case 2:
1010 board[x][y].plane = true;
1011 res->planes++;
1012 break;
1013 case 3:
1014 board[x][y].farm = true;
1015 res->farms++;
1016 break;
1017 case 4:
1018 board[x][y].ind = true;
1019 res->inds++;
1020 break;
1021 case 5:
1022 board[x][y].nuke = true;
1023 res->nukes++;
1024 break;
1026 res->cash -= price;
1028 draw_board();
1029 rb->sleep(HZ);
1031 return RET_VAL_OK;
1034 static int buy_resources_menu(void) {
1035 int selection = 0,nummen;
1037 MENUITEM_STRINGLIST(menu, "Buy Resources", NULL,
1038 "Buy men ($1)", "Buy tank ($300)", "Buy plane ($600)",
1039 "Buy Farm ($1150)", "Buy Factory ($1300)",
1040 "Buy Nuke ($2000)",
1041 "Finish buying");
1043 while(1) {
1044 switch(rb->do_menu(&menu, &selection, NULL, false)) {
1045 case 0:
1046 nummen = 0;
1047 if(get_number("How many men would you like?", &nummen,
1048 humanres.cash) == RET_VAL_USB)
1049 return RET_VAL_USB;
1050 if(!nummen)
1051 break;
1052 /* fall through */
1053 case 1:
1054 case 2:
1055 case 3:
1056 case 4:
1057 case 5:
1058 if(buy_resources(COLOUR_LIGHT, selection, 0, 0, nummen)
1059 == RET_VAL_USB)
1060 return RET_VAL_USB;
1061 break;
1062 case 6:
1063 return RET_VAL_OK;
1064 break;
1065 case MENU_ATTACHED_USB:
1066 return RET_VAL_USB;
1067 break;
1068 case GO_TO_PREVIOUS:
1069 return RET_VAL_OK;
1070 break;
1073 return RET_VAL_OK;
1076 static int move_unit(int colour, int type, int fromx, int fromy,
1077 int tox, int toy, int nummen) {
1078 const char *itemnames[][3] = {
1080 "troops",
1081 "the tank",
1082 "the plane",
1083 }, {
1084 "any troops",
1085 "a tank",
1086 "a plane",
1087 }, {
1088 "the troops",
1089 "the tank",
1090 "the plane",
1093 bool human = (colour == COLOUR_LIGHT);
1094 int temp;
1096 if(human) {
1097 rb->splashf(HZ, "Select where you want to move %s from",
1098 itemnames[0][type]);
1099 if((temp = select_square()) != RET_VAL_OK)
1100 return temp;
1101 fromx = cursor.x;
1102 fromy = cursor.y;
1104 if(board[fromx][fromy].colour != colour) {
1105 if(human)
1106 rb->splash(HZ, "That isn't your territory");
1107 return RET_VAL_QUIT_ERR;
1109 if(!tile_has_item(type, fromx, fromy)) {
1110 if(human)
1111 rb->splashf(HZ, "You don't have %s there", itemnames[1][type]);
1112 return RET_VAL_QUIT_ERR;
1114 if(type == 0) {
1115 if(human) {
1116 nummen = board[fromx][fromy].men;
1117 if((temp = get_number("How many men do you want to move?", &nummen,
1118 nummen)) != RET_VAL_OK)
1119 return temp;
1121 if(nummen > board[fromx][fromy].men) {
1122 if(human)
1123 rb->splash(HZ, "You don't have that many troops.");
1124 return RET_VAL_QUIT_ERR;
1127 if(human) {
1128 rb->splashf(HZ, "Select where you want to move %s to",
1129 itemnames[2][type]);
1130 if((temp = select_square()) != RET_VAL_OK)
1131 return temp;
1132 tox = cursor.x;
1133 toy = cursor.y;
1135 if((tox == fromx && toy == fromy) ||
1136 board[tox][toy].colour != colour ||
1137 (type != 2 && (abs(tox - fromx) > 1 || abs(toy - fromy) > 1))) {
1138 if(human)
1139 rb->splash(HZ, "Invalid move");
1140 return RET_VAL_QUIT_ERR;
1142 if(type != 0 && tile_has_item(type, tox, toy)) {
1143 if(human)
1144 rb->splashf(HZ, "There is already %s there", itemnames[1][type]);
1145 return RET_VAL_QUIT_ERR;
1147 switch(type) {
1148 case 0:
1149 board[fromx][fromy].men -= nummen;
1150 board[tox][toy].men += nummen;
1151 break;
1152 case 1:
1153 board[fromx][fromy].tank = false;
1154 board[tox][toy].tank = true;
1155 break;
1156 case 2:
1157 board[fromx][fromy].plane = false;
1158 board[tox][toy].plane = true;
1159 break;
1161 return RET_VAL_OK;
1164 static int move_unit_menu(void) {
1165 int selection = 0;
1167 MENUITEM_STRINGLIST(menu, "Move unit", NULL,
1168 "Move men", "Move tank", "Move plane");
1169 switch(rb->do_menu(&menu, &selection, NULL, false)) {
1170 case 0:
1171 case 1:
1172 case 2:
1173 switch(move_unit(COLOUR_LIGHT, selection, 0, 0, 0, 0, 0)) {
1174 case RET_VAL_OK:
1175 humanres.moves--;
1176 break;
1177 case RET_VAL_USB:
1178 return RET_VAL_USB;
1179 break;
1181 break;
1182 case MENU_ATTACHED_USB:
1183 return RET_VAL_USB;
1185 return RET_VAL_OK;
1188 static int launch_nuke(int colour, int nukex, int nukey, int targetx, int targety) {
1189 bool human = (colour == COLOUR_LIGHT);
1190 int temp;
1191 struct resources *res;
1193 if(board[nukex][nukey].colour != colour) {
1194 if(human)
1195 rb->splash(HZ, "That isn't your territory");
1196 return RET_VAL_QUIT_ERR;
1198 if(! board[nukex][nukey].nuke) {
1199 if(human)
1200 rb->splashf(HZ, "You don't have %s there", "a nuke");
1201 return RET_VAL_QUIT_ERR;
1203 if(human) {
1204 rb->splash(HZ, "Select place to target with nuke");
1205 if((temp = select_square()) != RET_VAL_OK)
1206 return temp;
1207 targetx = cursor.x;
1208 targety = cursor.y;
1210 if(human) {
1211 humanres.nukes--;
1212 } else {
1213 compres.nukes--;
1215 board[nukex][nukey].nuke = false;
1217 if(board[targetx][targety].colour == COLOUR_LIGHT) {
1218 res = &humanres;
1219 } else {
1220 res = &compres;
1222 res->men -= board[targetx][targety].men;
1223 res->tanks -= board[targetx][targety].tank;
1224 res->planes -= board[targetx][targety].plane;
1225 res->nukes -= board[targetx][targety].nuke;
1226 res->farms -= board[targetx][targety].farm;
1227 res->inds -= board[targetx][targety].ind;
1228 board[targetx][targety].men = 0;
1229 board[targetx][targety].tank = false;
1230 board[targetx][targety].plane = false;
1231 board[targetx][targety].ind = false;
1232 board[targetx][targety].nuke = false;
1233 board[targetx][targety].farm = false;
1234 /* TODO: Fallout carried by wind */
1236 return RET_VAL_OK;
1239 static int movement_menu(void) {
1240 int selection = 0, temp;
1242 MENUITEM_STRINGLIST(menu, "Movement", NULL,
1243 "Move unit", "Buy additional moves ($100)",
1244 "Launch nuclear missile", "Check map",
1245 "Finish moving", "Game menu");
1247 while(1) {
1248 switch(rb->do_menu(&menu, &selection, NULL, false)) {
1249 case 0:
1250 if(humanres.moves) {
1251 if(move_unit_menu()==RET_VAL_USB)
1252 return RET_VAL_USB;
1253 } else {
1254 rb->splash(HZ, "You have no more moves left."
1255 " You can buy more for $100 each.");
1257 break;
1258 case 1:
1259 if(humanres.cash > 100) {
1260 humanres.moves++;
1261 humanres.cash -= 100;
1262 rb->snprintf(buf, sizeof(buf), "You now have %d moves",
1263 humanres.moves);
1264 rb->splash(HZ, buf);
1266 break;
1267 case 2:
1268 if(humanres.nukes==0) {
1269 rb->splash(HZ, "You do not have any nukes to launch");
1270 } else {
1271 rb->splash(HZ, "Select place to launch nuke from");
1272 switch(select_square()) {
1273 case RET_VAL_OK:
1274 if(launch_nuke(COLOUR_LIGHT, cursor.x, cursor.y,
1275 0, 0) == RET_VAL_USB)
1276 return RET_VAL_USB;
1277 break;
1278 case RET_VAL_USB:
1279 return RET_VAL_USB;
1280 break;
1283 break;
1284 case 3:
1285 if(select_square() == RET_VAL_USB)
1286 return RET_VAL_USB;
1287 break;
1288 case 4:
1289 return RET_VAL_OK;
1290 break;
1291 case 5:
1292 if((temp = ingame_menu()) != RET_VAL_OK)
1293 return temp;
1294 break;
1295 case MENU_ATTACHED_USB:
1296 return RET_VAL_USB;
1297 break;
1300 return RET_VAL_OK;
1303 static const char* inventory_data(int selected_item, void * data,
1304 char * buffer, size_t buffer_len) {
1305 (void)data;
1306 switch(selected_item) {
1307 case 0:
1308 rb->snprintf(buffer,buffer_len,"Men: %d", humanres.men);
1309 break;
1310 case 1:
1311 rb->snprintf(buffer,buffer_len,"Tanks: %d", humanres.tanks);
1312 break;
1313 case 2:
1314 rb->snprintf(buffer,buffer_len,"Planes: %d", humanres.planes);
1315 break;
1316 case 3:
1317 rb->snprintf(buffer,buffer_len,"Factories: %d", humanres.inds);
1318 break;
1319 case 4:
1320 rb->snprintf(buffer,buffer_len,"Farms: %d", humanres.farms);
1321 break;
1322 case 5:
1323 rb->snprintf(buffer,buffer_len,"Nukes: %d", humanres.nukes);
1324 break;
1325 case 6:
1326 rb->snprintf(buffer,buffer_len,"Cash: %d", humanres.cash);
1327 break;
1328 case 7:
1329 rb->snprintf(buffer,buffer_len,"Food: %d", humanres.food);
1330 break;
1331 case 8:
1332 rb->snprintf(buffer,buffer_len,"Bank: %d", humanres.bank);
1333 break;
1334 default:
1335 return NULL;
1337 return buffer;
1340 static int show_inventory(void) {
1341 struct simplelist_info info;
1342 rb->simplelist_info_init(&info, "Inventory", 9, NULL);
1343 info.hide_selection = true;
1344 info.get_name = inventory_data;
1345 if(rb->simplelist_show_list(&info)) {
1346 return RET_VAL_USB;
1347 } else {
1348 return RET_VAL_OK;
1352 static int production_menu(void) {
1353 int selection = 0, temp;
1355 MENUITEM_STRINGLIST(menu, "Production", NULL,
1356 "Buy resources", "Show inventory", "Check map",
1357 "Invest money", "Withdraw money",
1358 "Finish turn", "Game menu");
1360 while(1) {
1361 switch(rb->do_menu(&menu, &selection, NULL, false)) {
1362 case 0:
1363 if(buy_resources_menu() == RET_VAL_USB)
1364 return RET_VAL_USB;
1365 break;
1366 case 1:
1367 if(show_inventory() == RET_VAL_USB)
1368 return RET_VAL_USB;
1369 break;
1370 case 2:
1371 if(select_square() == RET_VAL_USB)
1372 return RET_VAL_USB;
1373 break;
1374 case 3:
1375 temp = humanres.cash;
1376 if(get_number("How much do you want to invest?", &temp,
1377 humanres.cash) == RET_VAL_USB)
1378 return RET_VAL_USB;
1379 if(temp > humanres.cash) {
1380 rb->splash(HZ, "You don't have that much cash to invest");
1381 } else {
1382 humanres.cash -= temp;
1383 humanres.bank += temp;
1385 break;
1386 case 4:
1387 temp = humanres.bank;
1388 if(get_number("How much do you want to withdraw?", &temp,
1389 humanres.bank) == RET_VAL_USB)
1390 return RET_VAL_USB;
1391 if(temp > humanres.bank) {
1392 rb->splash(HZ, "You don't have that much cash to withdraw");
1393 } else {
1394 humanres.cash += temp;
1395 humanres.bank -= temp;
1397 break;
1398 case 5:
1399 return RET_VAL_OK;
1400 break;
1401 case 6:
1402 if((temp = ingame_menu()) != RET_VAL_OK)
1403 return temp;
1404 break;
1405 case MENU_ATTACHED_USB:
1406 return RET_VAL_USB;
1407 break;
1410 return RET_VAL_OK;
1413 static void init_resources(void) {
1414 humanres.cash = superdom_settings.startcash;
1415 humanres.food = superdom_settings.startfood;
1416 humanres.tanks = 0;
1417 humanres.planes = 0;
1418 humanres.nukes = 0;
1419 humanres.inds = 0;
1420 humanres.farms = 0;
1421 humanres.men = 0;
1422 humanres.bank = 0;
1423 humanres.moves = 0;
1424 compres.cash = superdom_settings.startcash;
1425 compres.food = superdom_settings.startfood;
1426 compres.tanks = 0;
1427 compres.planes = 0;
1428 compres.nukes = 0;
1429 compres.inds = 0;
1430 compres.farms = 0;
1431 compres.men = 0;
1432 compres.bank = 0;
1433 compres.moves = 0;
1436 static int select_square(void) {
1437 int button = 0;
1438 draw_board();
1439 draw_cursor();
1440 update_score();
1441 #if LCD_WIDTH >= 220
1442 rb->lcd_setfont(FONT_SYSFIXED);
1443 rb->lcd_putsxyf(125, LCD_HEIGHT-20,"Cash: %d", humanres.cash);
1444 rb->lcd_putsxyf(125, LCD_HEIGHT-10,"Food: %d", humanres.food);
1445 rb->lcd_setfont(FONT_UI);
1446 #endif
1447 rb->lcd_update();
1448 while(1) {
1449 button = rb->button_get(true);
1450 switch(button) {
1451 case SUPERDOM_CANCEL:
1452 rb->splash(HZ, "Cancelled");
1453 return RET_VAL_QUIT_ERR;
1454 break;
1455 case SUPERDOM_OK:
1456 return RET_VAL_OK;
1457 break;
1458 #if CONFIG_KEYPAD != IRIVER_H10_PAD
1459 case SUPERDOM_LEFT:
1460 case (SUPERDOM_LEFT|BUTTON_REPEAT):
1461 draw_cursor(); /* Deselect the current tile */
1462 if(cursor.x>1) {
1463 cursor.x--;
1464 } else {
1465 #ifdef IPOD_STYLE
1466 if(cursor.y>1)
1467 cursor.y--;
1468 else
1469 cursor.y = 10;
1470 #endif
1471 cursor.x = 10;
1473 update_score();
1474 draw_cursor();
1475 break;
1476 case SUPERDOM_RIGHT:
1477 case (SUPERDOM_RIGHT|BUTTON_REPEAT):
1478 draw_cursor(); /* Deselect the current tile */
1479 if(cursor.x<10) {
1480 cursor.x++;
1481 } else {
1482 #ifdef IPOD_STYLE
1483 if(cursor.y<10)
1484 cursor.y++;
1485 else
1486 cursor.y = 1;
1487 #endif
1488 cursor.x = 1;
1490 update_score();
1491 draw_cursor();
1492 break;
1493 #endif
1494 #ifndef IPOD_STYLE
1495 case SUPERDOM_UP:
1496 case (SUPERDOM_UP|BUTTON_REPEAT):
1497 draw_cursor(); /* Deselect the current tile */
1498 if(cursor.y>1) {
1499 cursor.y--;
1500 } else {
1501 #if CONFIG_KEYPAD == IRIVER_H10_PAD
1502 if(cursor.x > 1)
1503 cursor.x--;
1504 else
1505 cursor.x = 10;
1506 #endif
1507 cursor.y = 10;
1509 update_score();
1510 draw_cursor();
1511 break;
1512 case SUPERDOM_DOWN:
1513 case (SUPERDOM_DOWN|BUTTON_REPEAT):
1514 draw_cursor(); /* Deselect the current tile */
1515 if(cursor.y<10) {
1516 cursor.y++;
1517 } else {
1518 #if CONFIG_KEYPAD == IRIVER_H10_PAD
1519 if(cursor.x < 10)
1520 cursor.x++;
1521 else
1522 cursor.x = 1;
1523 #endif
1524 cursor.y = 1;
1526 update_score();
1527 draw_cursor();
1528 break;
1529 #endif
1530 default:
1531 if (rb->default_event_handler(button) == SYS_USB_CONNECTED)
1533 return RET_VAL_USB;
1539 static int killmen(int colour) {
1540 bool human = (colour == COLOUR_LIGHT);
1541 int menkilled,i,j;
1542 int percent;
1543 if(human) {
1544 percent = (humanres.food*1000)/humanres.men;
1545 humanres.food = 0;
1546 } else {
1547 percent = (compres.food*1000)/compres.men;
1548 compres.food = 0;
1550 menkilled = 0;
1551 for(i=1;i<11;i++) {
1552 for(j=1;j<11;j++) {
1553 if(board[i][j].colour == colour) {
1554 int nummen = ((board[i][j].men * percent)/1000);
1555 menkilled += board[i][j].men - nummen;
1556 board[i][j].men = nummen;
1561 if(human)
1562 humanres.men -= menkilled;
1563 else
1564 compres.men -= menkilled;
1565 return menkilled;
1568 /* return -1 if error, 1 if attack is succeeded, 0 otherwise */
1569 static int attack_territory(int colour, int x, int y) {
1570 bool human = (colour == COLOUR_LIGHT);
1571 int str_diff;
1573 if(board[x][y].colour == colour) {
1574 if(human)
1575 rb->splash(HZ, "You can't attack your own territory");
1576 return -1;
1578 str_diff = calc_strength(COLOUR_DARK, x, y) -
1579 calc_strength(COLOUR_LIGHT, x, y);
1580 if(human) {
1581 str_diff = -str_diff;
1583 rb->srand(*rb->current_tick);
1584 if(str_diff > 0 || (str_diff == 0 && rb->rand()%2)) {
1585 struct resources *offres, *defres;
1586 if(human) {
1587 offres = &humanres;
1588 defres = &compres;
1589 } else {
1590 offres = &compres;
1591 defres = &humanres;
1593 defres->men -= board[x][y].men;
1594 defres->tanks -= board[x][y].tank;
1595 defres->planes -= board[x][y].plane;
1596 defres->nukes -= board[x][y].nuke;
1597 defres->farms -= board[x][y].farm;
1598 defres->inds -= board[x][y].ind;
1599 offres->farms += board[x][y].farm;
1600 offres->inds += board[x][y].ind;
1601 board[x][y].colour = colour;
1602 board[x][y].men = 0;
1603 board[x][y].tank = false;
1604 board[x][y].plane = false;
1605 board[x][y].nuke = false;
1606 draw_board();
1607 if(human)
1608 rb->sleep(HZ*2);
1609 else
1610 rb->sleep(HZ);
1611 return 1;
1612 } else {
1613 if(human)
1614 rb->splash(HZ, "Your troops were unable to overcome"
1615 " the enemy troops");
1616 else
1617 rb->splash(HZ*2, "The computer attempted to "
1618 "attack, but the invasion was"
1619 " pushed back");
1620 return 0;
1622 return 0;
1625 static int war_menu(void) {
1626 int selection = 0, temp;
1628 MENUITEM_STRINGLIST(menu, "War!", NULL,
1629 "Select territory to attack",
1630 "Finish turn", "Game menu");
1632 while(humanres.moves) {
1633 switch(rb->do_menu(&menu, &selection, NULL, false)) {
1634 case 0:
1635 switch(select_square()) {
1636 case RET_VAL_OK:
1637 if(attack_territory(COLOUR_LIGHT, cursor.x, cursor.y)
1638 >= 0)
1639 humanres.moves--;
1640 break;
1641 case RET_VAL_USB:
1642 return RET_VAL_USB;
1643 break;
1645 break;
1646 case 1:
1647 return RET_VAL_OK;
1648 break;
1649 case 2:
1650 if((temp = ingame_menu()) != RET_VAL_OK)
1651 return temp;
1652 break;
1655 return RET_VAL_OK;
1658 struct threat {
1659 int x;
1660 int y;
1661 int str_diff;
1664 static 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)) {
1667 return true;
1669 if(!buy_resources(COLOUR_DARK, type, x-1, y, 0)) {
1670 return true;
1672 if(!buy_resources(COLOUR_DARK, type, x+1, y, 0)) {
1673 return true;
1675 if(!buy_resources(COLOUR_DARK, type, x, y-1, 0)) {
1676 return true;
1678 if(!buy_resources(COLOUR_DARK, type, x, y+1, 0)) {
1679 return true;
1681 return false;
1684 static 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)))
1690 return 1;
1691 else
1692 return 0;
1695 static 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) {
1699 *adj_x = x-1;
1700 *adj_y = y;
1701 return;
1703 if(board[x+1][y].colour == COLOUR_DARK) {
1704 *adj_x = x+1;
1705 *adj_y = y;
1706 return;
1708 if(board[x][y-1].colour == COLOUR_DARK) {
1709 *adj_x = x;
1710 *adj_y = y-1;
1711 return;
1713 if(board[x][y+1].colour == COLOUR_DARK) {
1714 *adj_x = x;
1715 *adj_y = y+1;
1716 return;
1720 static 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 */
1724 int i, j, k;
1725 bool offensive = true;
1726 struct threat threats[4];
1727 int numthreats = 0;
1728 int total_str_diff = 0;
1729 int numterritory = 0;
1730 int str_diff;
1731 int men_needed;
1732 struct threat targets[2];
1733 int numtargets;
1734 struct cursor adj;
1736 compres.cash += compres.bank;
1737 compres.bank = 0;
1738 for(i=1;i<11;i++) {
1739 for(j=1;j<11;j++) {
1740 if(board[i][j].colour == COLOUR_DARK) {
1741 numterritory++;
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) {
1746 offensive = false;
1747 threats[numthreats].x = i;
1748 threats[numthreats].y = j;
1749 threats[numthreats].str_diff = str_diff;
1750 numthreats++;
1754 rb->yield();
1757 if(offensive) {
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 */
1763 numtargets = 2;
1764 } else {
1765 numtargets = 1;
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 */
1770 k = 0;
1771 for(i=1;i<11;i++) {
1772 for(j=1;j<11;j++) {
1773 if(has_adjacent(i,j) &&
1774 (board[i][j].ind || board[i][j].farm)) {
1775 if(k<numtargets) {
1776 targets[k].x = i;
1777 targets[k].y = j;
1778 targets[k].str_diff =
1779 calc_strength(COLOUR_LIGHT, i, j) -
1780 calc_strength(COLOUR_DARK, i, j);
1781 k++;
1784 rb->yield();
1787 if(k == 0) {
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);
1797 rb->yield();
1799 } else {
1800 for(i=0;i<k;i++) {
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,
1806 &adj.x, &adj.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,
1812 men_needed);
1813 break;
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);
1822 } else {
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,
1842 men_needed);
1844 } else {
1845 /* Tanks it is */
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
1853 * men */
1854 find_adjacent(threats[i].x, threats[i].y,
1855 &adj.x, &adj.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);
1862 break;
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;
1873 compres.cash = 0;
1876 static 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)) {
1881 adj->x = x+1;
1882 adj->y = y;
1883 return 1;
1885 if(board[x-1][y].colour == COLOUR_LIGHT &&
1886 calc_strength(COLOUR_LIGHT,x-1,y)<=calc_strength(COLOUR_DARK,x-1,y)) {
1887 adj->x = x-1;
1888 adj->y = y;
1889 return 1;
1891 if(board[x][y+1].colour == COLOUR_LIGHT &&
1892 calc_strength(COLOUR_LIGHT,x,y+1)<=calc_strength(COLOUR_DARK,x,y+1)) {
1893 adj->x = x;
1894 adj->y = y+1;
1895 return 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)) {
1899 adj->x = x;
1900 adj->y = y-1;
1901 return 1;
1903 return 0;
1906 static void computer_war(void) {
1907 /* Work out where to attack - prioritise the defence of buildings */
1908 int i, j;
1909 bool found_target = true;
1910 struct cursor adj;
1912 while(found_target) {
1913 found_target = false;
1914 for(i=1;i<11;i++) {
1915 for(j=1;j<11;j++) {
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) {
1921 compres.moves--;
1922 if(!compres.moves)
1923 return;
1926 rb->yield();
1930 /* Defence stage done, move on to OFFENCE */
1931 found_target = true;
1932 while(found_target) {
1933 found_target = false;
1934 for(i=1;i<11;i++) {
1935 for(j=1;j<11;j++) {
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) {
1942 compres.moves--;
1943 if(!compres.moves)
1944 return;
1947 rb->yield();
1951 /* Spend leftover moves wherever attacking randomly */
1952 found_target = true;
1953 while(found_target) {
1954 found_target = false;
1955 for(i=1;i<11;i++) {
1956 for(j=1;j<11;j++) {
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) {
1962 compres.moves--;
1963 if(!compres.moves)
1964 return;
1967 rb->yield();
1973 static int load_game(const char* file) {
1974 int fd;
1976 fd = rb->open(file, O_RDONLY);
1977 if(fd < 0) {
1978 DEBUGF("Couldn't open savegame\n");
1979 return -1;
1981 rb->read(fd, buf, 5);
1982 if(rb->strcmp(buf, "SSGv3")) {
1983 rb->splash(HZ, "Invalid/incompatible savegame");
1984 return -1;
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.humanstartinds, 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));
2015 rb->close(fd);
2016 return 0;
2019 static 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 static 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. */
2032 int i,j;
2033 int totalpower = 0;
2034 for(i=1;i<11;i++) {
2035 for(j=1;j<11;j++) {
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)
2046 #if LCD_DEPTH > 1
2047 rb->lcd_set_backdrop(NULL);
2048 rb->lcd_set_foreground(LCD_BLACK);
2049 rb->lcd_set_background(LCD_WHITE);
2050 #endif
2052 cursor.x = 1;
2053 cursor.y = 1;
2054 default_settings();
2055 if(parameter) {
2056 if(load_game(parameter) != 0) {
2057 DEBUGF("Loading failed, generating new game\n");
2058 } else {
2059 switch(gamestate) {
2060 case GS_PROD:
2061 goto startprod;
2062 break;
2063 case GS_MOVE:
2064 goto startmove;
2065 break;
2066 case GS_WAR:
2067 goto startwar;
2068 break;
2069 default:
2070 goto startyear;
2071 break;
2076 switch(start_menu()) {
2077 case RET_VAL_OK: /* start playing */
2078 break;
2079 case RET_VAL_QUIT_ERR: /* quit */
2080 return PLUGIN_OK;
2081 break;
2082 case RET_VAL_USB:
2083 return PLUGIN_USB_CONNECTED;
2084 break;
2087 init_resources();
2088 init_board();
2089 gen_resources();
2090 startyear:
2091 while(1) {
2092 int avg_str_diff = (average_strength(COLOUR_LIGHT) -
2093 average_strength(COLOUR_DARK));
2094 if(avg_str_diff > 15) {
2095 rb->splash(HZ*4, "The computer has surrendered. You win.");
2096 return PLUGIN_OK;
2098 if(-avg_str_diff > 15) {
2099 rb->splash(HZ*4, "Your army have suffered terrible morale from"
2100 " the bleak prospects of winning. You lose.");
2101 return PLUGIN_OK;
2104 /* production */
2105 startprod:
2106 gamestate = GS_PROD;
2107 switch(production_menu()) {
2108 case RET_VAL_USB:
2109 return PLUGIN_USB_CONNECTED;
2110 break;
2111 case RET_VAL_QUIT_ERR:
2112 return PLUGIN_OK;
2113 break;
2115 computer_allocate();
2117 /* movement */
2118 humanres.moves = superdom_settings.movesperturn;
2119 startmove:
2120 gamestate = GS_MOVE;
2121 switch(movement_menu()) {
2122 case RET_VAL_USB:
2123 return PLUGIN_USB_CONNECTED;
2124 break;
2125 case RET_VAL_QUIT_ERR:
2126 return PLUGIN_OK;
2127 break;
2129 /* feed men */
2130 if(humanres.men) {
2131 if(humanres.food > humanres.men) {
2132 rb->snprintf(buf, sizeof(buf), "Your men ate %d units of food",
2133 humanres.men);
2134 humanres.food -= humanres.men;
2135 } else {
2136 rb->snprintf(buf, sizeof(buf), "There was not enough food"
2137 " to feed all your men, %d men have died of starvation",
2138 killmen(COLOUR_LIGHT));
2140 rb->splash(HZ*2, buf);
2142 if(compres.men) {
2143 if(compres.food > compres.men) {
2144 compres.food -= compres.men;
2145 } else {
2146 rb->snprintf(buf, sizeof(buf), "The computer does not have"
2147 " enough food to feed its men. %d have died of starvation",
2148 killmen(COLOUR_DARK));
2149 rb->splash(HZ, buf);
2152 /* war */
2153 humanres.moves = superdom_settings.movesperturn;
2154 startwar:
2155 gamestate = GS_WAR;
2156 switch(war_menu()) {
2157 case RET_VAL_USB:
2158 return PLUGIN_USB_CONNECTED;
2159 break;
2160 case RET_VAL_QUIT_ERR:
2161 return PLUGIN_OK;
2162 break;
2164 compres.moves = superdom_settings.movesperturn;
2165 computer_war();
2166 gen_resources();
2168 return PLUGIN_OK;