We have a 3.9 release, update builds.pm
[maemo-rb.git] / apps / plugins / superdom.c
blob4c25ff28e635560941e4a25cc2f3b38a738e1e2e
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 #define SUPERDOM_OK BUTTON_SELECT
125 #define SUPERDOM_UP BUTTON_UP
126 #define SUPERDOM_DOWN BUTTON_DOWN
127 #define SUPERDOM_LEFT BUTTON_LEFT
128 #define SUPERDOM_RIGHT BUTTON_RIGHT
129 #define SUPERDOM_CANCEL BUTTON_BACK
131 #elif CONFIG_KEYPAD == COWON_D2_PAD
132 #define SUPERDOM_CANCEL BUTTON_POWER
134 #elif CONFIG_KEYPAD == CREATIVEZVM_PAD
135 #define SUPERDOM_OK BUTTON_SELECT
136 #define SUPERDOM_UP BUTTON_UP
137 #define SUPERDOM_DOWN BUTTON_DOWN
138 #define SUPERDOM_LEFT BUTTON_LEFT
139 #define SUPERDOM_RIGHT BUTTON_RIGHT
140 #define SUPERDOM_CANCEL BUTTON_BACK
142 #elif CONFIG_KEYPAD == PHILIPS_HDD6330_PAD
143 #define SUPERDOM_OK BUTTON_PLAY
144 #define SUPERDOM_UP BUTTON_UP
145 #define SUPERDOM_DOWN BUTTON_DOWN
146 #define SUPERDOM_LEFT BUTTON_PREV
147 #define SUPERDOM_RIGHT BUTTON_NEXT
148 #define SUPERDOM_CANCEL BUTTON_LEFT
150 #elif CONFIG_KEYPAD == PHILIPS_SA9200_PAD
151 #define SUPERDOM_OK BUTTON_PLAY
152 #define SUPERDOM_UP BUTTON_UP
153 #define SUPERDOM_DOWN BUTTON_DOWN
154 #define SUPERDOM_LEFT BUTTON_PREV
155 #define SUPERDOM_RIGHT BUTTON_NEXT
156 #define SUPERDOM_CANCEL BUTTON_LEFT
158 #elif (CONFIG_KEYPAD == ONDAVX747_PAD) || (CONFIG_KEYPAD == MROBE500_PAD)
159 #define SUPERDOM_CANCEL BUTTON_POWER
161 #elif CONFIG_KEYPAD == SAMSUNG_YH_PAD
162 #define SUPERDOM_OK BUTTON_PLAY
163 #define SUPERDOM_UP BUTTON_UP
164 #define SUPERDOM_DOWN BUTTON_DOWN
165 #define SUPERDOM_LEFT BUTTON_LEFT
166 #define SUPERDOM_RIGHT BUTTON_RIGHT
167 #define SUPERDOM_CANCEL BUTTON_REW
169 #elif CONFIG_KEYPAD == PBELL_VIBE500_PAD
170 #define SUPERDOM_OK BUTTON_OK
171 #define SUPERDOM_UP BUTTON_UP
172 #define SUPERDOM_DOWN BUTTON_DOWN
173 #define SUPERDOM_LEFT BUTTON_PREV
174 #define SUPERDOM_RIGHT BUTTON_NEXT
175 #define SUPERDOM_CANCEL BUTTON_CANCEL
177 #elif CONFIG_KEYPAD == MPIO_HD300_PAD
178 #define SUPERDOM_OK BUTTON_ENTER
179 #define SUPERDOM_UP BUTTON_UP
180 #define SUPERDOM_DOWN BUTTON_DOWN
181 #define SUPERDOM_LEFT BUTTON_REW
182 #define SUPERDOM_RIGHT BUTTON_FF
183 #define SUPERDOM_CANCEL BUTTON_MENU
185 #endif
187 #ifdef HAVE_TOUCHSCREEN
188 #ifndef SUPERDOM_OK
189 #define SUPERDOM_OK BUTTON_CENTER
190 #endif
191 #ifndef SUPERDOM_UP
192 #define SUPERDOM_UP BUTTON_TOPMIDDLE
193 #endif
194 #ifndef SUPERDOM_LEFT
195 #define SUPERDOM_LEFT BUTTON_MIDLEFT
196 #endif
197 #ifndef SUPERDOM_RIGHT
198 #define SUPERDOM_RIGHT BUTTON_MIDRIGHT
199 #endif
200 #ifndef SUPERDOM_DOWN
201 #define SUPERDOM_DOWN BUTTON_BOTTOMMIDDLE
202 #endif
203 #ifndef SUPERDOM_CANCEL
204 #define SUPERDOM_CANCEL BUTTON_TOPLEFT
205 #endif
206 #endif
208 enum {
209 RET_VAL_OK,
210 RET_VAL_USB,
211 RET_VAL_QUIT_ERR, /* quit or error */
214 void gen_interest(void);
215 void init_resources(void);
216 int select_square(void);
217 void update_score(void);
218 void gen_resources(void);
219 void draw_cursor(void);
220 void draw_board(void);
222 struct tile{
223 signed int colour; /* -1 = Unset */
224 bool tank;
225 bool plane;
226 bool nuke;
227 bool ind;
228 bool farm;
229 int men;
232 struct resources {
233 int cash;
234 int food;
235 int farms;
236 int inds;
237 int men;
238 int tanks;
239 int planes;
240 int nukes;
241 int bank;
242 int moves;
245 struct settings {
246 int compstartfarms;
247 int compstartinds;
248 int humanstartfarms;
249 int humanstartinds;
250 int startcash;
251 int startfood;
252 int movesperturn;
253 } superdom_settings;
255 struct resources humanres;
256 struct resources compres;
257 enum { GS_PROD, GS_MOVE, GS_WAR };
258 int gamestate;
260 struct cursor{
261 int x;
262 int y;
263 } cursor;
265 struct tile board[12][12];
267 void init_board(void) {
268 int i,j;
269 rb->srand(*rb->current_tick);
270 for(i=0;i<12;i++) { /* Hopefully about 50% each colour */
271 for(j=0;j<12;j++) {
272 if((i<1)||(j<1)||(i>10)||(j>10))
273 board[i][j].colour = -1; /* Unset */
274 else
275 board[i][j].colour = rb->rand()%2;
276 board[i][j].tank = false;
277 board[i][j].plane = false;
278 board[i][j].nuke = false;
279 board[i][j].ind = false;
280 board[i][j].farm = false;
281 board[i][j].men = 0;
285 while(compres.farms < superdom_settings.compstartfarms) {
286 i = rb->rand()%10 + 1;
287 j = rb->rand()%10 + 1;
288 if((board[i][j].colour == COLOUR_DARK) && (board[i][j].farm == false)) {
289 board[i][j].farm = true;
290 compres.farms++;
293 while(compres.inds < superdom_settings.compstartinds) {
294 i = rb->rand()%10 + 1;
295 j = rb->rand()%10 + 1;
296 if((board[i][j].colour == COLOUR_DARK) && (board[i][j].ind == false)) {
297 board[i][j].ind = true;
298 compres.inds++;
301 while(humanres.farms < superdom_settings.humanstartfarms) {
302 i = rb->rand()%10 + 1;
303 j = rb->rand()%10 + 1;
304 if((board[i][j].colour == COLOUR_LIGHT)&&(board[i][j].farm == false)) {
305 board[i][j].farm = true;
306 humanres.farms++;
309 while(humanres.inds < superdom_settings.humanstartinds) {
310 i = rb->rand()%10 + 1;
311 j = rb->rand()%10 + 1;
312 if((board[i][j].colour == COLOUR_LIGHT) && (board[i][j].ind == false)) {
313 board[i][j].ind = true;
314 humanres.inds++;
319 void draw_board(void) {
320 int i,j;
321 rb->lcd_clear_display();
322 for(i=1;i<11;i++) {
323 for(j=1;j<11;j++) {
324 if(board[i][j].colour == COLOUR_DARK) {
325 rb->lcd_set_foreground(LCD_DARKGRAY);
326 } else {
327 rb->lcd_set_foreground(LCD_LIGHTGRAY);
329 rb->lcd_fillrect(MARGIN+(BOX_WIDTH*(i-1)),
330 MARGIN+(BOX_HEIGHT*(j-1)), BOX_WIDTH,
331 BOX_HEIGHT);
332 #if LCD_DEPTH != 16
333 rb->lcd_set_drawmode(DRMODE_BG | DRMODE_INVERSEVID);
334 #endif
335 if(board[i][j].ind) {
336 MY_BITMAP_PART(superdom_boarditems,
337 board[i][j].colour?ICON_WIDTH:0, 0, ICON_STRIDE,
338 #if LCD_WIDTH > LCD_HEIGHT
339 MARGIN+(BOX_WIDTH*(i-1))+1,
340 MARGIN+(BOX_HEIGHT*(j-1))+ICON_HEIGHT+1,
341 #else
342 MARGIN+(BOX_WIDTH*(i-1))+1+ICON_WIDTH,
343 MARGIN+(BOX_HEIGHT*(j-1))+1,
344 #endif
345 ICON_WIDTH, ICON_HEIGHT);
347 if(board[i][j].farm) {
348 MY_BITMAP_PART(superdom_boarditems,
349 board[i][j].colour?ICON_WIDTH:0, ICON_HEIGHT,
350 ICON_STRIDE, MARGIN+(BOX_WIDTH*(i-1))+1,
351 MARGIN+(BOX_HEIGHT*(j-1))+1,
352 ICON_WIDTH, ICON_HEIGHT);
354 if(board[i][j].tank) {
355 MY_BITMAP_PART(superdom_boarditems,
356 board[i][j].colour?ICON_WIDTH:0, ICON_HEIGHT*2,
357 ICON_STRIDE, MARGIN+(BOX_WIDTH*(i-1))+ICON_WIDTH+1,
358 MARGIN+(BOX_HEIGHT*(j-1))+ICON_HEIGHT+1,
359 ICON_WIDTH, ICON_HEIGHT);
361 if(board[i][j].men) {
362 MY_BITMAP_PART(superdom_boarditems,
363 board[i][j].colour?ICON_WIDTH:0, ICON_HEIGHT*3,
364 #if LCD_WIDTH > LCD_HEIGHT
365 ICON_STRIDE, MARGIN+(BOX_WIDTH*(i-1))+ICON_WIDTH+1,
366 MARGIN+(BOX_HEIGHT*(j-1))+1,
367 #else
368 ICON_STRIDE, MARGIN+(BOX_WIDTH*(i-1))+1,
369 MARGIN+(BOX_HEIGHT*(j-1))+1+ICON_HEIGHT,
370 #endif
371 ICON_WIDTH, ICON_HEIGHT);
373 if(board[i][j].plane) {
374 MY_BITMAP_PART(superdom_boarditems,
375 board[i][j].colour?ICON_WIDTH:0, ICON_HEIGHT*4,
376 #if LCD_WIDTH > LCD_HEIGHT
377 ICON_STRIDE,MARGIN+(BOX_WIDTH*(i-1))+ICON_WIDTH*2+1,
378 MARGIN+(BOX_HEIGHT*(j-1))+ICON_HEIGHT+1,
379 #else
380 ICON_STRIDE,MARGIN+(BOX_WIDTH*(i-1))+ICON_WIDTH+1,
381 MARGIN+(BOX_HEIGHT*(j-1))+ICON_HEIGHT*2+1,
382 #endif
383 ICON_WIDTH, ICON_HEIGHT);
385 if(board[i][j].nuke) {
386 MY_BITMAP_PART(superdom_boarditems,
387 board[i][j].colour?ICON_WIDTH:0, ICON_HEIGHT*5,
388 #if LCD_WIDTH > LCD_HEIGHT
389 ICON_STRIDE,MARGIN+(BOX_WIDTH*(i-1))+ICON_WIDTH*2+1,
390 MARGIN+(BOX_HEIGHT*(j-1))+1,
391 #else
392 ICON_STRIDE,MARGIN+(BOX_WIDTH*(i-1))+1,
393 MARGIN+(BOX_HEIGHT*(j-1))+ICON_HEIGHT*2+1,
394 #endif
395 ICON_WIDTH, ICON_HEIGHT);
397 #if LCD_DEPTH != 16
398 rb->lcd_set_drawmode(DRMODE_SOLID);
399 #endif
402 rb->lcd_set_foreground(LCD_BLACK);
403 for(i=0;i<=10;i++) { /* Draw Horizontal lines */
404 rb->lcd_hline(MARGIN, MARGIN+(BOX_WIDTH*10), MARGIN+(BOX_HEIGHT*i));
406 for(i=0;i<=10;i++) { /* Draw Vertical lines */
407 rb->lcd_vline(MARGIN+(BOX_WIDTH*i), MARGIN, MARGIN+(BOX_HEIGHT*10));
409 rb->lcd_update();
412 int calc_strength(int colour, int x, int y) {
413 int a, b, score=0;
414 for (a = -1; a < 2; a++) {
415 for (b = -1; b < 2; b++) {
416 if ((b == 0 || a == 0) &&
417 (board[x + a][y + b].colour == colour)) {
418 score += 10;
419 if(board[x + a][y + b].tank || board[x + a][y + b].farm)
420 score += 30;
421 if(board[x + a][y + b].plane || board[x + a][y + b].ind)
422 score += 40;
423 if(board[x + a][y + b].nuke)
424 score += 20;
425 if(board[x + a][y + b].men)
426 score += (board[x + a][y + b].men*133/1000);
430 return score;
433 void gen_interest(void) {
434 /* Interest should be around 10% */
435 rb->srand(*rb->current_tick);
436 int interest = 7+rb->rand()%6;
437 humanres.bank = humanres.bank+(interest*humanres.bank/100);
438 compres.bank = compres.bank+(interest*compres.bank/100);
441 void draw_cursor(void) {
442 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
443 rb->lcd_fillrect(MARGIN+((cursor.x-1)*BOX_WIDTH),
444 MARGIN+((cursor.y-1)*BOX_HEIGHT), BOX_WIDTH+1, BOX_HEIGHT+1);
445 rb->lcd_set_drawmode(DRMODE_SOLID);
446 rb->lcd_update();
449 void gen_resources(void) {
450 int inccash = 0;
451 int incfood = 0;
452 int ratecash = 0;
453 int ratefood = 0;
454 int i;
455 gen_interest();
456 rb->srand(*rb->current_tick);
457 /* Generate Human's resources */
458 for(i=0;i<humanres.inds;i++) {
459 inccash += (300+rb->rand()%200);
461 for(i=0;i<humanres.farms;i++) {
462 incfood += (200+rb->rand()%200);
464 if(humanres.inds)
465 ratecash = inccash/humanres.inds;
466 if(humanres.farms)
467 ratefood = incfood/humanres.farms;
468 if(ratecash > 450) {
469 if(ratefood > 350) {
470 rb->splash(HZ*2, "Patriotism sweeps the land, all production"
471 " is up this year!");
472 } else {
473 rb->splash(HZ*2, "Factories working at maximum efficiency,"
474 " cash production up this year!");
476 } else if(ratecash > 350) {
477 if(ratefood > 350) {
478 rb->splash(HZ*2, "Record crop harvest this year!");
479 } else if(ratefood > 250) {
480 rb->splash(HZ*2, "Production continues as normal");
481 } else {
482 rb->splash(HZ*2, "Spoilage of crops leads to reduced farm"
483 " output this year");
485 } else {
486 if(ratefood > 350) {
487 rb->splash(HZ*2, "Record crop harvest this year!");
488 } else if(ratefood > 250) {
489 rb->splash(HZ*2, "Factory unions introduced. Industrial"
490 " production is down this year.");
491 } else {
492 rb->splash(HZ*2, "Internet created. All production is down"
493 " due to time wasted.");
496 humanres.cash += inccash;
497 humanres.food += incfood;
499 /* Generate Computer's resources */
500 inccash = 0;
501 incfood = 0;
502 for(i=0;i<compres.inds;i++) {
503 inccash += (300+rb->rand()%200);
505 for(i=0;i<compres.farms;i++) {
506 incfood += (200+rb->rand()%200);
508 compres.cash += inccash;
509 compres.food += incfood;
512 void update_score(void) {
513 int strength;
514 rb->lcd_setfont(FONT_SYSFIXED);
515 rb->lcd_set_drawmode(DRMODE_BG|DRMODE_INVERSEVID);
516 rb->lcd_fillrect(5,LCD_HEIGHT-20,105,20);
517 rb->lcd_set_drawmode(DRMODE_SOLID);
518 strength = calc_strength(COLOUR_LIGHT, cursor.x, cursor.y);
519 rb->lcd_putsxyf(5,LCD_HEIGHT-20,"Your power: %d.%d",strength/10,strength%10);
520 strength = calc_strength(COLOUR_DARK, cursor.x, cursor.y);
521 rb->lcd_putsxyf(5,LCD_HEIGHT-10,"Comp power: %d.%d",strength/10,strength%10);
522 rb->lcd_setfont(FONT_UI);
525 int settings_menu(void) {
526 int selection = 0;
528 MENUITEM_STRINGLIST(menu, "Super Domination Settings", NULL,
529 "Computer starting farms", "Computer starting factories",
530 "Human starting farms", "Human starting factories",
531 "Starting cash", "Starting food", "Moves per turn");
533 while(1) {
534 switch(rb->do_menu(&menu, &selection, NULL, false)) {
535 case 0:
536 rb->set_int("Computer starting farms", "", UNIT_INT,
537 &superdom_settings.compstartfarms, NULL,
538 1, 0, 5, NULL);
539 break;
540 case 1:
541 rb->set_int("Computer starting factories", "", UNIT_INT,
542 &superdom_settings.compstartinds, NULL,
543 1, 0, 5, NULL);
544 break;
545 case 2:
546 rb->set_int("Human starting farms", "", UNIT_INT,
547 &superdom_settings.humanstartfarms, NULL,
548 1, 0, 5, NULL);
549 break;
550 case 3:
551 rb->set_int("Human starting factories", "", UNIT_INT,
552 &superdom_settings.humanstartinds, NULL,
553 1, 0, 5, NULL);
554 break;
555 case 4:
556 rb->set_int("Starting cash", "", UNIT_INT,
557 &superdom_settings.startcash, NULL,
558 250, 0, 5000, NULL);
559 break;
560 case 5:
561 rb->set_int("Starting food", "", UNIT_INT,
562 &superdom_settings.startfood, NULL,
563 250, 0, 5000, NULL);
564 break;
565 case 6:
566 rb->set_int("Moves per turn", "", UNIT_INT,
567 &superdom_settings.movesperturn, NULL,
568 1, 1, 5, NULL);
569 break;
570 case MENU_ATTACHED_USB:
571 return RET_VAL_USB;
572 break;
573 case GO_TO_PREVIOUS:
574 return RET_VAL_OK;
575 break;
578 return RET_VAL_OK;
581 static int superdom_help(void) {
582 static char* help_text[] = {
583 "Super", "domination", "is", "a", "turn", "based", "strategy", "game,",
584 "where", "the", "aim", "is", "to", "overpower", "the", "computer",
585 "player", "by", "taking", "their", "territory.", "",
586 "Each", "year", "you", "are", "allocated", "an", "amount", "of", "cash",
587 "and", "food,", "depending", "on", "how", "many", "farms", "and",
588 "factories", "you", "control.", "",
589 "Use", "this", "cash", "and", "food", "to", "buy", "and", "feed", "your",
590 "army.", "Each", "tile", "has", "a", "strength,", "calculated", "by",
591 "the", "ownership", "of", "adjacent", "tiles,", "and", "the", "type",
592 "and", "number", "of", "troops", "on", "them.",
595 if (display_text(ARRAYLEN(help_text), help_text, NULL, NULL, true))
596 return RET_VAL_USB;
597 return RET_VAL_OK;
600 int start_menu(void) {
601 int selection = 0;
603 MENUITEM_STRINGLIST(menu, "Super Domination Menu", NULL,
604 "Play Super Domination", "Settings",
605 "Help", "Playback Control", "Quit");
607 while(1) {
608 switch(rb->do_menu(&menu, &selection, NULL, false)) {
609 case 0:
610 return RET_VAL_OK; /* start playing */
611 break;
612 case 1:
613 if(settings_menu()==RET_VAL_USB)
614 return RET_VAL_USB;
615 break;
616 case 2:
617 if(superdom_help()==RET_VAL_USB)
618 return RET_VAL_USB;
619 break;
620 case 3:
621 if(playback_control(NULL))
622 return RET_VAL_USB;
623 break;
624 case 4:
625 return RET_VAL_QUIT_ERR;
626 break;
629 return RET_VAL_QUIT_ERR;
632 int save_game(void) {
633 int fd;
634 char savepath[MAX_PATH];
636 rb->snprintf(savepath, sizeof(savepath), "/Savegame.ssg");
637 if(rb->kbd_input(savepath, MAX_PATH)) {
638 DEBUGF("Keyboard input failed\n");
639 return -1;
642 fd = rb->open(savepath, O_WRONLY|O_CREAT, 0666);
643 DEBUGF("savepath: %s\n", savepath);
644 if(fd < 0) {
645 DEBUGF("Couldn't create/open file\n");
646 return -1;
649 rb->write(fd, "SSGv3", 5);
650 rb->write(fd, &gamestate, sizeof(gamestate));
651 rb->write(fd, &humanres.cash, sizeof(humanres.cash));
652 rb->write(fd, &humanres.food, sizeof(humanres.food));
653 rb->write(fd, &humanres.bank, sizeof(humanres.bank));
654 rb->write(fd, &humanres.planes, sizeof(humanres.planes));
655 rb->write(fd, &humanres.tanks, sizeof(humanres.tanks));
656 rb->write(fd, &humanres.men, sizeof(humanres.men));
657 rb->write(fd, &humanres.nukes, sizeof(humanres.nukes));
658 rb->write(fd, &humanres.inds, sizeof(humanres.inds));
659 rb->write(fd, &humanres.farms, sizeof(humanres.farms));
660 rb->write(fd, &humanres.moves, sizeof(humanres.moves));
661 rb->write(fd, &compres.cash, sizeof(compres.cash));
662 rb->write(fd, &compres.food, sizeof(compres.food));
663 rb->write(fd, &compres.bank, sizeof(compres.bank));
664 rb->write(fd, &compres.planes, sizeof(compres.planes));
665 rb->write(fd, &compres.tanks, sizeof(compres.tanks));
666 rb->write(fd, &compres.men, sizeof(compres.men));
667 rb->write(fd, &compres.nukes, sizeof(compres.nukes));
668 rb->write(fd, &compres.inds, sizeof(compres.inds));
669 rb->write(fd, &compres.farms, sizeof(compres.farms));
670 rb->write(fd, &compres.moves, sizeof(compres.moves));
671 rb->write(fd, board, sizeof(board));
672 rb->write(fd, &superdom_settings.compstartfarms, sizeof(int));
673 rb->write(fd, &superdom_settings.compstartinds, sizeof(int));
674 rb->write(fd, &superdom_settings.humanstartfarms, sizeof(int));
675 rb->write(fd, &superdom_settings.humanstartinds, sizeof(int));
676 rb->write(fd, &superdom_settings.startcash, sizeof(int));
677 rb->write(fd, &superdom_settings.startfood, sizeof(int));
678 rb->write(fd, &superdom_settings.movesperturn, sizeof(int));
679 rb->close(fd);
680 return 0;
683 int ingame_menu(void) {
684 MENUITEM_STRINGLIST(menu, "Super Domination Menu", NULL,
685 "Return to game", "Save Game",
686 "Playback Control", "Quit");
688 switch(rb->do_menu(&menu, NULL, NULL, false)) {
689 case 0:
690 return RET_VAL_OK;
691 break;
692 case 1:
693 if(!save_game())
694 rb->splash(HZ, "Game saved");
695 else
696 rb->splash(HZ, "Error in save");
697 break;
698 case 2:
699 if(playback_control(NULL))
700 return RET_VAL_USB;
701 break;
702 case 3:
703 return RET_VAL_QUIT_ERR;
704 break;
705 case MENU_ATTACHED_USB:
706 return RET_VAL_USB;
707 break;
708 case GO_TO_PREVIOUS:
709 return RET_VAL_OK;
710 break;
712 return RET_VAL_OK;
715 int get_number(char* param, int* value, int max) {
716 static const char *button_labels[4][3] = {
717 { "1", "2", "3" },
718 { "4", "5", "6" },
719 { "7", "8", "9" },
720 { "CLR", "0", "OK" }
722 int i,j,x=0,y=0;
723 int height, width;
724 int button = 0, ret = RET_VAL_OK;
725 bool done = false;
726 rb->lcd_clear_display();
727 rb->lcd_getstringsize("CLR", &width, &height);
728 if(width > NUM_BOX_WIDTH || height > NUM_BOX_HEIGHT)
729 rb->lcd_setfont(FONT_SYSFIXED);
730 /* Draw a 3x4 grid */
731 for(i=0;i<=3;i++) { /* Vertical lines */
732 rb->lcd_vline(NUM_MARGIN_X+(NUM_BOX_WIDTH*i), NUM_MARGIN_Y,
733 NUM_MARGIN_Y+(4*NUM_BOX_HEIGHT));
735 for(i=0;i<=4;i++) { /* Horizontal lines */
736 rb->lcd_hline(NUM_MARGIN_X, NUM_MARGIN_X+(3*NUM_BOX_WIDTH),
737 NUM_MARGIN_Y+(NUM_BOX_HEIGHT*i));
739 for(i=0;i<4;i++) {
740 for(j=0;j<3;j++) {
741 rb->lcd_getstringsize(button_labels[i][j], &width, &height);
742 rb->lcd_putsxy(
743 NUM_MARGIN_X+(j*NUM_BOX_WIDTH)+NUM_BOX_WIDTH/2-width/2,
744 NUM_MARGIN_Y+(i*NUM_BOX_HEIGHT)+NUM_BOX_HEIGHT/2-height/2,
745 button_labels[i][j]);
748 rb->lcd_putsxyf(NUM_MARGIN_X+10, NUM_MARGIN_Y+4*NUM_BOX_HEIGHT+10,"%d",*value);
749 rb->lcd_getstringsize(param, &width, &height);
750 if(width < LCD_WIDTH)
751 rb->lcd_putsxy((LCD_WIDTH-width)/2, (NUM_MARGIN_Y-height)/2, param);
752 else
753 rb->lcd_puts_scroll(0, (NUM_MARGIN_Y/height-1)/2, param);
754 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
755 rb->lcd_fillrect(NUM_MARGIN_X+(NUM_BOX_WIDTH*x),
756 NUM_MARGIN_Y+(NUM_BOX_HEIGHT*y),
757 NUM_BOX_WIDTH+1, NUM_BOX_HEIGHT+1);
758 rb->lcd_set_drawmode(DRMODE_SOLID);
759 rb->lcd_update();
760 while(!done) {
761 button = rb->button_get(true);
762 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
763 rb->lcd_fillrect(NUM_MARGIN_X+(NUM_BOX_WIDTH*x),
764 NUM_MARGIN_Y+(NUM_BOX_HEIGHT*y),
765 NUM_BOX_WIDTH+1, NUM_BOX_HEIGHT+1);
766 rb->lcd_set_drawmode(DRMODE_SOLID);
767 switch(button) {
768 case SUPERDOM_OK:
769 if(y!=3) {
770 *value *= 10;
771 *value += button_labels[y][x][0] - '0';
772 } else if(x==0) {
773 *value /= 10;
774 } else if(x==1) {
775 *value *= 10;
776 } else if(x==2) {
777 done = true;
778 break;
780 if ((unsigned) *value > (unsigned) max)
781 *value = max;
782 rb->lcd_set_drawmode(DRMODE_BG|DRMODE_INVERSEVID);
783 rb->lcd_fillrect(0, NUM_MARGIN_Y+4*NUM_BOX_HEIGHT+10,
784 LCD_WIDTH, 30);
785 rb->lcd_set_drawmode(DRMODE_SOLID);
786 rb->lcd_putsxyf(NUM_MARGIN_X+10,NUM_MARGIN_Y+4*NUM_BOX_HEIGHT+10,
787 "%d", *value);
788 break;
789 case SUPERDOM_CANCEL:
790 *value = 0;
791 done = true;
792 ret = RET_VAL_QUIT_ERR;
793 break;
794 #if CONFIG_KEYPAD != IRIVER_H10_PAD
795 case SUPERDOM_LEFT:
796 if(x==0) {
797 #ifdef IPOD_STYLE
798 if(y>0)
799 y--;
800 else
801 y=3;
802 #endif
803 x=2;
804 } else {
805 x--;
807 break;
808 case SUPERDOM_RIGHT:
809 if(x==2) {
810 #ifdef IPOD_STYLE
811 if(y==3)
812 y=0;
813 else
814 y++;
815 #endif
816 x=0;
817 } else {
818 x++;
820 break;
821 #endif
822 #ifndef IPOD_STYLE
823 case SUPERDOM_UP:
824 if(y==0) {
825 #if CONFIG_KEYPAD == IRIVER_H10_PAD
826 if(x > 0)
827 x--;
828 else
829 x=2;
830 #endif
831 y=3;
832 } else {
833 y--;
835 break;
836 case SUPERDOM_DOWN:
837 if(y==3) {
838 #if CONFIG_KEYPAD == IRIVER_H10_PAD
839 if(x < 2)
840 x++;
841 else
842 x=0;
843 #endif
844 y=0;
845 } else {
846 y++;
848 break;
849 #endif
850 default:
851 if (rb->default_event_handler(button) == SYS_USB_CONNECTED)
853 done = true;
854 ret = RET_VAL_USB;
856 break;
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 rb->lcd_update();
865 rb->lcd_setfont(FONT_UI);
866 rb->lcd_stop_scroll();
867 if (ret == RET_VAL_QUIT_ERR)
868 rb->splash(HZ, "Cancelled");
869 return ret;
872 bool tile_has_item(int type, int x, int y) {
873 switch(type) {
874 case 0:
875 return (board[x][y].men > 0);
876 break;
877 case 1:
878 return board[x][y].tank;
879 break;
880 case 2:
881 return board[x][y].plane;
882 break;
883 case 3:
884 return board[x][y].farm;
885 break;
886 case 4:
887 return board[x][y].ind;
888 break;
889 case 5:
890 return board[x][y].nuke;
891 break;
893 return false;
896 int buy_resources(int colour, int type, int x, int y, int nummen) {
897 const char *itemnames[][6] = {
899 "them",
900 "the tank",
901 "the plane",
902 "the farm",
903 "the industrial plant",
904 "the nuke",
905 }, {
906 "place men",
907 "place a tank",
908 "place a plane",
909 "build a farm",
910 "build an industrial plant",
911 "place a nuke",
912 }, {
913 NULL,
914 "a tank",
915 "a plane",
916 "a farm",
917 "an industrial plant",
918 "a nuke",
922 bool human = (colour == COLOUR_LIGHT);
923 int price = 0;
924 int temp;
925 struct resources *res;
927 if(human) {
928 res = &humanres;
929 } else {
930 res = &compres;
932 switch(type) {
933 case 0: /* men */
934 price = 1*nummen;
935 break;
936 case 1: /* tank */
937 price = 300;
938 break;
939 case 2: /* plane */
940 price = 600;
941 break;
942 case 3: /* Farm */
943 price = 1150;
944 break;
945 case 4: /* Factory */
946 price = 1300;
947 break;
948 case 5: /* nuke */
949 price = 2000;
950 break;
952 if(res->cash < price) {
953 if(human)
954 rb->splash(HZ, "Not enough money!");
955 return RET_VAL_QUIT_ERR;
957 if(human) {
958 rb->splashf(HZ, "Where do you want to place %s?", itemnames[0][type]);
959 if((temp = select_square()) != RET_VAL_OK)
960 return temp;
961 x = cursor.x;
962 y = cursor.y;
964 if(board[x][y].colour != colour) {
965 if(human)
966 rb->splashf(HZ, "Can't %s on enemy territory", itemnames[1][type]);
967 return RET_VAL_QUIT_ERR;
969 if(type != 0 && tile_has_item(type, x, y)) {
970 if(human)
971 rb->splashf(HZ, "There is already %s there", itemnames[2][type]);
972 return RET_VAL_QUIT_ERR;
974 switch(type) {
975 case 0:
976 board[x][y].men += nummen;
977 res->men += nummen;
978 break;
979 case 1:
980 board[x][y].tank = true;
981 res->tanks++;
982 break;
983 case 2:
984 board[x][y].plane = true;
985 res->planes++;
986 break;
987 case 3:
988 board[x][y].farm = true;
989 res->farms++;
990 break;
991 case 4:
992 board[x][y].ind = true;
993 res->inds++;
994 break;
995 case 5:
996 board[x][y].nuke = true;
997 res->nukes++;
998 break;
1000 res->cash -= price;
1002 draw_board();
1003 rb->sleep(HZ);
1005 return RET_VAL_OK;
1008 int buy_resources_menu(void) {
1009 int selection = 0,nummen;
1011 MENUITEM_STRINGLIST(menu, "Buy Resources", NULL,
1012 "Buy men ($1)", "Buy tank ($300)", "Buy plane ($600)",
1013 "Buy Farm ($1150)", "Buy Factory ($1300)",
1014 "Buy Nuke ($2000)",
1015 "Finish buying");
1017 while(1) {
1018 switch(rb->do_menu(&menu, &selection, NULL, false)) {
1019 case 0:
1020 nummen = 0;
1021 if(get_number("How many men would you like?", &nummen,
1022 humanres.cash) == RET_VAL_USB)
1023 return RET_VAL_USB;
1024 if(!nummen)
1025 break;
1026 /* fall through */
1027 case 1:
1028 case 2:
1029 case 3:
1030 case 4:
1031 case 5:
1032 if(buy_resources(COLOUR_LIGHT, selection, 0, 0, nummen)
1033 == RET_VAL_USB)
1034 return RET_VAL_USB;
1035 break;
1036 case 6:
1037 return RET_VAL_OK;
1038 break;
1039 case MENU_ATTACHED_USB:
1040 return RET_VAL_USB;
1041 break;
1042 case GO_TO_PREVIOUS:
1043 return RET_VAL_OK;
1044 break;
1047 return RET_VAL_OK;
1050 int move_unit(int colour, int type, int fromx, int fromy,
1051 int tox, int toy, int nummen) {
1052 const char *itemnames[][3] = {
1054 "troops",
1055 "the tank",
1056 "the plane",
1057 }, {
1058 "any troops",
1059 "a tank",
1060 "a plane",
1061 }, {
1062 "the troops",
1063 "the tank",
1064 "the plane",
1067 bool human = (colour == COLOUR_LIGHT);
1068 int temp;
1070 if(human) {
1071 rb->splashf(HZ, "Select where you want to move %s from",
1072 itemnames[0][type]);
1073 if((temp = select_square()) != RET_VAL_OK)
1074 return temp;
1075 fromx = cursor.x;
1076 fromy = cursor.y;
1078 if(board[fromx][fromy].colour != colour) {
1079 if(human)
1080 rb->splash(HZ, "That isn't your territory");
1081 return RET_VAL_QUIT_ERR;
1083 if(!tile_has_item(type, fromx, fromy)) {
1084 if(human)
1085 rb->splashf(HZ, "You don't have %s there", itemnames[1][type]);
1086 return RET_VAL_QUIT_ERR;
1088 if(type == 0) {
1089 if(human) {
1090 nummen = board[fromx][fromy].men;
1091 if((temp = get_number("How many men do you want to move?", &nummen,
1092 nummen)) != RET_VAL_OK)
1093 return temp;
1095 if(nummen > board[fromx][fromy].men) {
1096 if(human)
1097 rb->splash(HZ, "You don't have that many troops.");
1098 return RET_VAL_QUIT_ERR;
1101 if(human) {
1102 rb->splashf(HZ, "Select where you want to move %s to",
1103 itemnames[2][type]);
1104 if((temp = select_square()) != RET_VAL_OK)
1105 return temp;
1106 tox = cursor.x;
1107 toy = cursor.y;
1109 if((tox == fromx && toy == fromy) ||
1110 board[tox][toy].colour != colour ||
1111 (type != 2 && (abs(tox - fromx) > 1 || abs(toy - fromy) > 1))) {
1112 if(human)
1113 rb->splash(HZ, "Invalid move");
1114 return RET_VAL_QUIT_ERR;
1116 if(type != 0 && tile_has_item(type, tox, toy)) {
1117 if(human)
1118 rb->splashf(HZ, "There is already %s there", itemnames[1][type]);
1119 return RET_VAL_QUIT_ERR;
1121 switch(type) {
1122 case 0:
1123 board[fromx][fromy].men -= nummen;
1124 board[tox][toy].men += nummen;
1125 break;
1126 case 1:
1127 board[fromx][fromy].tank = false;
1128 board[tox][toy].tank = true;
1129 break;
1130 case 2:
1131 board[fromx][fromy].plane = false;
1132 board[tox][toy].plane = true;
1133 break;
1135 return RET_VAL_OK;
1138 int move_unit_menu(void) {
1139 int selection = 0;
1141 MENUITEM_STRINGLIST(menu, "Move unit", NULL,
1142 "Move men", "Move tank", "Move plane");
1143 switch(rb->do_menu(&menu, &selection, NULL, false)) {
1144 case 0:
1145 case 1:
1146 case 2:
1147 switch(move_unit(COLOUR_LIGHT, selection, 0, 0, 0, 0, 0)) {
1148 case RET_VAL_OK:
1149 humanres.moves--;
1150 break;
1151 case RET_VAL_USB:
1152 return RET_VAL_USB;
1153 break;
1155 break;
1156 case MENU_ATTACHED_USB:
1157 return RET_VAL_USB;
1159 return RET_VAL_OK;
1162 int launch_nuke(int colour, int nukex, int nukey, int targetx, int targety) {
1163 bool human = (colour == COLOUR_LIGHT);
1164 int temp;
1165 struct resources *res;
1167 if(board[nukex][nukey].colour != colour) {
1168 if(human)
1169 rb->splash(HZ, "That isn't your territory");
1170 return RET_VAL_QUIT_ERR;
1172 if(! board[nukex][nukey].nuke) {
1173 if(human)
1174 rb->splashf(HZ, "You don't have %s there", "a nuke");
1175 return RET_VAL_QUIT_ERR;
1177 if(human) {
1178 rb->splash(HZ, "Select place to target with nuke");
1179 if((temp = select_square()) != RET_VAL_OK)
1180 return temp;
1181 targetx = cursor.x;
1182 targety = cursor.y;
1184 if(human) {
1185 humanres.nukes--;
1186 } else {
1187 compres.nukes--;
1189 board[nukex][nukey].nuke = false;
1191 if(board[targetx][targety].colour == COLOUR_LIGHT) {
1192 res = &humanres;
1193 } else {
1194 res = &compres;
1196 res->men -= board[targetx][targety].men;
1197 res->tanks -= board[targetx][targety].tank;
1198 res->planes -= board[targetx][targety].plane;
1199 res->nukes -= board[targetx][targety].nuke;
1200 res->farms -= board[targetx][targety].farm;
1201 res->inds -= board[targetx][targety].ind;
1202 board[targetx][targety].men = 0;
1203 board[targetx][targety].tank = false;
1204 board[targetx][targety].plane = false;
1205 board[targetx][targety].ind = false;
1206 board[targetx][targety].nuke = false;
1207 board[targetx][targety].farm = false;
1208 /* TODO: Fallout carried by wind */
1210 return RET_VAL_OK;
1213 int movement_menu(void) {
1214 int selection = 0, temp;
1216 MENUITEM_STRINGLIST(menu, "Movement", NULL,
1217 "Move unit", "Buy additional moves ($100)",
1218 "Launch nuclear missile", "Check map",
1219 "Finish moving", "Game menu");
1221 while(1) {
1222 switch(rb->do_menu(&menu, &selection, NULL, false)) {
1223 case 0:
1224 if(humanres.moves) {
1225 if(move_unit_menu()==RET_VAL_USB)
1226 return RET_VAL_USB;
1227 } else {
1228 rb->splash(HZ, "You have no more moves left."
1229 " You can buy more for $100 each.");
1231 break;
1232 case 1:
1233 if(humanres.cash > 100) {
1234 humanres.moves++;
1235 humanres.cash -= 100;
1236 rb->snprintf(buf, sizeof(buf), "You now have %d moves",
1237 humanres.moves);
1238 rb->splash(HZ, buf);
1240 break;
1241 case 2:
1242 if(humanres.nukes==0) {
1243 rb->splash(HZ, "You do not have any nukes to launch");
1244 } else {
1245 rb->splash(HZ, "Select place to launch nuke from");
1246 switch(select_square()) {
1247 case RET_VAL_OK:
1248 if(launch_nuke(COLOUR_LIGHT, cursor.x, cursor.y,
1249 0, 0) == RET_VAL_USB)
1250 return RET_VAL_USB;
1251 break;
1252 case RET_VAL_USB:
1253 return RET_VAL_USB;
1254 break;
1257 break;
1258 case 3:
1259 if(select_square() == RET_VAL_USB)
1260 return RET_VAL_USB;
1261 break;
1262 case 4:
1263 return RET_VAL_OK;
1264 break;
1265 case 5:
1266 if((temp = ingame_menu()) != RET_VAL_OK)
1267 return temp;
1268 break;
1269 case MENU_ATTACHED_USB:
1270 return RET_VAL_USB;
1271 break;
1274 return RET_VAL_OK;
1277 static const char* inventory_data(int selected_item, void * data,
1278 char * buffer, size_t buffer_len) {
1279 (void)data;
1280 switch(selected_item) {
1281 case 0:
1282 rb->snprintf(buffer,buffer_len,"Men: %d", humanres.men);
1283 break;
1284 case 1:
1285 rb->snprintf(buffer,buffer_len,"Tanks: %d", humanres.tanks);
1286 break;
1287 case 2:
1288 rb->snprintf(buffer,buffer_len,"Planes: %d", humanres.planes);
1289 break;
1290 case 3:
1291 rb->snprintf(buffer,buffer_len,"Factories: %d", humanres.inds);
1292 break;
1293 case 4:
1294 rb->snprintf(buffer,buffer_len,"Farms: %d", humanres.farms);
1295 break;
1296 case 5:
1297 rb->snprintf(buffer,buffer_len,"Nukes: %d", humanres.nukes);
1298 break;
1299 case 6:
1300 rb->snprintf(buffer,buffer_len,"Cash: %d", humanres.cash);
1301 break;
1302 case 7:
1303 rb->snprintf(buffer,buffer_len,"Food: %d", humanres.food);
1304 break;
1305 case 8:
1306 rb->snprintf(buffer,buffer_len,"Bank: %d", humanres.bank);
1307 break;
1308 default:
1309 return NULL;
1311 return buffer;
1314 int show_inventory(void) {
1315 struct simplelist_info info;
1316 rb->simplelist_info_init(&info, "Inventory", 9, NULL);
1317 info.hide_selection = true;
1318 info.get_name = inventory_data;
1319 if(rb->simplelist_show_list(&info)) {
1320 return RET_VAL_USB;
1321 } else {
1322 return RET_VAL_OK;
1326 int production_menu(void) {
1327 int selection = 0, temp;
1329 MENUITEM_STRINGLIST(menu, "Production", NULL,
1330 "Buy resources", "Show inventory", "Check map",
1331 "Invest money", "Withdraw money",
1332 "Finish turn", "Game menu");
1334 while(1) {
1335 switch(rb->do_menu(&menu, &selection, NULL, false)) {
1336 case 0:
1337 if(buy_resources_menu() == RET_VAL_USB)
1338 return RET_VAL_USB;
1339 break;
1340 case 1:
1341 if(show_inventory() == RET_VAL_USB)
1342 return RET_VAL_USB;
1343 break;
1344 case 2:
1345 if(select_square() == RET_VAL_USB)
1346 return RET_VAL_USB;
1347 break;
1348 case 3:
1349 temp = humanres.cash;
1350 if(get_number("How much do you want to invest?", &temp,
1351 humanres.cash) == RET_VAL_USB)
1352 return RET_VAL_USB;
1353 if(temp > humanres.cash) {
1354 rb->splash(HZ, "You don't have that much cash to invest");
1355 } else {
1356 humanres.cash -= temp;
1357 humanres.bank += temp;
1359 break;
1360 case 4:
1361 temp = humanres.bank;
1362 if(get_number("How much do you want to withdraw?", &temp,
1363 humanres.bank) == RET_VAL_USB)
1364 return RET_VAL_USB;
1365 if(temp > humanres.bank) {
1366 rb->splash(HZ, "You don't have that much cash to withdraw");
1367 } else {
1368 humanres.cash += temp;
1369 humanres.bank -= temp;
1371 break;
1372 case 5:
1373 return RET_VAL_OK;
1374 break;
1375 case 6:
1376 if((temp = ingame_menu()) != RET_VAL_OK)
1377 return temp;
1378 break;
1379 case MENU_ATTACHED_USB:
1380 return RET_VAL_USB;
1381 break;
1384 return RET_VAL_OK;
1387 void init_resources(void) {
1388 humanres.cash = superdom_settings.startcash;
1389 humanres.food = superdom_settings.startfood;
1390 humanres.tanks = 0;
1391 humanres.planes = 0;
1392 humanres.nukes = 0;
1393 humanres.inds = 0;
1394 humanres.farms = 0;
1395 humanres.men = 0;
1396 humanres.bank = 0;
1397 humanres.moves = 0;
1398 compres.cash = superdom_settings.startcash;
1399 compres.food = superdom_settings.startfood;
1400 compres.tanks = 0;
1401 compres.planes = 0;
1402 compres.nukes = 0;
1403 compres.inds = 0;
1404 compres.farms = 0;
1405 compres.men = 0;
1406 compres.bank = 0;
1407 compres.moves = 0;
1410 int select_square(void) {
1411 int button = 0;
1412 draw_board();
1413 draw_cursor();
1414 update_score();
1415 #if LCD_WIDTH >= 220
1416 rb->lcd_setfont(FONT_SYSFIXED);
1417 rb->lcd_putsxyf(125, LCD_HEIGHT-20,"Cash: %d", humanres.cash);
1418 rb->lcd_putsxyf(125, LCD_HEIGHT-10,"Food: %d", humanres.food);
1419 rb->lcd_setfont(FONT_UI);
1420 #endif
1421 rb->lcd_update();
1422 while(1) {
1423 button = rb->button_get(true);
1424 switch(button) {
1425 case SUPERDOM_CANCEL:
1426 rb->splash(HZ, "Cancelled");
1427 return RET_VAL_QUIT_ERR;
1428 break;
1429 case SUPERDOM_OK:
1430 return RET_VAL_OK;
1431 break;
1432 #if CONFIG_KEYPAD != IRIVER_H10_PAD
1433 case SUPERDOM_LEFT:
1434 case (SUPERDOM_LEFT|BUTTON_REPEAT):
1435 draw_cursor(); /* Deselect the current tile */
1436 if(cursor.x>1) {
1437 cursor.x--;
1438 } else {
1439 #ifdef IPOD_STYLE
1440 if(cursor.y>1)
1441 cursor.y--;
1442 else
1443 cursor.y = 10;
1444 #endif
1445 cursor.x = 10;
1447 update_score();
1448 draw_cursor();
1449 break;
1450 case SUPERDOM_RIGHT:
1451 case (SUPERDOM_RIGHT|BUTTON_REPEAT):
1452 draw_cursor(); /* Deselect the current tile */
1453 if(cursor.x<10) {
1454 cursor.x++;
1455 } else {
1456 #ifdef IPOD_STYLE
1457 if(cursor.y<10)
1458 cursor.y++;
1459 else
1460 cursor.y = 1;
1461 #endif
1462 cursor.x = 1;
1464 update_score();
1465 draw_cursor();
1466 break;
1467 #endif
1468 #ifndef IPOD_STYLE
1469 case SUPERDOM_UP:
1470 case (SUPERDOM_UP|BUTTON_REPEAT):
1471 draw_cursor(); /* Deselect the current tile */
1472 if(cursor.y>1) {
1473 cursor.y--;
1474 } else {
1475 #if CONFIG_KEYPAD == IRIVER_H10_PAD
1476 if(cursor.x > 1)
1477 cursor.x--;
1478 else
1479 cursor.x = 10;
1480 #endif
1481 cursor.y = 10;
1483 update_score();
1484 draw_cursor();
1485 break;
1486 case SUPERDOM_DOWN:
1487 case (SUPERDOM_DOWN|BUTTON_REPEAT):
1488 draw_cursor(); /* Deselect the current tile */
1489 if(cursor.y<10) {
1490 cursor.y++;
1491 } else {
1492 #if CONFIG_KEYPAD == IRIVER_H10_PAD
1493 if(cursor.x < 10)
1494 cursor.x++;
1495 else
1496 cursor.x = 1;
1497 #endif
1498 cursor.y = 1;
1500 update_score();
1501 draw_cursor();
1502 break;
1503 #endif
1504 default:
1505 if (rb->default_event_handler(button) == SYS_USB_CONNECTED)
1507 return RET_VAL_USB;
1513 int killmen(int colour) {
1514 bool human = (colour == COLOUR_LIGHT);
1515 int menkilled,i,j;
1516 int percent;
1517 if(human) {
1518 percent = (humanres.food*1000)/humanres.men;
1519 humanres.food = 0;
1520 } else {
1521 percent = (compres.food*1000)/compres.men;
1522 compres.food = 0;
1524 menkilled = 0;
1525 for(i=1;i<11;i++) {
1526 for(j=1;j<11;j++) {
1527 if(board[i][j].colour == colour) {
1528 int nummen = ((board[i][j].men * percent)/1000);
1529 menkilled += board[i][j].men - nummen;
1530 board[i][j].men = nummen;
1535 if(human)
1536 humanres.men -= menkilled;
1537 else
1538 compres.men -= menkilled;
1539 return menkilled;
1542 /* return -1 if error, 1 if attack is succeeded, 0 otherwise */
1543 int attack_territory(int colour, int x, int y) {
1544 bool human = (colour == COLOUR_LIGHT);
1545 int str_diff;
1547 if(board[x][y].colour == colour) {
1548 if(human)
1549 rb->splash(HZ, "You can't attack your own territory");
1550 return -1;
1552 str_diff = calc_strength(COLOUR_DARK, x, y) -
1553 calc_strength(COLOUR_LIGHT, x, y);
1554 if(human) {
1555 str_diff = -str_diff;
1557 rb->srand(*rb->current_tick);
1558 if(str_diff > 0 || (str_diff == 0 && rb->rand()%2)) {
1559 struct resources *offres, *defres;
1560 if(human) {
1561 offres = &humanres;
1562 defres = &compres;
1563 } else {
1564 offres = &compres;
1565 defres = &humanres;
1567 defres->men -= board[x][y].men;
1568 defres->tanks -= board[x][y].tank;
1569 defres->planes -= board[x][y].plane;
1570 defres->nukes -= board[x][y].nuke;
1571 defres->farms -= board[x][y].farm;
1572 defres->inds -= board[x][y].ind;
1573 offres->farms += board[x][y].farm;
1574 offres->inds += board[x][y].ind;
1575 board[x][y].colour = colour;
1576 board[x][y].men = 0;
1577 board[x][y].tank = false;
1578 board[x][y].plane = false;
1579 board[x][y].nuke = false;
1580 draw_board();
1581 if(human)
1582 rb->sleep(HZ*2);
1583 else
1584 rb->sleep(HZ);
1585 return 1;
1586 } else {
1587 if(human)
1588 rb->splash(HZ, "Your troops were unable to overcome"
1589 " the enemy troops");
1590 else
1591 rb->splash(HZ*2, "The computer attempted to "
1592 "attack, but the invasion was"
1593 " pushed back");
1594 return 0;
1596 return 0;
1599 int war_menu(void) {
1600 int selection = 0, temp;
1602 MENUITEM_STRINGLIST(menu, "War!", NULL,
1603 "Select territory to attack",
1604 "Finish turn", "Game menu");
1606 while(humanres.moves) {
1607 switch(rb->do_menu(&menu, &selection, NULL, false)) {
1608 case 0:
1609 switch(select_square()) {
1610 case RET_VAL_OK:
1611 if(attack_territory(COLOUR_LIGHT, cursor.x, cursor.y)
1612 >= 0)
1613 humanres.moves--;
1614 break;
1615 case RET_VAL_USB:
1616 return RET_VAL_USB;
1617 break;
1619 break;
1620 case 1:
1621 return RET_VAL_OK;
1622 break;
1623 case 2:
1624 if((temp = ingame_menu()) != RET_VAL_OK)
1625 return temp;
1626 break;
1629 return RET_VAL_OK;
1632 struct threat {
1633 int x;
1634 int y;
1635 int str_diff;
1638 bool place_adjacent(bool tank, int x, int y) {
1639 int type = (tank? 1: 2);
1640 if(!buy_resources(COLOUR_DARK, type, x, y, 0)) {
1641 return true;
1643 if(!buy_resources(COLOUR_DARK, type, x-1, y, 0)) {
1644 return true;
1646 if(!buy_resources(COLOUR_DARK, type, x+1, y, 0)) {
1647 return true;
1649 if(!buy_resources(COLOUR_DARK, type, x, y-1, 0)) {
1650 return true;
1652 if(!buy_resources(COLOUR_DARK, type, x, y+1, 0)) {
1653 return true;
1655 return false;
1658 bool has_adjacent(int x, int y) {
1659 if((board[x][y].colour == COLOUR_LIGHT) &&
1660 ((board[x-1][y].colour == COLOUR_DARK) ||
1661 (board[x+1][y].colour == COLOUR_DARK) ||
1662 (board[x][y+1].colour == COLOUR_DARK) ||
1663 (board[x][y-1].colour == COLOUR_DARK)))
1664 return 1;
1665 else
1666 return 0;
1669 void find_adjacent(int x, int y, int* adj_x, int* adj_y) {
1670 /* Finds adjacent squares, returning squares without tanks on them
1671 * in preference to those with them */
1672 if(board[x-1][y].colour == COLOUR_DARK) {
1673 *adj_x = x-1;
1674 *adj_y = y;
1675 return;
1677 if(board[x+1][y].colour == COLOUR_DARK) {
1678 *adj_x = x+1;
1679 *adj_y = y;
1680 return;
1682 if(board[x][y-1].colour == COLOUR_DARK) {
1683 *adj_x = x;
1684 *adj_y = y-1;
1685 return;
1687 if(board[x][y+1].colour == COLOUR_DARK) {
1688 *adj_x = x;
1689 *adj_y = y+1;
1690 return;
1694 void computer_allocate(void) {
1695 /* Firstly, decide whether to go offensive or defensive.
1696 * This is primarily decided by the human player posing a threat to either
1697 * the computer's farms or factories */
1698 int i, j, k;
1699 bool offensive = true;
1700 struct threat threats[4];
1701 int numthreats = 0;
1702 int total_str_diff = 0;
1703 int numterritory = 0;
1704 int str_diff;
1705 int men_needed;
1706 struct threat targets[2];
1707 int numtargets;
1708 struct cursor adj;
1710 compres.cash += compres.bank;
1711 compres.bank = 0;
1712 for(i=1;i<11;i++) {
1713 for(j=1;j<11;j++) {
1714 if(board[i][j].colour == COLOUR_DARK) {
1715 numterritory++;
1716 str_diff = calc_strength(COLOUR_LIGHT,i,j) -
1717 calc_strength(COLOUR_DARK,i,j);
1718 if(str_diff > 0 && (board[i][j].ind || board[i][j].farm)) {
1719 if(numthreats < 3) {
1720 offensive = false;
1721 threats[numthreats].x = i;
1722 threats[numthreats].y = j;
1723 threats[numthreats].str_diff = str_diff;
1724 numthreats++;
1728 rb->yield();
1731 if(offensive) {
1732 /* The AI is going to go straight for the throat here and attack
1733 * the player's farms and factories. The amount of cash
1734 * the AI has to spend will determine how many targets there are */
1735 if(compres.cash > 1200) {
1736 /* 1200 is a figure I pulled out of nowhere. Adjust as needed */
1737 numtargets = 2;
1738 } else {
1739 numtargets = 1;
1741 /* Work out which target(s) to attack. They must have adjacent squares
1742 * owned by the computer. If none are found just place troops in
1743 * random places around the map until we run out of money */
1744 k = 0;
1745 for(i=1;i<11;i++) {
1746 for(j=1;j<11;j++) {
1747 if(has_adjacent(i,j) &&
1748 (board[i][j].ind || board[i][j].farm)) {
1749 if(k<numtargets) {
1750 targets[k].x = i;
1751 targets[k].y = j;
1752 targets[k].str_diff =
1753 calc_strength(COLOUR_LIGHT, i, j) -
1754 calc_strength(COLOUR_DARK, i, j);
1755 k++;
1758 rb->yield();
1761 if(k == 0) {
1762 /* No targets found! Randomly pick squares and if they're owned
1763 * by the computer then stick a tank on it. */
1764 rb->srand(*rb->current_tick);
1765 while(compres.cash >= 300 && compres.tanks < numterritory) {
1766 i = rb->rand()%10 + 1;
1767 j = rb->rand()%10 + 1;
1768 if(board[i][j].colour == COLOUR_DARK) {
1769 buy_resources(COLOUR_DARK, 1, i, j, 0);
1771 rb->yield();
1773 } else {
1774 for(i=0;i<k;i++) {
1775 str_diff = targets[i].str_diff;
1776 while(str_diff + 20 > 0 && compres.cash > 0) {
1777 /* While we still need them keep placing men */
1778 if(!place_adjacent(true, targets[i].x, targets[i].y)) {
1779 find_adjacent(targets[i].x, targets[i].y,
1780 &adj.x, &adj.y);
1781 men_needed = (str_diff + 20)*1000/133;
1782 if(compres.cash < men_needed) {
1783 men_needed = compres.cash;
1785 buy_resources(COLOUR_DARK, 0, adj.x, adj.y,
1786 men_needed);
1787 break;
1789 str_diff = calc_strength(COLOUR_LIGHT,
1790 targets[i].x, targets[i].y) -
1791 calc_strength(COLOUR_DARK,
1792 targets[i].x, targets[i].y);
1796 } else {
1797 /* Work out what to place on each square to defend it.
1798 * Tanks are preferential because they do not require food,
1799 * but if the budget is tight then we fall back onto troops.
1800 * Conversely if cash is not an issue and there are already tanks in
1801 * place planes will be deployed. We would like a margin of at least
1802 * 20 points to be safe. */
1804 for(i=0;i<numthreats;i++) {
1805 total_str_diff += threats[i].str_diff;
1807 if((total_str_diff+20)*10 > compres.cash) {
1808 /* Not enough cash to accomodate all threats using tanks alone -
1809 * use men as a backup */
1810 for(i=0;i<numthreats;i++) {
1811 men_needed = ((threats[i].str_diff + 20)*1000)/133;
1812 if(compres.cash < men_needed) {
1813 men_needed = compres.cash;
1815 buy_resources(COLOUR_DARK, 0, threats[i].x, threats[i].y,
1816 men_needed);
1818 } else {
1819 /* Tanks it is */
1820 /* Enough money to pay their way by planes? */
1821 bool tank = ((total_str_diff+20)*15 >= compres.cash);
1822 for(i=0;i<numthreats;i++) {
1823 str_diff = threats[i].str_diff;
1824 while(str_diff + 20 > 0) {
1825 if(!place_adjacent(tank, threats[i].x, threats[i].y)) {
1826 /* No room for any more planes or tanks, revert to
1827 * men */
1828 find_adjacent(threats[i].x, threats[i].y,
1829 &adj.x, &adj.y);
1830 men_needed = (str_diff + 20)*1000/133;
1831 if(compres.cash < men_needed) {
1832 men_needed = compres.cash;
1834 buy_resources(COLOUR_DARK, 0, threats[i].x,
1835 threats[i].y, men_needed);
1836 break;
1838 str_diff = calc_strength(COLOUR_LIGHT,
1839 threats[i].x, threats[i].y) -
1840 calc_strength(COLOUR_DARK,
1841 threats[i].x, threats[i].y);
1846 compres.bank += compres.cash;
1847 compres.cash = 0;
1850 int find_adj_target(int x, int y, struct cursor* adj) {
1851 /* Find a square next to a computer's farm or factory owned by the player
1852 * that is vulnerable. Return 1 on success, 0 otherwise */
1853 if(board[x+1][y].colour == COLOUR_LIGHT &&
1854 calc_strength(COLOUR_LIGHT,x+1,y)<=calc_strength(COLOUR_DARK,x+1,y)) {
1855 adj->x = x+1;
1856 adj->y = y;
1857 return 1;
1859 if(board[x-1][y].colour == COLOUR_LIGHT &&
1860 calc_strength(COLOUR_LIGHT,x-1,y)<=calc_strength(COLOUR_DARK,x-1,y)) {
1861 adj->x = x-1;
1862 adj->y = y;
1863 return 1;
1865 if(board[x][y+1].colour == COLOUR_LIGHT &&
1866 calc_strength(COLOUR_LIGHT,x,y+1)<=calc_strength(COLOUR_DARK,x,y+1)) {
1867 adj->x = x;
1868 adj->y = y+1;
1869 return 1;
1871 if(board[x][y-1].colour == COLOUR_LIGHT &&
1872 calc_strength(COLOUR_LIGHT,x,y-1)<=calc_strength(COLOUR_DARK,x,y-1)) {
1873 adj->x = x;
1874 adj->y = y-1;
1875 return 1;
1877 return 0;
1880 void computer_war(void) {
1881 /* Work out where to attack - prioritise the defence of buildings */
1882 int i, j;
1883 bool found_target = true;
1884 struct cursor adj;
1886 while(found_target) {
1887 found_target = false;
1888 for(i=1;i<11;i++) {
1889 for(j=1;j<11;j++) {
1890 if((board[i][j].colour == COLOUR_DARK) &&
1891 (board[i][j].farm || board[i][j].ind) &&
1892 find_adj_target(i, j, &adj)) {
1893 found_target = true;
1894 if(attack_territory(COLOUR_DARK, adj.x, adj.y) >= 0) {
1895 compres.moves--;
1896 if(!compres.moves)
1897 return;
1900 rb->yield();
1904 /* Defence stage done, move on to OFFENCE */
1905 found_target = true;
1906 while(found_target) {
1907 found_target = false;
1908 for(i=1;i<11;i++) {
1909 for(j=1;j<11;j++) {
1910 if(board[i][j].colour == COLOUR_LIGHT &&
1911 (board[i][j].ind || board[i][j].farm) &&
1912 (calc_strength(COLOUR_DARK, i, j) >=
1913 calc_strength(COLOUR_LIGHT, i, j))) {
1914 found_target = true;
1915 if(attack_territory(COLOUR_DARK, i, j) >= 0) {
1916 compres.moves--;
1917 if(!compres.moves)
1918 return;
1921 rb->yield();
1925 /* Spend leftover moves wherever attacking randomly */
1926 found_target = true;
1927 while(found_target) {
1928 found_target = false;
1929 for(i=1;i<11;i++) {
1930 for(j=1;j<11;j++) {
1931 if(board[i][j].colour == COLOUR_LIGHT &&
1932 (calc_strength(COLOUR_DARK, i, j) >=
1933 calc_strength(COLOUR_LIGHT, i, j))) {
1934 found_target = true;
1935 if(attack_territory(COLOUR_DARK, i, j) >= 0) {
1936 compres.moves--;
1937 if(!compres.moves)
1938 return;
1941 rb->yield();
1947 static int load_game(const char* file) {
1948 int fd;
1950 fd = rb->open(file, O_RDONLY);
1951 if(fd < 0) {
1952 DEBUGF("Couldn't open savegame\n");
1953 return -1;
1955 rb->read(fd, buf, 5);
1956 if(rb->strcmp(buf, "SSGv3")) {
1957 rb->splash(HZ, "Invalid/incompatible savegame");
1958 return -1;
1960 rb->read(fd, &gamestate, sizeof(gamestate));
1961 rb->read(fd, &humanres.cash, sizeof(humanres.cash));
1962 rb->read(fd, &humanres.food, sizeof(humanres.food));
1963 rb->read(fd, &humanres.bank, sizeof(humanres.bank));
1964 rb->read(fd, &humanres.planes, sizeof(humanres.planes));
1965 rb->read(fd, &humanres.tanks, sizeof(humanres.tanks));
1966 rb->read(fd, &humanres.men, sizeof(humanres.men));
1967 rb->read(fd, &humanres.nukes, sizeof(humanres.nukes));
1968 rb->read(fd, &humanres.inds, sizeof(humanres.inds));
1969 rb->read(fd, &humanres.farms, sizeof(humanres.farms));
1970 rb->read(fd, &humanres.moves, sizeof(humanres.moves));
1971 rb->read(fd, &compres.cash, sizeof(humanres.cash));
1972 rb->read(fd, &compres.food, sizeof(humanres.food));
1973 rb->read(fd, &compres.bank, sizeof(humanres.bank));
1974 rb->read(fd, &compres.planes, sizeof(humanres.planes));
1975 rb->read(fd, &compres.tanks, sizeof(humanres.tanks));
1976 rb->read(fd, &compres.men, sizeof(humanres.men));
1977 rb->read(fd, &compres.nukes, sizeof(humanres.nukes));
1978 rb->read(fd, &compres.inds, sizeof(humanres.inds));
1979 rb->read(fd, &compres.farms, sizeof(humanres.farms));
1980 rb->read(fd, &compres.moves, sizeof(humanres.moves));
1981 rb->read(fd, board, sizeof(board));
1982 rb->read(fd, &superdom_settings.compstartfarms, sizeof(int));
1983 rb->read(fd, &superdom_settings.compstartinds, sizeof(int));
1984 rb->read(fd, &superdom_settings.humanstartfarms, sizeof(int));
1985 rb->read(fd, &superdom_settings.humanstartinds, sizeof(int));
1986 rb->read(fd, &superdom_settings.startcash, sizeof(int));
1987 rb->read(fd, &superdom_settings.startfood, sizeof(int));
1988 rb->read(fd, &superdom_settings.movesperturn, sizeof(int));
1989 rb->close(fd);
1990 return 0;
1993 void default_settings(void) {
1994 superdom_settings.compstartfarms = 1;
1995 superdom_settings.compstartinds = 1;
1996 superdom_settings.humanstartfarms = 2;
1997 superdom_settings.humanstartinds = 2;
1998 superdom_settings.startcash = 0;
1999 superdom_settings.startfood = 0;
2000 superdom_settings.movesperturn = 2;
2003 int average_strength(int colour) {
2004 /* This function calculates the average strength of the given player,
2005 * used to determine when the computer wins or loses. */
2006 int i,j;
2007 int totalpower = 0;
2008 for(i=1;i<11;i++) {
2009 for(j=1;j<11;j++) {
2010 if(board[i][j].colour != -1) {
2011 totalpower += calc_strength(colour, i, j);
2015 return totalpower/100;
2018 enum plugin_status plugin_start(const void* parameter)
2020 #if LCD_DEPTH > 1
2021 rb->lcd_set_backdrop(NULL);
2022 rb->lcd_set_foreground(LCD_BLACK);
2023 rb->lcd_set_background(LCD_WHITE);
2024 #endif
2026 cursor.x = 1;
2027 cursor.y = 1;
2028 default_settings();
2029 if(parameter) {
2030 if(load_game(parameter) != 0) {
2031 DEBUGF("Loading failed, generating new game\n");
2032 } else {
2033 switch(gamestate) {
2034 case GS_PROD:
2035 goto startprod;
2036 break;
2037 case GS_MOVE:
2038 goto startmove;
2039 break;
2040 case GS_WAR:
2041 goto startwar;
2042 break;
2043 default:
2044 goto startyear;
2045 break;
2050 switch(start_menu()) {
2051 case RET_VAL_OK: /* start playing */
2052 break;
2053 case RET_VAL_QUIT_ERR: /* quit */
2054 return PLUGIN_OK;
2055 break;
2056 case RET_VAL_USB:
2057 return PLUGIN_USB_CONNECTED;
2058 break;
2061 init_resources();
2062 init_board();
2063 gen_resources();
2064 startyear:
2065 while(1) {
2066 int avg_str_diff = (average_strength(COLOUR_LIGHT) -
2067 average_strength(COLOUR_DARK));
2068 if(avg_str_diff > 15) {
2069 rb->splash(HZ*4, "The computer has surrendered. You win.");
2070 return PLUGIN_OK;
2072 if(-avg_str_diff > 15) {
2073 rb->splash(HZ*4, "Your army have suffered terrible morale from"
2074 " the bleak prospects of winning. You lose.");
2075 return PLUGIN_OK;
2078 /* production */
2079 startprod:
2080 gamestate = GS_PROD;
2081 switch(production_menu()) {
2082 case RET_VAL_USB:
2083 return PLUGIN_USB_CONNECTED;
2084 break;
2085 case RET_VAL_QUIT_ERR:
2086 return PLUGIN_OK;
2087 break;
2089 computer_allocate();
2091 /* movement */
2092 humanres.moves = superdom_settings.movesperturn;
2093 startmove:
2094 gamestate = GS_MOVE;
2095 switch(movement_menu()) {
2096 case RET_VAL_USB:
2097 return PLUGIN_USB_CONNECTED;
2098 break;
2099 case RET_VAL_QUIT_ERR:
2100 return PLUGIN_OK;
2101 break;
2103 /* feed men */
2104 if(humanres.men) {
2105 if(humanres.food > humanres.men) {
2106 rb->snprintf(buf, sizeof(buf), "Your men ate %d units of food",
2107 humanres.men);
2108 humanres.food -= humanres.men;
2109 } else {
2110 rb->snprintf(buf, sizeof(buf), "There was not enough food"
2111 " to feed all your men, %d men have died of starvation",
2112 killmen(COLOUR_LIGHT));
2114 rb->splash(HZ*2, buf);
2116 if(compres.men) {
2117 if(compres.food > compres.men) {
2118 compres.food -= compres.men;
2119 } else {
2120 rb->snprintf(buf, sizeof(buf), "The computer does not have"
2121 " enough food to feed its men. %d have died of starvation",
2122 killmen(COLOUR_DARK));
2123 rb->splash(HZ, buf);
2126 /* war */
2127 humanres.moves = superdom_settings.movesperturn;
2128 startwar:
2129 gamestate = GS_WAR;
2130 switch(war_menu()) {
2131 case RET_VAL_USB:
2132 return PLUGIN_USB_CONNECTED;
2133 break;
2134 case RET_VAL_QUIT_ERR:
2135 return PLUGIN_OK;
2136 break;
2138 compres.moves = superdom_settings.movesperturn;
2139 computer_war();
2140 gen_resources();
2142 return PLUGIN_OK;