fix red.
[kugel-rb.git] / apps / plugins / superdom.c
blobc2a7d8f896298181d43fc7fdc82b5e1af923c3e8
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 };
242 int gamestate;
244 struct cursor{
245 int x;
246 int y;
247 } cursor;
249 struct tile board[12][12];
251 void init_board(void) {
252 int i,j;
253 rb->srand(*rb->current_tick);
254 for(i=0;i<12;i++) { /* Hopefully about 50% each colour */
255 for(j=0;j<12;j++) {
256 if((i<1)||(j<1)||(i>10)||(j>10))
257 board[i][j].colour = -1; /* Unset */
258 else
259 board[i][j].colour = rb->rand()%2;
260 board[i][j].tank = false;
261 board[i][j].plane = false;
262 board[i][j].nuke = false;
263 board[i][j].ind = false;
264 board[i][j].farm = false;
265 board[i][j].men = 0;
269 while(compres.farms < superdom_settings.compstartfarms) {
270 i = rb->rand()%10 + 1;
271 j = rb->rand()%10 + 1;
272 if((board[i][j].colour == COLOUR_DARK) && (board[i][j].farm == false)) {
273 board[i][j].farm = true;
274 compres.farms++;
277 while(compres.inds < superdom_settings.compstartinds) {
278 i = rb->rand()%10 + 1;
279 j = rb->rand()%10 + 1;
280 if((board[i][j].colour == COLOUR_DARK) && (board[i][j].ind == false)) {
281 board[i][j].ind = true;
282 compres.inds++;
285 while(humanres.farms < superdom_settings.humanstartfarms) {
286 i = rb->rand()%10 + 1;
287 j = rb->rand()%10 + 1;
288 if((board[i][j].colour == COLOUR_LIGHT)&&(board[i][j].farm == false)) {
289 board[i][j].farm = true;
290 humanres.farms++;
293 while(humanres.inds < superdom_settings.humanstartinds) {
294 i = rb->rand()%10 + 1;
295 j = rb->rand()%10 + 1;
296 if((board[i][j].colour == COLOUR_LIGHT) && (board[i][j].ind == false)) {
297 board[i][j].ind = true;
298 humanres.inds++;
303 void draw_board(void) {
304 int i,j;
305 rb->lcd_clear_display();
306 for(i=1;i<11;i++) {
307 for(j=1;j<11;j++) {
308 if(board[i][j].colour == COLOUR_DARK) {
309 rb->lcd_set_foreground(LCD_DARKGRAY);
310 } else {
311 rb->lcd_set_foreground(LCD_LIGHTGRAY);
313 rb->lcd_fillrect(MARGIN+(BOX_WIDTH*(i-1)),
314 MARGIN+(BOX_HEIGHT*(j-1)), BOX_WIDTH,
315 BOX_HEIGHT);
316 #if LCD_DEPTH != 16
317 rb->lcd_set_drawmode(DRMODE_BG | DRMODE_INVERSEVID);
318 #endif
319 if(board[i][j].ind) {
320 MY_BITMAP_PART(superdom_boarditems,
321 board[i][j].colour?ICON_WIDTH:0, 0, ICON_STRIDE,
322 #if LCD_WIDTH > LCD_HEIGHT
323 MARGIN+(BOX_WIDTH*(i-1))+1,
324 MARGIN+(BOX_HEIGHT*(j-1))+ICON_HEIGHT+1,
325 #else
326 MARGIN+(BOX_WIDTH*(i-1))+1+ICON_WIDTH,
327 MARGIN+(BOX_HEIGHT*(j-1))+1,
328 #endif
329 ICON_WIDTH, ICON_HEIGHT);
331 if(board[i][j].farm) {
332 MY_BITMAP_PART(superdom_boarditems,
333 board[i][j].colour?ICON_WIDTH:0, ICON_HEIGHT,
334 ICON_STRIDE, MARGIN+(BOX_WIDTH*(i-1))+1,
335 MARGIN+(BOX_HEIGHT*(j-1))+1,
336 ICON_WIDTH, ICON_HEIGHT);
338 if(board[i][j].tank) {
339 MY_BITMAP_PART(superdom_boarditems,
340 board[i][j].colour?ICON_WIDTH:0, ICON_HEIGHT*2,
341 ICON_STRIDE, MARGIN+(BOX_WIDTH*(i-1))+ICON_WIDTH+1,
342 MARGIN+(BOX_HEIGHT*(j-1))+ICON_HEIGHT+1,
343 ICON_WIDTH, ICON_HEIGHT);
345 if(board[i][j].men) {
346 MY_BITMAP_PART(superdom_boarditems,
347 board[i][j].colour?ICON_WIDTH:0, ICON_HEIGHT*3,
348 #if LCD_WIDTH > LCD_HEIGHT
349 ICON_STRIDE, MARGIN+(BOX_WIDTH*(i-1))+ICON_WIDTH+1,
350 MARGIN+(BOX_HEIGHT*(j-1))+1,
351 #else
352 ICON_STRIDE, MARGIN+(BOX_WIDTH*(i-1))+1,
353 MARGIN+(BOX_HEIGHT*(j-1))+1+ICON_HEIGHT,
354 #endif
355 ICON_WIDTH, ICON_HEIGHT);
357 if(board[i][j].plane) {
358 MY_BITMAP_PART(superdom_boarditems,
359 board[i][j].colour?ICON_WIDTH:0, ICON_HEIGHT*4,
360 #if LCD_WIDTH > LCD_HEIGHT
361 ICON_STRIDE,MARGIN+(BOX_WIDTH*(i-1))+ICON_WIDTH*2+1,
362 MARGIN+(BOX_HEIGHT*(j-1))+ICON_HEIGHT+1,
363 #else
364 ICON_STRIDE,MARGIN+(BOX_WIDTH*(i-1))+ICON_WIDTH+1,
365 MARGIN+(BOX_HEIGHT*(j-1))+ICON_HEIGHT*2+1,
366 #endif
367 ICON_WIDTH, ICON_HEIGHT);
369 if(board[i][j].nuke) {
370 MY_BITMAP_PART(superdom_boarditems,
371 board[i][j].colour?ICON_WIDTH:0, ICON_HEIGHT*5,
372 #if LCD_WIDTH > LCD_HEIGHT
373 ICON_STRIDE,MARGIN+(BOX_WIDTH*(i-1))+ICON_WIDTH*2+1,
374 MARGIN+(BOX_HEIGHT*(j-1))+1,
375 #else
376 ICON_STRIDE,MARGIN+(BOX_WIDTH*(i-1))+1,
377 MARGIN+(BOX_HEIGHT*(j-1))+ICON_HEIGHT*2+1,
378 #endif
379 ICON_WIDTH, ICON_HEIGHT);
381 #if LCD_DEPTH != 16
382 rb->lcd_set_drawmode(DRMODE_SOLID);
383 #endif
386 rb->lcd_set_foreground(LCD_BLACK);
387 for(i=0;i<=10;i++) { /* Draw Horizontal lines */
388 rb->lcd_hline(MARGIN, MARGIN+(BOX_WIDTH*10), MARGIN+(BOX_HEIGHT*i));
390 for(i=0;i<=10;i++) { /* Draw Vertical lines */
391 rb->lcd_vline(MARGIN+(BOX_WIDTH*i), MARGIN, MARGIN+(BOX_HEIGHT*10));
393 rb->lcd_update();
396 int calc_strength(int colour, int x, int y) {
397 int a, b, score=0;
398 for (a = -1; a < 2; a++) {
399 for (b = -1; b < 2; b++) {
400 if ((b == 0 || a == 0) &&
401 (board[x + a][y + b].colour == colour)) {
402 score += 10;
403 if(board[x + a][y + b].tank || board[x + a][y + b].farm)
404 score += 30;
405 if(board[x + a][y + b].plane || board[x + a][y + b].ind)
406 score += 40;
407 if(board[x + a][y + b].nuke)
408 score += 20;
409 if(board[x + a][y + b].men)
410 score += (board[x + a][y + b].men*133/1000);
414 return score;
417 void gen_interest(void) {
418 /* Interest should be around 10% */
419 rb->srand(*rb->current_tick);
420 int interest = 7+rb->rand()%6;
421 humanres.bank = humanres.bank+(interest*humanres.bank/100);
422 compres.bank = compres.bank+(interest*compres.bank/100);
425 void draw_cursor(void) {
426 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
427 rb->lcd_fillrect(MARGIN+((cursor.x-1)*BOX_WIDTH),
428 MARGIN+((cursor.y-1)*BOX_HEIGHT), BOX_WIDTH+1, BOX_HEIGHT+1);
429 rb->lcd_set_drawmode(DRMODE_SOLID);
430 rb->lcd_update();
433 void gen_resources(void) {
434 int inccash = 0;
435 int incfood = 0;
436 int ratecash = 0;
437 int ratefood = 0;
438 int i;
439 gen_interest();
440 rb->srand(*rb->current_tick);
441 /* Generate Human's resources */
442 for(i=0;i<humanres.inds;i++) {
443 inccash += (300+rb->rand()%200);
445 for(i=0;i<humanres.farms;i++) {
446 incfood += (200+rb->rand()%200);
448 if(humanres.inds)
449 ratecash = inccash/humanres.inds;
450 if(humanres.farms)
451 ratefood = incfood/humanres.farms;
452 if(ratecash > 450) {
453 if(ratefood > 350) {
454 rb->splash(HZ*2, "Patriotism sweeps the land, all production"
455 " is up this year!");
456 } else {
457 rb->splash(HZ*2, "Factories working at maximum efficiency,"
458 " cash production up this year!");
460 } else if(ratecash > 350) {
461 if(ratefood > 350) {
462 rb->splash(HZ*2, "Record crop harvest this year!");
463 } else if(ratefood > 250) {
464 rb->splash(HZ*2, "Production continues as normal");
465 } else {
466 rb->splash(HZ*2, "Spoilage of crops leads to reduced farm"
467 " output this year");
469 } else {
470 if(ratefood > 350) {
471 rb->splash(HZ*2, "Record crop harvest this year!");
472 } else if(ratefood > 250) {
473 rb->splash(HZ*2, "Factory unions introduced. Industrial"
474 " production is down this year.");
475 } else {
476 rb->splash(HZ*2, "Internet created. All production is down"
477 " due to time wasted.");
480 humanres.cash += inccash;
481 humanres.food += incfood;
483 /* Generate Computer's resources */
484 inccash = 0;
485 incfood = 0;
486 for(i=0;i<compres.inds;i++) {
487 inccash += (300+rb->rand()%200);
489 for(i=0;i<compres.farms;i++) {
490 incfood += (200+rb->rand()%200);
492 compres.cash += inccash;
493 compres.food += incfood;
496 void update_score(void) {
497 int strength;
498 rb->lcd_setfont(FONT_SYSFIXED);
499 rb->lcd_set_drawmode(DRMODE_BG|DRMODE_INVERSEVID);
500 rb->lcd_fillrect(5,LCD_HEIGHT-20,105,20);
501 rb->lcd_set_drawmode(DRMODE_SOLID);
502 strength = calc_strength(COLOUR_LIGHT, cursor.x, cursor.y);
503 rb->snprintf(buf, sizeof(buf), "Your power: %d.%d",
504 strength/10, strength%10);
505 rb->lcd_putsxy(5,LCD_HEIGHT-20, buf);
506 strength = calc_strength(COLOUR_DARK, cursor.x, cursor.y);
507 rb->snprintf(buf, sizeof(buf), "Comp power: %d.%d",
508 strength/10, strength%10);
509 rb->lcd_putsxy(5,LCD_HEIGHT-10, buf);
510 rb->lcd_setfont(FONT_UI);
513 int settings_menu(void) {
514 int selection = 0;
516 MENUITEM_STRINGLIST(menu, "Super Domination Settings", NULL,
517 "Computer starting farms", "Computer starting factories",
518 "Human starting farms", "Human starting factories",
519 "Starting cash", "Starting food", "Moves per turn");
521 while(1) {
522 switch(rb->do_menu(&menu, &selection, NULL, false)) {
523 case 0:
524 rb->set_int("Computer starting farms", "", UNIT_INT,
525 &superdom_settings.compstartfarms, NULL,
526 1, 0, 5, NULL);
527 break;
528 case 1:
529 rb->set_int("Computer starting factories", "", UNIT_INT,
530 &superdom_settings.compstartinds, NULL,
531 1, 0, 5, NULL);
532 break;
533 case 2:
534 rb->set_int("Human starting farms", "", UNIT_INT,
535 &superdom_settings.humanstartfarms, NULL,
536 1, 0, 5, NULL);
537 break;
538 case 3:
539 rb->set_int("Human starting factories", "", UNIT_INT,
540 &superdom_settings.humanstartinds, NULL,
541 1, 0, 5, NULL);
542 break;
543 case 4:
544 rb->set_int("Starting cash", "", UNIT_INT,
545 &superdom_settings.startcash, NULL,
546 250, 0, 5000, NULL);
547 break;
548 case 5:
549 rb->set_int("Starting food", "", UNIT_INT,
550 &superdom_settings.startfood, NULL,
551 250, 0, 5000, NULL);
552 break;
553 case 6:
554 rb->set_int("Moves per turn", "", UNIT_INT,
555 &superdom_settings.movesperturn, NULL,
556 1, 1, 5, NULL);
557 break;
558 case MENU_ATTACHED_USB:
559 return RET_VAL_USB;
560 break;
561 case GO_TO_PREVIOUS:
562 return RET_VAL_OK;
563 break;
566 return RET_VAL_OK;
569 static int superdom_help(void) {
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, true))
584 return RET_VAL_USB;
585 return RET_VAL_OK;
588 int start_menu(void) {
589 int selection = 0;
591 MENUITEM_STRINGLIST(menu, "Super Domination Menu", NULL,
592 "Play Super Domination", "Settings",
593 "Help", "Playback Control", "Quit");
595 while(1) {
596 switch(rb->do_menu(&menu, &selection, NULL, false)) {
597 case 0:
598 return RET_VAL_OK; /* start playing */
599 break;
600 case 1:
601 if(settings_menu()==RET_VAL_USB)
602 return RET_VAL_USB;
603 break;
604 case 2:
605 if(superdom_help()==RET_VAL_USB)
606 return RET_VAL_USB;
607 break;
608 case 3:
609 if(playback_control(NULL))
610 return RET_VAL_USB;
611 break;
612 case 4:
613 return RET_VAL_QUIT_ERR;
614 break;
617 return RET_VAL_QUIT_ERR;
620 int save_game(void) {
621 int fd;
622 char savepath[MAX_PATH];
624 rb->snprintf(savepath, sizeof(savepath), "/Savegame.ssg");
625 if(rb->kbd_input(savepath, MAX_PATH)) {
626 DEBUGF("Keyboard input failed\n");
627 return -1;
630 fd = rb->open(savepath, O_WRONLY|O_CREAT, 0666);
631 DEBUGF("savepath: %s\n", savepath);
632 if(fd < 0) {
633 DEBUGF("Couldn't create/open file\n");
634 return -1;
637 rb->write(fd, "SSGv3", 5);
638 rb->write(fd, &gamestate, sizeof(gamestate));
639 rb->write(fd, &humanres.cash, sizeof(humanres.cash));
640 rb->write(fd, &humanres.food, sizeof(humanres.food));
641 rb->write(fd, &humanres.bank, sizeof(humanres.bank));
642 rb->write(fd, &humanres.planes, sizeof(humanres.planes));
643 rb->write(fd, &humanres.tanks, sizeof(humanres.tanks));
644 rb->write(fd, &humanres.men, sizeof(humanres.men));
645 rb->write(fd, &humanres.nukes, sizeof(humanres.nukes));
646 rb->write(fd, &humanres.inds, sizeof(humanres.inds));
647 rb->write(fd, &humanres.farms, sizeof(humanres.farms));
648 rb->write(fd, &humanres.moves, sizeof(humanres.moves));
649 rb->write(fd, &compres.cash, sizeof(compres.cash));
650 rb->write(fd, &compres.food, sizeof(compres.food));
651 rb->write(fd, &compres.bank, sizeof(compres.bank));
652 rb->write(fd, &compres.planes, sizeof(compres.planes));
653 rb->write(fd, &compres.tanks, sizeof(compres.tanks));
654 rb->write(fd, &compres.men, sizeof(compres.men));
655 rb->write(fd, &compres.nukes, sizeof(compres.nukes));
656 rb->write(fd, &compres.inds, sizeof(compres.inds));
657 rb->write(fd, &compres.farms, sizeof(compres.farms));
658 rb->write(fd, &compres.moves, sizeof(compres.moves));
659 rb->write(fd, board, sizeof(board));
660 rb->write(fd, &superdom_settings.compstartfarms, sizeof(int));
661 rb->write(fd, &superdom_settings.compstartinds, sizeof(int));
662 rb->write(fd, &superdom_settings.humanstartfarms, sizeof(int));
663 rb->write(fd, &superdom_settings.humanstartinds, sizeof(int));
664 rb->write(fd, &superdom_settings.startcash, sizeof(int));
665 rb->write(fd, &superdom_settings.startfood, sizeof(int));
666 rb->write(fd, &superdom_settings.movesperturn, sizeof(int));
667 rb->close(fd);
668 return 0;
671 int ingame_menu(void) {
672 MENUITEM_STRINGLIST(menu, "Super Domination Menu", NULL,
673 "Return to game", "Save Game",
674 "Playback Control", "Quit");
676 switch(rb->do_menu(&menu, NULL, NULL, false)) {
677 case 0:
678 return RET_VAL_OK;
679 break;
680 case 1:
681 if(!save_game())
682 rb->splash(HZ, "Game saved");
683 else
684 rb->splash(HZ, "Error in save");
685 break;
686 case 2:
687 if(playback_control(NULL))
688 return RET_VAL_USB;
689 break;
690 case 3:
691 return RET_VAL_QUIT_ERR;
692 break;
693 case MENU_ATTACHED_USB:
694 return RET_VAL_USB;
695 break;
696 case GO_TO_PREVIOUS:
697 return RET_VAL_OK;
698 break;
700 return RET_VAL_OK;
703 int get_number(char* param, int* value, int max) {
704 static const char *button_labels[4][3] = {
705 { "1", "2", "3" },
706 { "4", "5", "6" },
707 { "7", "8", "9" },
708 { "CLR", "0", "OK" }
710 int i,j,x=0,y=0;
711 int height, width;
712 int button = 0, ret = RET_VAL_OK;
713 bool done = false;
714 rb->lcd_clear_display();
715 rb->lcd_getstringsize("CLR", &width, &height);
716 if(width > NUM_BOX_WIDTH || height > NUM_BOX_HEIGHT)
717 rb->lcd_setfont(FONT_SYSFIXED);
718 /* Draw a 3x4 grid */
719 for(i=0;i<=3;i++) { /* Vertical lines */
720 rb->lcd_vline(NUM_MARGIN_X+(NUM_BOX_WIDTH*i), NUM_MARGIN_Y,
721 NUM_MARGIN_Y+(4*NUM_BOX_HEIGHT));
723 for(i=0;i<=4;i++) { /* Horizontal lines */
724 rb->lcd_hline(NUM_MARGIN_X, NUM_MARGIN_X+(3*NUM_BOX_WIDTH),
725 NUM_MARGIN_Y+(NUM_BOX_HEIGHT*i));
727 for(i=0;i<4;i++) {
728 for(j=0;j<3;j++) {
729 rb->lcd_getstringsize(button_labels[i][j], &width, &height);
730 rb->lcd_putsxy(
731 NUM_MARGIN_X+(j*NUM_BOX_WIDTH)+NUM_BOX_WIDTH/2-width/2,
732 NUM_MARGIN_Y+(i*NUM_BOX_HEIGHT)+NUM_BOX_HEIGHT/2-height/2,
733 button_labels[i][j]);
736 rb->snprintf(buf,sizeof(buf), "%d", *value);
737 rb->lcd_putsxy(NUM_MARGIN_X+10, NUM_MARGIN_Y+4*NUM_BOX_HEIGHT+10, buf);
738 rb->lcd_getstringsize(param, &width, &height);
739 if(width < LCD_WIDTH)
740 rb->lcd_putsxy((LCD_WIDTH-width)/2, (NUM_MARGIN_Y-height)/2, param);
741 else
742 rb->lcd_puts_scroll(0, (NUM_MARGIN_Y/height-1)/2, param);
743 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
744 rb->lcd_fillrect(NUM_MARGIN_X+(NUM_BOX_WIDTH*x),
745 NUM_MARGIN_Y+(NUM_BOX_HEIGHT*y),
746 NUM_BOX_WIDTH+1, NUM_BOX_HEIGHT+1);
747 rb->lcd_set_drawmode(DRMODE_SOLID);
748 rb->lcd_update();
749 while(!done) {
750 button = rb->button_get(true);
751 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
752 rb->lcd_fillrect(NUM_MARGIN_X+(NUM_BOX_WIDTH*x),
753 NUM_MARGIN_Y+(NUM_BOX_HEIGHT*y),
754 NUM_BOX_WIDTH+1, NUM_BOX_HEIGHT+1);
755 rb->lcd_set_drawmode(DRMODE_SOLID);
756 switch(button) {
757 case SUPERDOM_OK:
758 if(y!=3) {
759 *value *= 10;
760 *value += button_labels[y][x][0] - '0';
761 } else if(x==0) {
762 *value /= 10;
763 } else if(x==1) {
764 *value *= 10;
765 } else if(x==2) {
766 done = true;
767 break;
769 if ((unsigned) *value > (unsigned) max)
770 *value = max;
771 rb->lcd_set_drawmode(DRMODE_BG|DRMODE_INVERSEVID);
772 rb->lcd_fillrect(0, NUM_MARGIN_Y+4*NUM_BOX_HEIGHT+10,
773 LCD_WIDTH, 30);
774 rb->lcd_set_drawmode(DRMODE_SOLID);
775 rb->snprintf(buf,sizeof(buf), "%d", *value);
776 rb->lcd_putsxy(NUM_MARGIN_X+10,
777 NUM_MARGIN_Y+4*NUM_BOX_HEIGHT+10, buf);
778 break;
779 case SUPERDOM_CANCEL:
780 *value = 0;
781 done = true;
782 ret = RET_VAL_QUIT_ERR;
783 break;
784 #if CONFIG_KEYPAD != IRIVER_H10_PAD
785 case SUPERDOM_LEFT:
786 if(x==0) {
787 #ifdef IPOD_STYLE
788 if(y>0)
789 y--;
790 else
791 y=3;
792 #endif
793 x=2;
794 } else {
795 x--;
797 break;
798 case SUPERDOM_RIGHT:
799 if(x==2) {
800 #ifdef IPOD_STYLE
801 if(y==3)
802 y=0;
803 else
804 y++;
805 #endif
806 x=0;
807 } else {
808 x++;
810 break;
811 #endif
812 #ifndef IPOD_STYLE
813 case SUPERDOM_UP:
814 if(y==0) {
815 #if CONFIG_KEYPAD == IRIVER_H10_PAD
816 if(x > 0)
817 x--;
818 else
819 x=2;
820 #endif
821 y=3;
822 } else {
823 y--;
825 break;
826 case SUPERDOM_DOWN:
827 if(y==3) {
828 #if CONFIG_KEYPAD == IRIVER_H10_PAD
829 if(x < 2)
830 x++;
831 else
832 x=0;
833 #endif
834 y=0;
835 } else {
836 y++;
838 break;
839 #endif
840 default:
841 if (rb->default_event_handler(button) == SYS_USB_CONNECTED)
843 done = true;
844 ret = RET_VAL_USB;
846 break;
848 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
849 rb->lcd_fillrect(NUM_MARGIN_X+(NUM_BOX_WIDTH*x),
850 NUM_MARGIN_Y+(NUM_BOX_HEIGHT*y),
851 NUM_BOX_WIDTH+1, NUM_BOX_HEIGHT+1);
852 rb->lcd_set_drawmode(DRMODE_SOLID);
853 rb->lcd_update();
855 rb->lcd_setfont(FONT_UI);
856 rb->lcd_stop_scroll();
857 if (ret == RET_VAL_QUIT_ERR)
858 rb->splash(HZ, "Cancelled");
859 return ret;
862 bool tile_has_item(int type, int x, int y) {
863 switch(type) {
864 case 0:
865 return (board[x][y].men > 0);
866 break;
867 case 1:
868 return board[x][y].tank;
869 break;
870 case 2:
871 return board[x][y].plane;
872 break;
873 case 3:
874 return board[x][y].farm;
875 break;
876 case 4:
877 return board[x][y].ind;
878 break;
879 case 5:
880 return board[x][y].nuke;
881 break;
883 return false;
886 int buy_resources(int colour, int type, int x, int y, int nummen) {
887 const char *itemnames[][6] = {
889 "them",
890 "the tank",
891 "the plane",
892 "the farm",
893 "the industrial plant",
894 "the nuke",
895 }, {
896 "place men",
897 "place a tank",
898 "place a plane",
899 "build a farm",
900 "build an industrial plant",
901 "place a nuke",
902 }, {
903 NULL,
904 "a tank",
905 "a plane",
906 "a farm",
907 "an industrial plant",
908 "a nuke",
912 bool human = (colour == COLOUR_LIGHT);
913 int price = 0;
914 int temp;
915 struct resources *res;
917 if(human) {
918 res = &humanres;
919 } else {
920 res = &compres;
922 switch(type) {
923 case 0: /* men */
924 price = 1*nummen;
925 break;
926 case 1: /* tank */
927 price = 300;
928 break;
929 case 2: /* plane */
930 price = 600;
931 break;
932 case 3: /* Farm */
933 price = 1150;
934 break;
935 case 4: /* Factory */
936 price = 1300;
937 break;
938 case 5: /* nuke */
939 price = 2000;
940 break;
942 if(res->cash < price) {
943 if(human)
944 rb->splash(HZ, "Not enough money!");
945 return RET_VAL_QUIT_ERR;
947 if(human) {
948 rb->splashf(HZ, "Where do you want to place %s?", itemnames[0][type]);
949 if((temp = select_square()) != RET_VAL_OK)
950 return temp;
951 x = cursor.x;
952 y = cursor.y;
954 if(board[x][y].colour != colour) {
955 if(human)
956 rb->splashf(HZ, "Can't %s on enemy territory", itemnames[1][type]);
957 return RET_VAL_QUIT_ERR;
959 if(type != 0 && tile_has_item(type, x, y)) {
960 if(human)
961 rb->splashf(HZ, "There is already %s there", itemnames[2][type]);
962 return RET_VAL_QUIT_ERR;
964 switch(type) {
965 case 0:
966 board[x][y].men += nummen;
967 res->men += nummen;
968 break;
969 case 1:
970 board[x][y].tank = true;
971 res->tanks++;
972 break;
973 case 2:
974 board[x][y].plane = true;
975 res->planes++;
976 break;
977 case 3:
978 board[x][y].farm = true;
979 res->farms++;
980 break;
981 case 4:
982 board[x][y].ind = true;
983 res->inds++;
984 break;
985 case 5:
986 board[x][y].nuke = true;
987 res->nukes++;
988 break;
990 res->cash -= price;
992 draw_board();
993 rb->sleep(HZ);
995 return RET_VAL_OK;
998 int buy_resources_menu(void) {
999 int selection = 0,nummen;
1001 MENUITEM_STRINGLIST(menu, "Buy Resources", NULL,
1002 "Buy men ($1)", "Buy tank ($300)", "Buy plane ($600)",
1003 "Buy Farm ($1150)", "Buy Factory ($1300)",
1004 "Buy Nuke ($2000)",
1005 "Finish buying");
1007 while(1) {
1008 switch(rb->do_menu(&menu, &selection, NULL, false)) {
1009 case 0:
1010 nummen = 0;
1011 if(get_number("How many men would you like?", &nummen,
1012 humanres.cash) == RET_VAL_USB)
1013 return RET_VAL_USB;
1014 if(!nummen)
1015 break;
1016 /* fall through */
1017 case 1:
1018 case 2:
1019 case 3:
1020 case 4:
1021 case 5:
1022 if(buy_resources(COLOUR_LIGHT, selection, 0, 0, nummen)
1023 == RET_VAL_USB)
1024 return RET_VAL_USB;
1025 break;
1026 case 6:
1027 return RET_VAL_OK;
1028 break;
1029 case MENU_ATTACHED_USB:
1030 return RET_VAL_USB;
1031 break;
1032 case GO_TO_PREVIOUS:
1033 return RET_VAL_OK;
1034 break;
1037 return RET_VAL_OK;
1040 int move_unit(int colour, int type, int fromx, int fromy,
1041 int tox, int toy, int nummen) {
1042 const char *itemnames[][3] = {
1044 "troops",
1045 "the tank",
1046 "the plane",
1047 }, {
1048 "any troops",
1049 "a tank",
1050 "a plane",
1051 }, {
1052 "the troops",
1053 "the tank",
1054 "the plane",
1057 bool human = (colour == COLOUR_LIGHT);
1058 int temp;
1060 if(human) {
1061 rb->splashf(HZ, "Select where you want to move %s from",
1062 itemnames[0][type]);
1063 if((temp = select_square()) != RET_VAL_OK)
1064 return temp;
1065 fromx = cursor.x;
1066 fromy = cursor.y;
1068 if(board[fromx][fromy].colour != colour) {
1069 if(human)
1070 rb->splash(HZ, "That isn't your territory");
1071 return RET_VAL_QUIT_ERR;
1073 if(!tile_has_item(type, fromx, fromy)) {
1074 if(human)
1075 rb->splashf(HZ, "You don't have %s there", itemnames[1][type]);
1076 return RET_VAL_QUIT_ERR;
1078 if(type == 0) {
1079 if(human) {
1080 nummen = board[fromx][fromy].men;
1081 if((temp = get_number("How many men do you want to move?", &nummen,
1082 nummen)) != RET_VAL_OK)
1083 return temp;
1085 if(nummen > board[fromx][fromy].men) {
1086 if(human)
1087 rb->splash(HZ, "You don't have that many troops.");
1088 return RET_VAL_QUIT_ERR;
1091 if(human) {
1092 rb->splashf(HZ, "Select where you want to move %s to",
1093 itemnames[2][type]);
1094 if((temp = select_square()) != RET_VAL_OK)
1095 return temp;
1096 tox = cursor.x;
1097 toy = cursor.y;
1099 if((tox == fromx && toy == fromy) ||
1100 board[tox][toy].colour != colour ||
1101 (type != 2 && (abs(tox - fromx) > 1 || abs(toy - fromy) > 1))) {
1102 if(human)
1103 rb->splash(HZ, "Invalid move");
1104 return RET_VAL_QUIT_ERR;
1106 if(type != 0 && tile_has_item(type, tox, toy)) {
1107 if(human)
1108 rb->splashf(HZ, "There is already %s there", itemnames[1][type]);
1109 return RET_VAL_QUIT_ERR;
1111 switch(type) {
1112 case 0:
1113 board[fromx][fromy].men -= nummen;
1114 board[tox][toy].men += nummen;
1115 break;
1116 case 1:
1117 board[fromx][fromy].tank = false;
1118 board[tox][toy].tank = true;
1119 break;
1120 case 2:
1121 board[fromx][fromy].plane = false;
1122 board[tox][toy].plane = true;
1123 break;
1125 return RET_VAL_OK;
1128 int move_unit_menu(void) {
1129 int selection = 0;
1131 MENUITEM_STRINGLIST(menu, "Move unit", NULL,
1132 "Move men", "Move tank", "Move plane");
1133 switch(rb->do_menu(&menu, &selection, NULL, false)) {
1134 case 0:
1135 case 1:
1136 case 2:
1137 switch(move_unit(COLOUR_LIGHT, selection, 0, 0, 0, 0, 0)) {
1138 case RET_VAL_OK:
1139 humanres.moves--;
1140 break;
1141 case RET_VAL_USB:
1142 return RET_VAL_USB;
1143 break;
1145 break;
1146 case MENU_ATTACHED_USB:
1147 return RET_VAL_USB;
1149 return RET_VAL_OK;
1152 int launch_nuke(int colour, int nukex, int nukey, int targetx, int targety) {
1153 bool human = (colour == COLOUR_LIGHT);
1154 int temp;
1155 struct resources *res;
1157 if(board[nukex][nukey].colour != colour) {
1158 if(human)
1159 rb->splash(HZ, "That isn't your territory");
1160 return RET_VAL_QUIT_ERR;
1162 if(! board[nukex][nukey].nuke) {
1163 if(human)
1164 rb->splashf(HZ, "You don't have %s there", "a nuke");
1165 return RET_VAL_QUIT_ERR;
1167 if(human) {
1168 rb->splash(HZ, "Select place to target with nuke");
1169 if((temp = select_square()) != RET_VAL_OK)
1170 return temp;
1171 targetx = cursor.x;
1172 targety = cursor.y;
1174 if(human) {
1175 humanres.nukes--;
1176 } else {
1177 compres.nukes--;
1179 board[nukex][nukey].nuke = false;
1181 if(board[targetx][targety].colour == COLOUR_LIGHT) {
1182 res = &humanres;
1183 } else {
1184 res = &compres;
1186 res->men -= board[targetx][targety].men;
1187 res->tanks -= board[targetx][targety].tank;
1188 res->planes -= board[targetx][targety].plane;
1189 res->nukes -= board[targetx][targety].nuke;
1190 res->farms -= board[targetx][targety].farm;
1191 res->inds -= board[targetx][targety].ind;
1192 board[targetx][targety].men = 0;
1193 board[targetx][targety].tank = false;
1194 board[targetx][targety].plane = false;
1195 board[targetx][targety].ind = false;
1196 board[targetx][targety].nuke = false;
1197 board[targetx][targety].farm = false;
1198 /* TODO: Fallout carried by wind */
1200 return RET_VAL_OK;
1203 int movement_menu(void) {
1204 int selection = 0, temp;
1206 MENUITEM_STRINGLIST(menu, "Movement", NULL,
1207 "Move unit", "Buy additional moves ($100)",
1208 "Launch nuclear missile", "Check map",
1209 "Finish moving", "Game menu");
1211 while(1) {
1212 switch(rb->do_menu(&menu, &selection, NULL, false)) {
1213 case 0:
1214 if(humanres.moves) {
1215 if(move_unit_menu()==RET_VAL_USB)
1216 return RET_VAL_USB;
1217 } else {
1218 rb->splash(HZ, "You have no more moves left."
1219 " You can buy more for $100 each.");
1221 break;
1222 case 1:
1223 if(humanres.cash > 100) {
1224 humanres.moves++;
1225 humanres.cash -= 100;
1226 rb->snprintf(buf, sizeof(buf), "You now have %d moves",
1227 humanres.moves);
1228 rb->splash(HZ, buf);
1230 break;
1231 case 2:
1232 if(humanres.nukes==0) {
1233 rb->splash(HZ, "You do not have any nukes to launch");
1234 } else {
1235 rb->splash(HZ, "Select place to launch nuke from");
1236 switch(select_square()) {
1237 case RET_VAL_OK:
1238 if(launch_nuke(COLOUR_LIGHT, cursor.x, cursor.y,
1239 0, 0) == RET_VAL_USB)
1240 return RET_VAL_USB;
1241 break;
1242 case RET_VAL_USB:
1243 return RET_VAL_USB;
1244 break;
1247 break;
1248 case 3:
1249 if(select_square() == RET_VAL_USB)
1250 return RET_VAL_USB;
1251 break;
1252 case 4:
1253 return RET_VAL_OK;
1254 break;
1255 case 5:
1256 if((temp = ingame_menu()) != RET_VAL_OK)
1257 return temp;
1258 break;
1259 case MENU_ATTACHED_USB:
1260 return RET_VAL_USB;
1261 break;
1264 return RET_VAL_OK;
1267 static const char* inventory_data(int selected_item, void * data,
1268 char * buffer, size_t buffer_len) {
1269 (void)data;
1270 switch(selected_item) {
1271 case 0:
1272 rb->snprintf(buffer,buffer_len,"Men: %d", humanres.men);
1273 break;
1274 case 1:
1275 rb->snprintf(buffer,buffer_len,"Tanks: %d", humanres.tanks);
1276 break;
1277 case 2:
1278 rb->snprintf(buffer,buffer_len,"Planes: %d", humanres.planes);
1279 break;
1280 case 3:
1281 rb->snprintf(buffer,buffer_len,"Factories: %d", humanres.inds);
1282 break;
1283 case 4:
1284 rb->snprintf(buffer,buffer_len,"Farms: %d", humanres.farms);
1285 break;
1286 case 5:
1287 rb->snprintf(buffer,buffer_len,"Nukes: %d", humanres.nukes);
1288 break;
1289 case 6:
1290 rb->snprintf(buffer,buffer_len,"Cash: %d", humanres.cash);
1291 break;
1292 case 7:
1293 rb->snprintf(buffer,buffer_len,"Food: %d", humanres.food);
1294 break;
1295 case 8:
1296 rb->snprintf(buffer,buffer_len,"Bank: %d", humanres.bank);
1297 break;
1298 default:
1299 return NULL;
1301 return buffer;
1304 int show_inventory(void) {
1305 struct simplelist_info info;
1306 rb->simplelist_info_init(&info, "Inventory", 9, NULL);
1307 info.hide_selection = true;
1308 info.get_name = inventory_data;
1309 if(rb->simplelist_show_list(&info)) {
1310 return RET_VAL_USB;
1311 } else {
1312 return RET_VAL_OK;
1316 int production_menu(void) {
1317 int selection = 0, temp;
1319 MENUITEM_STRINGLIST(menu, "Production", NULL,
1320 "Buy resources", "Show inventory", "Check map",
1321 "Invest money", "Withdraw money",
1322 "Finish turn", "Game menu");
1324 while(1) {
1325 switch(rb->do_menu(&menu, &selection, NULL, false)) {
1326 case 0:
1327 if(buy_resources_menu() == RET_VAL_USB)
1328 return RET_VAL_USB;
1329 break;
1330 case 1:
1331 if(show_inventory() == RET_VAL_USB)
1332 return RET_VAL_USB;
1333 break;
1334 case 2:
1335 if(select_square() == RET_VAL_USB)
1336 return RET_VAL_USB;
1337 break;
1338 case 3:
1339 temp = humanres.cash;
1340 if(get_number("How much do you want to invest?", &temp,
1341 humanres.cash) == RET_VAL_USB)
1342 return RET_VAL_USB;
1343 if(temp > humanres.cash) {
1344 rb->splash(HZ, "You don't have that much cash to invest");
1345 } else {
1346 humanres.cash -= temp;
1347 humanres.bank += temp;
1349 break;
1350 case 4:
1351 temp = humanres.bank;
1352 if(get_number("How much do you want to withdraw?", &temp,
1353 humanres.bank) == RET_VAL_USB)
1354 return RET_VAL_USB;
1355 if(temp > humanres.bank) {
1356 rb->splash(HZ, "You don't have that much cash to withdraw");
1357 } else {
1358 humanres.cash += temp;
1359 humanres.bank -= temp;
1361 break;
1362 case 5:
1363 return RET_VAL_OK;
1364 break;
1365 case 6:
1366 if((temp = ingame_menu()) != RET_VAL_OK)
1367 return temp;
1368 break;
1369 case MENU_ATTACHED_USB:
1370 return RET_VAL_USB;
1371 break;
1374 return RET_VAL_OK;
1377 void init_resources(void) {
1378 humanres.cash = superdom_settings.startcash;
1379 humanres.food = superdom_settings.startfood;
1380 humanres.tanks = 0;
1381 humanres.planes = 0;
1382 humanres.nukes = 0;
1383 humanres.inds = 0;
1384 humanres.farms = 0;
1385 humanres.men = 0;
1386 humanres.bank = 0;
1387 humanres.moves = 0;
1388 compres.cash = superdom_settings.startcash;
1389 compres.food = superdom_settings.startfood;
1390 compres.tanks = 0;
1391 compres.planes = 0;
1392 compres.nukes = 0;
1393 compres.inds = 0;
1394 compres.farms = 0;
1395 compres.men = 0;
1396 compres.bank = 0;
1397 compres.moves = 0;
1400 int select_square(void) {
1401 int button = 0;
1402 draw_board();
1403 draw_cursor();
1404 update_score();
1405 #if LCD_WIDTH >= 220
1406 rb->lcd_setfont(FONT_SYSFIXED);
1407 rb->snprintf(buf, sizeof(buf), "Cash: %d", humanres.cash);
1408 rb->lcd_putsxy(125, LCD_HEIGHT-20, buf);
1409 rb->snprintf(buf, sizeof(buf), "Food: %d", humanres.food);
1410 rb->lcd_putsxy(125, LCD_HEIGHT-10, buf);
1411 rb->lcd_setfont(FONT_UI);
1412 #endif
1413 rb->lcd_update();
1414 while(1) {
1415 button = rb->button_get(true);
1416 switch(button) {
1417 case SUPERDOM_CANCEL:
1418 rb->splash(HZ, "Cancelled");
1419 return RET_VAL_QUIT_ERR;
1420 break;
1421 case SUPERDOM_OK:
1422 return RET_VAL_OK;
1423 break;
1424 #if CONFIG_KEYPAD != IRIVER_H10_PAD
1425 case SUPERDOM_LEFT:
1426 case (SUPERDOM_LEFT|BUTTON_REPEAT):
1427 draw_cursor(); /* Deselect the current tile */
1428 if(cursor.x>1) {
1429 cursor.x--;
1430 } else {
1431 #ifdef IPOD_STYLE
1432 if(cursor.y>1)
1433 cursor.y--;
1434 else
1435 cursor.y = 10;
1436 #endif
1437 cursor.x = 10;
1439 update_score();
1440 draw_cursor();
1441 break;
1442 case SUPERDOM_RIGHT:
1443 case (SUPERDOM_RIGHT|BUTTON_REPEAT):
1444 draw_cursor(); /* Deselect the current tile */
1445 if(cursor.x<10) {
1446 cursor.x++;
1447 } else {
1448 #ifdef IPOD_STYLE
1449 if(cursor.y<10)
1450 cursor.y++;
1451 else
1452 cursor.y = 1;
1453 #endif
1454 cursor.x = 1;
1456 update_score();
1457 draw_cursor();
1458 break;
1459 #endif
1460 #ifndef IPOD_STYLE
1461 case SUPERDOM_UP:
1462 case (SUPERDOM_UP|BUTTON_REPEAT):
1463 draw_cursor(); /* Deselect the current tile */
1464 if(cursor.y>1) {
1465 cursor.y--;
1466 } else {
1467 #if CONFIG_KEYPAD == IRIVER_H10_PAD
1468 if(cursor.x > 1)
1469 cursor.x--;
1470 else
1471 cursor.x = 10;
1472 #endif
1473 cursor.y = 10;
1475 update_score();
1476 draw_cursor();
1477 break;
1478 case SUPERDOM_DOWN:
1479 case (SUPERDOM_DOWN|BUTTON_REPEAT):
1480 draw_cursor(); /* Deselect the current tile */
1481 if(cursor.y<10) {
1482 cursor.y++;
1483 } else {
1484 #if CONFIG_KEYPAD == IRIVER_H10_PAD
1485 if(cursor.x < 10)
1486 cursor.x++;
1487 else
1488 cursor.x = 1;
1489 #endif
1490 cursor.y = 1;
1492 update_score();
1493 draw_cursor();
1494 break;
1495 #endif
1496 default:
1497 if (rb->default_event_handler(button) == SYS_USB_CONNECTED)
1499 return RET_VAL_USB;
1505 int killmen(int colour) {
1506 bool human = (colour == COLOUR_LIGHT);
1507 int menkilled,i,j;
1508 int percent;
1509 if(human) {
1510 percent = (humanres.food*1000)/humanres.men;
1511 humanres.food = 0;
1512 } else {
1513 percent = (compres.food*1000)/compres.men;
1514 compres.food = 0;
1516 menkilled = 0;
1517 for(i=1;i<11;i++) {
1518 for(j=1;j<11;j++) {
1519 if(board[i][j].colour == colour) {
1520 int nummen = ((board[i][j].men * percent)/1000);
1521 menkilled += board[i][j].men - nummen;
1522 board[i][j].men = nummen;
1527 if(human)
1528 humanres.men -= menkilled;
1529 else
1530 compres.men -= menkilled;
1531 return menkilled;
1534 /* return -1 if error, 1 if attack is succeeded, 0 otherwise */
1535 int attack_territory(int colour, int x, int y) {
1536 bool human = (colour == COLOUR_LIGHT);
1537 int str_diff;
1539 if(board[x][y].colour == colour) {
1540 if(human)
1541 rb->splash(HZ, "You can't attack your own territory");
1542 return -1;
1544 str_diff = calc_strength(COLOUR_DARK, x, y) -
1545 calc_strength(COLOUR_LIGHT, x, y);
1546 if(human) {
1547 str_diff = -str_diff;
1549 rb->srand(*rb->current_tick);
1550 if(str_diff > 0 || (str_diff == 0 && rb->rand()%2)) {
1551 struct resources *offres, *defres;
1552 if(human) {
1553 offres = &humanres;
1554 defres = &compres;
1555 } else {
1556 offres = &compres;
1557 defres = &humanres;
1559 defres->men -= board[x][y].men;
1560 defres->tanks -= board[x][y].tank;
1561 defres->planes -= board[x][y].plane;
1562 defres->nukes -= board[x][y].nuke;
1563 defres->farms -= board[x][y].farm;
1564 defres->inds -= board[x][y].ind;
1565 offres->farms += board[x][y].farm;
1566 offres->inds += board[x][y].ind;
1567 board[x][y].colour = colour;
1568 board[x][y].men = 0;
1569 board[x][y].tank = false;
1570 board[x][y].plane = false;
1571 board[x][y].nuke = false;
1572 draw_board();
1573 if(human)
1574 rb->sleep(HZ*2);
1575 else
1576 rb->sleep(HZ);
1577 return 1;
1578 } else {
1579 if(human)
1580 rb->splash(HZ, "Your troops were unable to overcome"
1581 " the enemy troops");
1582 else
1583 rb->splash(HZ*2, "The computer attempted to "
1584 "attack, but the invasion was"
1585 " pushed back");
1586 return 0;
1588 return 0;
1591 int war_menu(void) {
1592 int selection = 0, temp;
1594 MENUITEM_STRINGLIST(menu, "War!", NULL,
1595 "Select territory to attack",
1596 "Finish turn", "Game menu");
1598 while(humanres.moves) {
1599 switch(rb->do_menu(&menu, &selection, NULL, false)) {
1600 case 0:
1601 switch(select_square()) {
1602 case RET_VAL_OK:
1603 if(attack_territory(COLOUR_LIGHT, cursor.x, cursor.y)
1604 >= 0)
1605 humanres.moves--;
1606 break;
1607 case RET_VAL_USB:
1608 return RET_VAL_USB;
1609 break;
1611 break;
1612 case 1:
1613 return RET_VAL_OK;
1614 break;
1615 case 2:
1616 if((temp = ingame_menu()) != RET_VAL_OK)
1617 return temp;
1618 break;
1621 return RET_VAL_OK;
1624 struct threat {
1625 int x;
1626 int y;
1627 int str_diff;
1630 bool place_adjacent(bool tank, int x, int y) {
1631 int type = (tank? 1: 2);
1632 if(!buy_resources(COLOUR_DARK, type, x, y, 0)) {
1633 return true;
1635 if(!buy_resources(COLOUR_DARK, type, x-1, y, 0)) {
1636 return true;
1638 if(!buy_resources(COLOUR_DARK, type, x+1, y, 0)) {
1639 return true;
1641 if(!buy_resources(COLOUR_DARK, type, x, y-1, 0)) {
1642 return true;
1644 if(!buy_resources(COLOUR_DARK, type, x, y+1, 0)) {
1645 return true;
1647 return false;
1650 bool has_adjacent(int x, int y) {
1651 if((board[x][y].colour == COLOUR_LIGHT) &&
1652 ((board[x-1][y].colour == COLOUR_DARK) ||
1653 (board[x+1][y].colour == COLOUR_DARK) ||
1654 (board[x][y+1].colour == COLOUR_DARK) ||
1655 (board[x][y-1].colour == COLOUR_DARK)))
1656 return 1;
1657 else
1658 return 0;
1661 void find_adjacent(int x, int y, int* adj_x, int* adj_y) {
1662 /* Finds adjacent squares, returning squares without tanks on them
1663 * in preference to those with them */
1664 if(board[x-1][y].colour == COLOUR_DARK) {
1665 *adj_x = x-1;
1666 *adj_y = y;
1667 return;
1669 if(board[x+1][y].colour == COLOUR_DARK) {
1670 *adj_x = x+1;
1671 *adj_y = y;
1672 return;
1674 if(board[x][y-1].colour == COLOUR_DARK) {
1675 *adj_x = x;
1676 *adj_y = y-1;
1677 return;
1679 if(board[x][y+1].colour == COLOUR_DARK) {
1680 *adj_x = x;
1681 *adj_y = y+1;
1682 return;
1686 void computer_allocate(void) {
1687 /* Firstly, decide whether to go offensive or defensive.
1688 * This is primarily decided by the human player posing a threat to either
1689 * the computer's farms or factories */
1690 int i, j, k;
1691 bool offensive = true;
1692 struct threat threats[4];
1693 int numthreats = 0;
1694 int total_str_diff = 0;
1695 int numterritory = 0;
1696 int str_diff;
1697 int men_needed;
1698 struct threat targets[2];
1699 int numtargets;
1700 struct cursor adj;
1702 compres.cash += compres.bank;
1703 compres.bank = 0;
1704 for(i=1;i<11;i++) {
1705 for(j=1;j<11;j++) {
1706 if(board[i][j].colour == COLOUR_DARK) {
1707 numterritory++;
1708 str_diff = calc_strength(COLOUR_LIGHT,i,j) -
1709 calc_strength(COLOUR_DARK,i,j);
1710 if(str_diff > 0 && (board[i][j].ind || board[i][j].farm)) {
1711 if(numthreats < 3) {
1712 offensive = false;
1713 threats[numthreats].x = i;
1714 threats[numthreats].y = j;
1715 threats[numthreats].str_diff = str_diff;
1716 numthreats++;
1720 rb->yield();
1723 if(offensive) {
1724 /* The AI is going to go straight for the throat here and attack
1725 * the player's farms and factories. The amount of cash
1726 * the AI has to spend will determine how many targets there are */
1727 if(compres.cash > 1200) {
1728 /* 1200 is a figure I pulled out of nowhere. Adjust as needed */
1729 numtargets = 2;
1730 } else {
1731 numtargets = 1;
1733 /* Work out which target(s) to attack. They must have adjacent squares
1734 * owned by the computer. If none are found just place troops in
1735 * random places around the map until we run out of money */
1736 k = 0;
1737 for(i=1;i<11;i++) {
1738 for(j=1;j<11;j++) {
1739 if(has_adjacent(i,j) &&
1740 (board[i][j].ind || board[i][j].farm)) {
1741 if(k<numtargets) {
1742 targets[k].x = i;
1743 targets[k].y = j;
1744 targets[k].str_diff =
1745 calc_strength(COLOUR_LIGHT, i, j) -
1746 calc_strength(COLOUR_DARK, i, j);
1747 k++;
1750 rb->yield();
1753 if(k == 0) {
1754 /* No targets found! Randomly pick squares and if they're owned
1755 * by the computer then stick a tank on it. */
1756 rb->srand(*rb->current_tick);
1757 while(compres.cash >= 300 && compres.tanks < numterritory) {
1758 i = rb->rand()%10 + 1;
1759 j = rb->rand()%10 + 1;
1760 if(board[i][j].colour == COLOUR_DARK) {
1761 buy_resources(COLOUR_DARK, 1, i, j, 0);
1763 rb->yield();
1765 } else {
1766 for(i=0;i<k;i++) {
1767 str_diff = targets[i].str_diff;
1768 while(str_diff + 20 > 0 && compres.cash > 0) {
1769 /* While we still need them keep placing men */
1770 if(!place_adjacent(true, targets[i].x, targets[i].y)) {
1771 find_adjacent(targets[i].x, targets[i].y,
1772 &adj.x, &adj.y);
1773 men_needed = (str_diff + 20)*1000/133;
1774 if(compres.cash < men_needed) {
1775 men_needed = compres.cash;
1777 buy_resources(COLOUR_DARK, 0, adj.x, adj.y,
1778 men_needed);
1779 break;
1781 str_diff = calc_strength(COLOUR_LIGHT,
1782 targets[i].x, targets[i].y) -
1783 calc_strength(COLOUR_DARK,
1784 targets[i].x, targets[i].y);
1788 } else {
1789 /* Work out what to place on each square to defend it.
1790 * Tanks are preferential because they do not require food,
1791 * but if the budget is tight then we fall back onto troops.
1792 * Conversely if cash is not an issue and there are already tanks in
1793 * place planes will be deployed. We would like a margin of at least
1794 * 20 points to be safe. */
1796 for(i=0;i<numthreats;i++) {
1797 total_str_diff += threats[i].str_diff;
1799 if((total_str_diff+20)*10 > compres.cash) {
1800 /* Not enough cash to accomodate all threats using tanks alone -
1801 * use men as a backup */
1802 for(i=0;i<numthreats;i++) {
1803 men_needed = ((threats[i].str_diff + 20)*1000)/133;
1804 if(compres.cash < men_needed) {
1805 men_needed = compres.cash;
1807 buy_resources(COLOUR_DARK, 0, threats[i].x, threats[i].y,
1808 men_needed);
1810 } else {
1811 /* Tanks it is */
1812 /* Enough money to pay their way by planes? */
1813 bool tank = ((total_str_diff+20)*15 >= compres.cash);
1814 for(i=0;i<numthreats;i++) {
1815 str_diff = threats[i].str_diff;
1816 while(str_diff + 20 > 0) {
1817 if(!place_adjacent(tank, threats[i].x, threats[i].y)) {
1818 /* No room for any more planes or tanks, revert to
1819 * men */
1820 find_adjacent(threats[i].x, threats[i].y,
1821 &adj.x, &adj.y);
1822 men_needed = (str_diff + 20)*1000/133;
1823 if(compres.cash < men_needed) {
1824 men_needed = compres.cash;
1826 buy_resources(COLOUR_DARK, 0, threats[i].x,
1827 threats[i].y, men_needed);
1828 break;
1830 str_diff = calc_strength(COLOUR_LIGHT,
1831 threats[i].x, threats[i].y) -
1832 calc_strength(COLOUR_DARK,
1833 threats[i].x, threats[i].y);
1838 compres.bank += compres.cash;
1839 compres.cash = 0;
1842 int find_adj_target(int x, int y, struct cursor* adj) {
1843 /* Find a square next to a computer's farm or factory owned by the player
1844 * that is vulnerable. Return 1 on success, 0 otherwise */
1845 if(board[x+1][y].colour == COLOUR_LIGHT &&
1846 calc_strength(COLOUR_LIGHT,x+1,y)<=calc_strength(COLOUR_DARK,x+1,y)) {
1847 adj->x = x+1;
1848 adj->y = y;
1849 return 1;
1851 if(board[x-1][y].colour == COLOUR_LIGHT &&
1852 calc_strength(COLOUR_LIGHT,x-1,y)<=calc_strength(COLOUR_DARK,x-1,y)) {
1853 adj->x = x-1;
1854 adj->y = y;
1855 return 1;
1857 if(board[x][y+1].colour == COLOUR_LIGHT &&
1858 calc_strength(COLOUR_LIGHT,x,y+1)<=calc_strength(COLOUR_DARK,x,y+1)) {
1859 adj->x = x;
1860 adj->y = y+1;
1861 return 1;
1863 if(board[x][y-1].colour == COLOUR_LIGHT &&
1864 calc_strength(COLOUR_LIGHT,x,y-1)<=calc_strength(COLOUR_DARK,x,y-1)) {
1865 adj->x = x;
1866 adj->y = y-1;
1867 return 1;
1869 return 0;
1872 void computer_war(void) {
1873 /* Work out where to attack - prioritise the defence of buildings */
1874 int i, j;
1875 bool found_target = true;
1876 struct cursor adj;
1878 while(found_target) {
1879 found_target = false;
1880 for(i=1;i<11;i++) {
1881 for(j=1;j<11;j++) {
1882 if((board[i][j].colour == COLOUR_DARK) &&
1883 (board[i][j].farm || board[i][j].ind) &&
1884 find_adj_target(i, j, &adj)) {
1885 found_target = true;
1886 if(attack_territory(COLOUR_DARK, adj.x, adj.y) >= 0) {
1887 compres.moves--;
1888 if(!compres.moves)
1889 return;
1892 rb->yield();
1896 /* Defence stage done, move on to OFFENCE */
1897 found_target = true;
1898 while(found_target) {
1899 found_target = false;
1900 for(i=1;i<11;i++) {
1901 for(j=1;j<11;j++) {
1902 if(board[i][j].colour == COLOUR_LIGHT &&
1903 (board[i][j].ind || board[i][j].farm) &&
1904 (calc_strength(COLOUR_DARK, i, j) >=
1905 calc_strength(COLOUR_LIGHT, i, j))) {
1906 found_target = true;
1907 if(attack_territory(COLOUR_DARK, i, j) >= 0) {
1908 compres.moves--;
1909 if(!compres.moves)
1910 return;
1913 rb->yield();
1917 /* Spend leftover moves wherever attacking randomly */
1918 found_target = true;
1919 while(found_target) {
1920 found_target = false;
1921 for(i=1;i<11;i++) {
1922 for(j=1;j<11;j++) {
1923 if(board[i][j].colour == COLOUR_LIGHT &&
1924 (calc_strength(COLOUR_DARK, i, j) >=
1925 calc_strength(COLOUR_LIGHT, i, j))) {
1926 found_target = true;
1927 if(attack_territory(COLOUR_DARK, i, j) >= 0) {
1928 compres.moves--;
1929 if(!compres.moves)
1930 return;
1933 rb->yield();
1939 static int load_game(const char* file) {
1940 int fd;
1942 fd = rb->open(file, O_RDONLY);
1943 if(fd < 0) {
1944 DEBUGF("Couldn't open savegame\n");
1945 return -1;
1947 rb->read(fd, buf, 5);
1948 if(rb->strcmp(buf, "SSGv3")) {
1949 rb->splash(HZ, "Invalid/incompatible savegame");
1950 return -1;
1952 rb->read(fd, &gamestate, sizeof(gamestate));
1953 rb->read(fd, &humanres.cash, sizeof(humanres.cash));
1954 rb->read(fd, &humanres.food, sizeof(humanres.food));
1955 rb->read(fd, &humanres.bank, sizeof(humanres.bank));
1956 rb->read(fd, &humanres.planes, sizeof(humanres.planes));
1957 rb->read(fd, &humanres.tanks, sizeof(humanres.tanks));
1958 rb->read(fd, &humanres.men, sizeof(humanres.men));
1959 rb->read(fd, &humanres.nukes, sizeof(humanres.nukes));
1960 rb->read(fd, &humanres.inds, sizeof(humanres.inds));
1961 rb->read(fd, &humanres.farms, sizeof(humanres.farms));
1962 rb->read(fd, &humanres.moves, sizeof(humanres.moves));
1963 rb->read(fd, &compres.cash, sizeof(humanres.cash));
1964 rb->read(fd, &compres.food, sizeof(humanres.food));
1965 rb->read(fd, &compres.bank, sizeof(humanres.bank));
1966 rb->read(fd, &compres.planes, sizeof(humanres.planes));
1967 rb->read(fd, &compres.tanks, sizeof(humanres.tanks));
1968 rb->read(fd, &compres.men, sizeof(humanres.men));
1969 rb->read(fd, &compres.nukes, sizeof(humanres.nukes));
1970 rb->read(fd, &compres.inds, sizeof(humanres.inds));
1971 rb->read(fd, &compres.farms, sizeof(humanres.farms));
1972 rb->read(fd, &compres.moves, sizeof(humanres.moves));
1973 rb->read(fd, board, sizeof(board));
1974 rb->read(fd, &superdom_settings.compstartfarms, sizeof(int));
1975 rb->read(fd, &superdom_settings.compstartinds, sizeof(int));
1976 rb->read(fd, &superdom_settings.humanstartfarms, sizeof(int));
1977 rb->read(fd, &superdom_settings.humanstartinds, sizeof(int));
1978 rb->read(fd, &superdom_settings.startcash, sizeof(int));
1979 rb->read(fd, &superdom_settings.startfood, sizeof(int));
1980 rb->read(fd, &superdom_settings.movesperturn, sizeof(int));
1981 rb->close(fd);
1982 return 0;
1985 void default_settings(void) {
1986 superdom_settings.compstartfarms = 1;
1987 superdom_settings.compstartinds = 1;
1988 superdom_settings.humanstartfarms = 2;
1989 superdom_settings.humanstartinds = 2;
1990 superdom_settings.startcash = 0;
1991 superdom_settings.startfood = 0;
1992 superdom_settings.movesperturn = 2;
1995 int average_strength(int colour) {
1996 /* This function calculates the average strength of the given player,
1997 * used to determine when the computer wins or loses. */
1998 int i,j;
1999 int totalpower = 0;
2000 for(i=1;i<11;i++) {
2001 for(j=1;j<11;j++) {
2002 if(board[i][j].colour != -1) {
2003 totalpower += calc_strength(colour, i, j);
2007 return totalpower/100;
2010 enum plugin_status plugin_start(const void* parameter)
2012 #if LCD_DEPTH > 1
2013 rb->lcd_set_backdrop(NULL);
2014 rb->lcd_set_foreground(LCD_BLACK);
2015 rb->lcd_set_background(LCD_WHITE);
2016 #endif
2018 cursor.x = 1;
2019 cursor.y = 1;
2020 default_settings();
2021 if(parameter) {
2022 if(load_game(parameter) != 0) {
2023 DEBUGF("Loading failed, generating new game\n");
2024 } else {
2025 switch(gamestate) {
2026 case GS_PROD:
2027 goto startprod;
2028 break;
2029 case GS_MOVE:
2030 goto startmove;
2031 break;
2032 case GS_WAR:
2033 goto startwar;
2034 break;
2035 default:
2036 goto startyear;
2037 break;
2042 switch(start_menu()) {
2043 case RET_VAL_OK: /* start playing */
2044 break;
2045 case RET_VAL_QUIT_ERR: /* quit */
2046 return PLUGIN_OK;
2047 break;
2048 case RET_VAL_USB:
2049 return PLUGIN_USB_CONNECTED;
2050 break;
2053 init_resources();
2054 init_board();
2055 gen_resources();
2056 startyear:
2057 while(1) {
2058 int avg_str_diff = (average_strength(COLOUR_LIGHT) -
2059 average_strength(COLOUR_DARK));
2060 if(avg_str_diff > 15) {
2061 rb->splash(HZ*4, "The computer has surrendered. You win.");
2062 return PLUGIN_OK;
2064 if(-avg_str_diff > 15) {
2065 rb->splash(HZ*4, "Your army have suffered terrible morale from"
2066 " the bleak prospects of winning. You lose.");
2067 return PLUGIN_OK;
2070 /* production */
2071 startprod:
2072 gamestate = GS_PROD;
2073 switch(production_menu()) {
2074 case RET_VAL_USB:
2075 return PLUGIN_USB_CONNECTED;
2076 break;
2077 case RET_VAL_QUIT_ERR:
2078 return PLUGIN_OK;
2079 break;
2081 computer_allocate();
2083 /* movement */
2084 humanres.moves = superdom_settings.movesperturn;
2085 startmove:
2086 gamestate = GS_MOVE;
2087 switch(movement_menu()) {
2088 case RET_VAL_USB:
2089 return PLUGIN_USB_CONNECTED;
2090 break;
2091 case RET_VAL_QUIT_ERR:
2092 return PLUGIN_OK;
2093 break;
2095 /* feed men */
2096 if(humanres.men) {
2097 if(humanres.food > humanres.men) {
2098 rb->snprintf(buf, sizeof(buf), "Your men ate %d units of food",
2099 humanres.men);
2100 humanres.food -= humanres.men;
2101 } else {
2102 rb->snprintf(buf, sizeof(buf), "There was not enough food"
2103 " to feed all your men, %d men have died of starvation",
2104 killmen(COLOUR_LIGHT));
2106 rb->splash(HZ*2, buf);
2108 if(compres.men) {
2109 if(compres.food > compres.men) {
2110 compres.food -= compres.men;
2111 } else {
2112 rb->snprintf(buf, sizeof(buf), "The computer does not have"
2113 " enough food to feed its men. %d have died of starvation",
2114 killmen(COLOUR_DARK));
2115 rb->splash(HZ, buf);
2118 /* war */
2119 humanres.moves = superdom_settings.movesperturn;
2120 startwar:
2121 gamestate = GS_WAR;
2122 switch(war_menu()) {
2123 case RET_VAL_USB:
2124 return PLUGIN_USB_CONNECTED;
2125 break;
2126 case RET_VAL_QUIT_ERR:
2127 return PLUGIN_OK;
2128 break;
2130 compres.moves = superdom_settings.movesperturn;
2131 computer_war();
2132 gen_resources();
2134 return PLUGIN_OK;