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