Fix FS#11007: Lua didn't parse negative numbers correct when reading from files
[kugel-rb.git] / apps / plugins / superdom.c
blobf38db8d1f421de253f882d0a26f569539af84250
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 #endif
163 #ifdef HAVE_TOUCHSCREEN
164 #ifndef SUPERDOM_OK
165 #define SUPERDOM_OK BUTTON_CENTER
166 #endif
167 #ifndef SUPERDOM_UP
168 #define SUPERDOM_UP BUTTON_TOPMIDDLE
169 #endif
170 #ifndef SUPERDOM_LEFT
171 #define SUPERDOM_LEFT BUTTON_MIDLEFT
172 #endif
173 #ifndef SUPERDOM_RIGHT
174 #define SUPERDOM_RIGHT BUTTON_MIDRIGHT
175 #endif
176 #ifndef SUPERDOM_DOWN
177 #define SUPERDOM_DOWN BUTTON_BOTTOMMIDDLE
178 #endif
179 #ifndef SUPERDOM_CANCEL
180 #define SUPERDOM_CANCEL BUTTON_TOPLEFT
181 #endif
182 #endif
184 enum {
185 RET_VAL_OK,
186 RET_VAL_USB,
187 RET_VAL_QUIT_ERR, /* quit or error */
190 void gen_interest(void);
191 void init_resources(void);
192 int select_square(void);
193 void update_score(void);
194 void gen_resources(void);
195 void draw_cursor(void);
196 void draw_board(void);
198 struct tile{
199 signed int colour; /* -1 = Unset */
200 bool tank;
201 bool plane;
202 bool nuke;
203 bool ind;
204 bool farm;
205 int men;
208 struct resources {
209 int cash;
210 int food;
211 int farms;
212 int inds;
213 int men;
214 int tanks;
215 int planes;
216 int nukes;
217 int bank;
218 int moves;
221 struct settings {
222 int compstartfarms;
223 int compstartinds;
224 int humanstartfarms;
225 int humanstartinds;
226 int startcash;
227 int startfood;
228 int movesperturn;
229 } superdom_settings;
231 struct resources humanres;
232 struct resources compres;
233 enum { GS_PROD, GS_MOVE, GS_WAR } gamestate;
235 struct cursor{
236 int x;
237 int y;
238 } cursor;
240 struct tile board[12][12];
242 void init_board(void) {
243 int i,j;
244 rb->srand(*rb->current_tick);
245 for(i=0;i<12;i++) { /* Hopefully about 50% each colour */
246 for(j=0;j<12;j++) {
247 if((i<1)||(j<1)||(i>10)||(j>10))
248 board[i][j].colour = -1; /* Unset */
249 else
250 board[i][j].colour = rb->rand()%2;
251 board[i][j].tank = false;
252 board[i][j].plane = false;
253 board[i][j].nuke = false;
254 board[i][j].ind = false;
255 board[i][j].farm = false;
256 board[i][j].men = 0;
260 while(compres.farms < superdom_settings.compstartfarms) {
261 i = rb->rand()%10 + 1;
262 j = rb->rand()%10 + 1;
263 if((board[i][j].colour == COLOUR_DARK) && (board[i][j].farm == false)) {
264 board[i][j].farm = true;
265 compres.farms++;
268 while(compres.inds < superdom_settings.compstartinds) {
269 i = rb->rand()%10 + 1;
270 j = rb->rand()%10 + 1;
271 if((board[i][j].colour == COLOUR_DARK) && (board[i][j].ind == false)) {
272 board[i][j].ind = true;
273 compres.inds++;
276 while(humanres.farms < superdom_settings.humanstartfarms) {
277 i = rb->rand()%10 + 1;
278 j = rb->rand()%10 + 1;
279 if((board[i][j].colour == COLOUR_LIGHT)&&(board[i][j].farm == false)) {
280 board[i][j].farm = true;
281 humanres.farms++;
284 while(humanres.inds < superdom_settings.humanstartinds) {
285 i = rb->rand()%10 + 1;
286 j = rb->rand()%10 + 1;
287 if((board[i][j].colour == COLOUR_LIGHT) && (board[i][j].ind == false)) {
288 board[i][j].ind = true;
289 humanres.inds++;
294 void draw_board(void) {
295 int i,j;
296 rb->lcd_clear_display();
297 for(i=1;i<11;i++) {
298 for(j=1;j<11;j++) {
299 if(board[i][j].colour == COLOUR_DARK) {
300 rb->lcd_set_foreground(LCD_DARKGRAY);
301 } else {
302 rb->lcd_set_foreground(LCD_LIGHTGRAY);
304 rb->lcd_fillrect(MARGIN+(BOX_WIDTH*(i-1)),
305 MARGIN+(BOX_HEIGHT*(j-1)), BOX_WIDTH,
306 BOX_HEIGHT);
307 #if LCD_DEPTH != 16
308 rb->lcd_set_drawmode(DRMODE_BG | DRMODE_INVERSEVID);
309 #endif
310 if(board[i][j].ind) {
311 MY_BITMAP_PART(superdom_boarditems,
312 board[i][j].colour?ICON_WIDTH:0, 0, ICON_STRIDE,
313 #if LCD_WIDTH > LCD_HEIGHT
314 MARGIN+(BOX_WIDTH*(i-1))+1,
315 MARGIN+(BOX_HEIGHT*(j-1))+ICON_HEIGHT+1,
316 #else
317 MARGIN+(BOX_WIDTH*(i-1))+1+ICON_WIDTH,
318 MARGIN+(BOX_HEIGHT*(j-1))+1,
319 #endif
320 ICON_WIDTH, ICON_HEIGHT);
322 if(board[i][j].farm) {
323 MY_BITMAP_PART(superdom_boarditems,
324 board[i][j].colour?ICON_WIDTH:0, ICON_HEIGHT,
325 ICON_STRIDE, MARGIN+(BOX_WIDTH*(i-1))+1,
326 MARGIN+(BOX_HEIGHT*(j-1))+1,
327 ICON_WIDTH, ICON_HEIGHT);
329 if(board[i][j].tank) {
330 MY_BITMAP_PART(superdom_boarditems,
331 board[i][j].colour?ICON_WIDTH:0, ICON_HEIGHT*2,
332 ICON_STRIDE, MARGIN+(BOX_WIDTH*(i-1))+ICON_WIDTH+1,
333 MARGIN+(BOX_HEIGHT*(j-1))+ICON_HEIGHT+1,
334 ICON_WIDTH, ICON_HEIGHT);
336 if(board[i][j].men) {
337 MY_BITMAP_PART(superdom_boarditems,
338 board[i][j].colour?ICON_WIDTH:0, ICON_HEIGHT*3,
339 #if LCD_WIDTH > LCD_HEIGHT
340 ICON_STRIDE, MARGIN+(BOX_WIDTH*(i-1))+ICON_WIDTH+1,
341 MARGIN+(BOX_HEIGHT*(j-1))+1,
342 #else
343 ICON_STRIDE, MARGIN+(BOX_WIDTH*(i-1))+1,
344 MARGIN+(BOX_HEIGHT*(j-1))+1+ICON_HEIGHT,
345 #endif
346 ICON_WIDTH, ICON_HEIGHT);
348 if(board[i][j].plane) {
349 MY_BITMAP_PART(superdom_boarditems,
350 board[i][j].colour?ICON_WIDTH:0, ICON_HEIGHT*4,
351 #if LCD_WIDTH > LCD_HEIGHT
352 ICON_STRIDE,MARGIN+(BOX_WIDTH*(i-1))+ICON_WIDTH*2+1,
353 MARGIN+(BOX_HEIGHT*(j-1))+ICON_HEIGHT+1,
354 #else
355 ICON_STRIDE,MARGIN+(BOX_WIDTH*(i-1))+ICON_WIDTH+1,
356 MARGIN+(BOX_HEIGHT*(j-1))+ICON_HEIGHT*2+1,
357 #endif
358 ICON_WIDTH, ICON_HEIGHT);
360 if(board[i][j].nuke) {
361 MY_BITMAP_PART(superdom_boarditems,
362 board[i][j].colour?ICON_WIDTH:0, ICON_HEIGHT*5,
363 #if LCD_WIDTH > LCD_HEIGHT
364 ICON_STRIDE,MARGIN+(BOX_WIDTH*(i-1))+ICON_WIDTH*2+1,
365 MARGIN+(BOX_HEIGHT*(j-1))+1,
366 #else
367 ICON_STRIDE,MARGIN+(BOX_WIDTH*(i-1))+1,
368 MARGIN+(BOX_HEIGHT*(j-1))+ICON_HEIGHT*2+1,
369 #endif
370 ICON_WIDTH, ICON_HEIGHT);
372 #if LCD_DEPTH != 16
373 rb->lcd_set_drawmode(DRMODE_SOLID);
374 #endif
377 rb->lcd_set_foreground(LCD_BLACK);
378 for(i=0;i<=10;i++) { /* Draw Horizontal lines */
379 rb->lcd_hline(MARGIN, MARGIN+(BOX_WIDTH*10), MARGIN+(BOX_HEIGHT*i));
381 for(i=0;i<=10;i++) { /* Draw Vertical lines */
382 rb->lcd_vline(MARGIN+(BOX_WIDTH*i), MARGIN, MARGIN+(BOX_HEIGHT*10));
384 rb->lcd_update();
387 int calc_strength(int colour, int x, int y) {
388 int a, b, score=0;
389 for (a = -1; a < 2; a++) {
390 for (b = -1; b < 2; b++) {
391 if ((b == 0 || a == 0) &&
392 (board[x + a][y + b].colour == colour)) {
393 score += 10;
394 if(board[x + a][y + b].tank || board[x + a][y + b].farm)
395 score += 30;
396 if(board[x + a][y + b].plane || board[x + a][y + b].ind)
397 score += 40;
398 if(board[x + a][y + b].nuke)
399 score += 20;
400 if(board[x + a][y + b].men)
401 score += (board[x + a][y + b].men*133/1000);
405 return score;
408 void gen_interest(void) {
409 /* Interest should be around 10% */
410 rb->srand(*rb->current_tick);
411 int interest = 7+rb->rand()%6;
412 humanres.bank = humanres.bank+(interest*humanres.bank/100);
413 compres.bank = compres.bank+(interest*compres.bank/100);
416 void draw_cursor(void) {
417 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
418 rb->lcd_fillrect(MARGIN+((cursor.x-1)*BOX_WIDTH),
419 MARGIN+((cursor.y-1)*BOX_HEIGHT), BOX_WIDTH+1, BOX_HEIGHT+1);
420 rb->lcd_set_drawmode(DRMODE_SOLID);
421 rb->lcd_update();
424 void gen_resources(void) {
425 int inccash = 0;
426 int incfood = 0;
427 int ratecash = 0;
428 int ratefood = 0;
429 int i;
430 gen_interest();
431 rb->srand(*rb->current_tick);
432 /* Generate Human's resources */
433 for(i=0;i<humanres.inds;i++) {
434 inccash += (300+rb->rand()%200);
436 for(i=0;i<humanres.farms;i++) {
437 incfood += (200+rb->rand()%200);
439 if(humanres.inds)
440 ratecash = inccash/humanres.inds;
441 if(humanres.farms)
442 ratefood = incfood/humanres.farms;
443 if(ratecash > 450) {
444 if(ratefood > 350) {
445 rb->splash(HZ*2, "Patriotism sweeps the land, all production"
446 " is up this year!");
447 } else {
448 rb->splash(HZ*2, "Factories working at maximum efficiency,"
449 " cash production up this year!");
451 } else if(ratecash > 350) {
452 if(ratefood > 350) {
453 rb->splash(HZ*2, "Record crop harvest this year!");
454 } else if(ratefood > 250) {
455 rb->splash(HZ*2, "Production continues as normal");
456 } else {
457 rb->splash(HZ*2, "Spoilage of crops leads to reduced farm"
458 " output this year");
460 } else {
461 if(ratefood > 350) {
462 rb->splash(HZ*2, "Record crop harvest this year!");
463 } else if(ratefood > 250) {
464 rb->splash(HZ*2, "Factory unions introduced. Industrial"
465 " production is down this year.");
466 } else {
467 rb->splash(HZ*2, "Internet created. All production is down"
468 " due to time wasted.");
471 humanres.cash += inccash;
472 humanres.food += incfood;
474 /* Generate Computer's resources */
475 inccash = 0;
476 incfood = 0;
477 for(i=0;i<compres.inds;i++) {
478 inccash += (300+rb->rand()%200);
480 for(i=0;i<compres.farms;i++) {
481 incfood += (200+rb->rand()%200);
483 compres.cash += inccash;
484 compres.food += incfood;
487 void update_score(void) {
488 int strength;
489 rb->lcd_setfont(FONT_SYSFIXED);
490 rb->lcd_set_drawmode(DRMODE_BG|DRMODE_INVERSEVID);
491 rb->lcd_fillrect(5,LCD_HEIGHT-20,105,20);
492 rb->lcd_set_drawmode(DRMODE_SOLID);
493 strength = calc_strength(COLOUR_LIGHT, cursor.x, cursor.y);
494 rb->snprintf(buf, sizeof(buf), "Your power: %d.%d",
495 strength/10, strength%10);
496 rb->lcd_putsxy(5,LCD_HEIGHT-20, buf);
497 strength = calc_strength(COLOUR_DARK, cursor.x, cursor.y);
498 rb->snprintf(buf, sizeof(buf), "Comp power: %d.%d",
499 strength/10, strength%10);
500 rb->lcd_putsxy(5,LCD_HEIGHT-10, buf);
501 rb->lcd_setfont(FONT_UI);
504 int settings_menu(void) {
505 int selection = 0;
507 MENUITEM_STRINGLIST(menu, "Super Domination Settings", NULL,
508 "Computer starting farms", "Computer starting factories",
509 "Human starting farms", "Human starting factories",
510 "Starting cash", "Starting food", "Moves per turn");
512 while(1) {
513 switch(rb->do_menu(&menu, &selection, NULL, false)) {
514 case 0:
515 rb->set_int("Computer starting farms", "", UNIT_INT,
516 &superdom_settings.compstartfarms, NULL,
517 1, 0, 5, NULL);
518 break;
519 case 1:
520 rb->set_int("Computer starting factories", "", UNIT_INT,
521 &superdom_settings.compstartinds, NULL,
522 1, 0, 5, NULL);
523 break;
524 case 2:
525 rb->set_int("Human starting farms", "", UNIT_INT,
526 &superdom_settings.humanstartfarms, NULL,
527 1, 0, 5, NULL);
528 break;
529 case 3:
530 rb->set_int("Human starting factories", "", UNIT_INT,
531 &superdom_settings.humanstartinds, NULL,
532 1, 0, 5, NULL);
533 break;
534 case 4:
535 rb->set_int("Starting cash", "", UNIT_INT,
536 &superdom_settings.startcash, NULL,
537 250, 0, 5000, NULL);
538 break;
539 case 5:
540 rb->set_int("Starting food", "", UNIT_INT,
541 &superdom_settings.startfood, NULL,
542 250, 0, 5000, NULL);
543 break;
544 case 6:
545 rb->set_int("Moves per turn", "", UNIT_INT,
546 &superdom_settings.movesperturn, NULL,
547 1, 1, 5, NULL);
548 break;
549 case MENU_ATTACHED_USB:
550 return RET_VAL_USB;
551 break;
552 case GO_TO_PREVIOUS:
553 return RET_VAL_OK;
554 break;
557 return RET_VAL_OK;
560 static int superdom_help(void) {
561 int button;
562 static char* help_text[] = {
563 "Super", "domination", "is", "a", "turn", "based", "strategy", "game,",
564 "where", "the", "aim", "is", "to", "overpower", "the", "computer",
565 "player", "by", "taking", "their", "territory.", "",
566 "Each", "year", "you", "are", "allocated", "an", "amount", "of", "cash",
567 "and", "food,", "depending", "on", "how", "many", "farms", "and",
568 "factories", "you", "control.", "",
569 "Use", "this", "cash", "and", "food", "to", "buy", "and", "feed", "your",
570 "army.", "Each", "tile", "has", "a", "strength,", "calculated", "by",
571 "the", "ownership", "of", "adjacent", "tiles,", "and", "the", "type",
572 "and", "number", "of", "troops", "on", "them.",
575 if (display_text(ARRAYLEN(help_text), help_text, NULL, NULL))
576 return RET_VAL_USB;
577 do {
578 button = rb->button_get(true);
579 if ( rb->default_event_handler( button ) == SYS_USB_CONNECTED )
580 return RET_VAL_USB;
581 } while( ( button == BUTTON_NONE )
582 || ( button & (BUTTON_REL|BUTTON_REPEAT) ) );
584 return RET_VAL_OK;
587 int start_menu(void) {
588 int selection = 0;
590 MENUITEM_STRINGLIST(menu, "Super Domination Menu", NULL,
591 "Play Super Domination", "Settings",
592 "Help", "Playback Control", "Quit");
594 while(1) {
595 switch(rb->do_menu(&menu, &selection, NULL, false)) {
596 case 0:
597 return RET_VAL_OK; /* start playing */
598 break;
599 case 1:
600 if(settings_menu()==RET_VAL_USB)
601 return RET_VAL_USB;
602 break;
603 case 2:
604 if(superdom_help()==RET_VAL_USB)
605 return RET_VAL_USB;
606 break;
607 case 3:
608 if(playback_control(NULL))
609 return RET_VAL_USB;
610 break;
611 case 4:
612 return RET_VAL_QUIT_ERR;
613 break;
616 return RET_VAL_QUIT_ERR;
619 int save_game(void) {
620 int fd;
621 char savepath[MAX_PATH];
623 rb->snprintf(savepath, sizeof(savepath), "/Savegame.ssg");
624 if(rb->kbd_input(savepath, MAX_PATH)) {
625 DEBUGF("Keyboard input failed\n");
626 return -1;
629 fd = rb->open(savepath, O_WRONLY|O_CREAT);
630 DEBUGF("savepath: %s\n", savepath);
631 if(fd < 0) {
632 DEBUGF("Couldn't create/open file\n");
633 return -1;
636 rb->write(fd, "SSGv3", 5);
637 rb->write(fd, &gamestate, sizeof(gamestate));
638 rb->write(fd, &humanres.cash, sizeof(humanres.cash));
639 rb->write(fd, &humanres.food, sizeof(humanres.food));
640 rb->write(fd, &humanres.bank, sizeof(humanres.bank));
641 rb->write(fd, &humanres.planes, sizeof(humanres.planes));
642 rb->write(fd, &humanres.tanks, sizeof(humanres.tanks));
643 rb->write(fd, &humanres.men, sizeof(humanres.men));
644 rb->write(fd, &humanres.nukes, sizeof(humanres.nukes));
645 rb->write(fd, &humanres.inds, sizeof(humanres.inds));
646 rb->write(fd, &humanres.farms, sizeof(humanres.farms));
647 rb->write(fd, &humanres.moves, sizeof(humanres.moves));
648 rb->write(fd, &compres.cash, sizeof(compres.cash));
649 rb->write(fd, &compres.food, sizeof(compres.food));
650 rb->write(fd, &compres.bank, sizeof(compres.bank));
651 rb->write(fd, &compres.planes, sizeof(compres.planes));
652 rb->write(fd, &compres.tanks, sizeof(compres.tanks));
653 rb->write(fd, &compres.men, sizeof(compres.men));
654 rb->write(fd, &compres.nukes, sizeof(compres.nukes));
655 rb->write(fd, &compres.inds, sizeof(compres.inds));
656 rb->write(fd, &compres.farms, sizeof(compres.farms));
657 rb->write(fd, &compres.moves, sizeof(compres.moves));
658 rb->write(fd, board, sizeof(board));
659 rb->write(fd, &superdom_settings.compstartfarms, sizeof(int));
660 rb->write(fd, &superdom_settings.compstartinds, sizeof(int));
661 rb->write(fd, &superdom_settings.humanstartfarms, sizeof(int));
662 rb->write(fd, &superdom_settings.humanstartinds, sizeof(int));
663 rb->write(fd, &superdom_settings.startcash, sizeof(int));
664 rb->write(fd, &superdom_settings.startfood, sizeof(int));
665 rb->write(fd, &superdom_settings.movesperturn, sizeof(int));
666 rb->close(fd);
667 return 0;
670 int ingame_menu(void) {
671 MENUITEM_STRINGLIST(menu, "Super Domination Menu", NULL,
672 "Return to game", "Save Game",
673 "Playback Control", "Quit");
675 switch(rb->do_menu(&menu, NULL, NULL, false)) {
676 case 0:
677 return RET_VAL_OK;
678 break;
679 case 1:
680 if(!save_game())
681 rb->splash(HZ, "Game saved");
682 else
683 rb->splash(HZ, "Error in save");
684 break;
685 case 2:
686 if(playback_control(NULL))
687 return RET_VAL_USB;
688 break;
689 case 3:
690 return RET_VAL_QUIT_ERR;
691 break;
692 case MENU_ATTACHED_USB:
693 return RET_VAL_USB;
694 break;
695 case GO_TO_PREVIOUS:
696 return RET_VAL_OK;
697 break;
699 return RET_VAL_OK;
702 int get_number(char* param, int* value, int max) {
703 static const char *button_labels[4][3] = {
704 { "1", "2", "3" },
705 { "4", "5", "6" },
706 { "7", "8", "9" },
707 { "CLR", "0", "OK" }
709 int i,j,x=0,y=0;
710 int height, width;
711 int button = 0, ret = RET_VAL_OK;
712 bool done = false;
713 rb->lcd_clear_display();
714 rb->lcd_getstringsize("CLR", &width, &height);
715 if(width > NUM_BOX_WIDTH || height > NUM_BOX_HEIGHT)
716 rb->lcd_setfont(FONT_SYSFIXED);
717 /* Draw a 3x4 grid */
718 for(i=0;i<=3;i++) { /* Vertical lines */
719 rb->lcd_vline(NUM_MARGIN_X+(NUM_BOX_WIDTH*i), NUM_MARGIN_Y,
720 NUM_MARGIN_Y+(4*NUM_BOX_HEIGHT));
722 for(i=0;i<=4;i++) { /* Horizontal lines */
723 rb->lcd_hline(NUM_MARGIN_X, NUM_MARGIN_X+(3*NUM_BOX_WIDTH),
724 NUM_MARGIN_Y+(NUM_BOX_HEIGHT*i));
726 for(i=0;i<4;i++) {
727 for(j=0;j<3;j++) {
728 rb->lcd_getstringsize(button_labels[i][j], &width, &height);
729 rb->lcd_putsxy(
730 NUM_MARGIN_X+(j*NUM_BOX_WIDTH)+NUM_BOX_WIDTH/2-width/2,
731 NUM_MARGIN_Y+(i*NUM_BOX_HEIGHT)+NUM_BOX_HEIGHT/2-height/2,
732 button_labels[i][j]);
735 rb->snprintf(buf,sizeof(buf), "%d", *value);
736 rb->lcd_putsxy(NUM_MARGIN_X+10, NUM_MARGIN_Y+4*NUM_BOX_HEIGHT+10, buf);
737 rb->lcd_getstringsize(param, &width, &height);
738 if(width < LCD_WIDTH)
739 rb->lcd_putsxy((LCD_WIDTH-width)/2, (NUM_MARGIN_Y-height)/2, param);
740 else
741 rb->lcd_puts_scroll(0, (NUM_MARGIN_Y/height-1)/2, param);
742 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
743 rb->lcd_fillrect(NUM_MARGIN_X+(NUM_BOX_WIDTH*x),
744 NUM_MARGIN_Y+(NUM_BOX_HEIGHT*y),
745 NUM_BOX_WIDTH+1, NUM_BOX_HEIGHT+1);
746 rb->lcd_set_drawmode(DRMODE_SOLID);
747 rb->lcd_update();
748 while(!done) {
749 button = rb->button_get(true);
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 switch(button) {
756 case SUPERDOM_OK:
757 if(y!=3) {
758 *value *= 10;
759 *value += button_labels[y][x][0] - '0';
760 } else if(x==0) {
761 *value /= 10;
762 } else if(x==1) {
763 *value *= 10;
764 } else if(x==2) {
765 done = true;
766 break;
768 if ((unsigned) *value > (unsigned) max)
769 *value = max;
770 rb->lcd_set_drawmode(DRMODE_BG|DRMODE_INVERSEVID);
771 rb->lcd_fillrect(0, NUM_MARGIN_Y+4*NUM_BOX_HEIGHT+10,
772 LCD_WIDTH, 30);
773 rb->lcd_set_drawmode(DRMODE_SOLID);
774 rb->snprintf(buf,sizeof(buf), "%d", *value);
775 rb->lcd_putsxy(NUM_MARGIN_X+10,
776 NUM_MARGIN_Y+4*NUM_BOX_HEIGHT+10, buf);
777 break;
778 case SUPERDOM_CANCEL:
779 *value = 0;
780 done = true;
781 ret = RET_VAL_QUIT_ERR;
782 break;
783 #if CONFIG_KEYPAD != IRIVER_H10_PAD
784 case SUPERDOM_LEFT:
785 if(x==0) {
786 #ifdef IPOD_STYLE
787 if(y>0)
788 y--;
789 else
790 y=3;
791 #endif
792 x=2;
793 } else {
794 x--;
796 break;
797 case SUPERDOM_RIGHT:
798 if(x==2) {
799 #ifdef IPOD_STYLE
800 if(y==3)
801 y=0;
802 else
803 y++;
804 #endif
805 x=0;
806 } else {
807 x++;
809 break;
810 #endif
811 #ifndef IPOD_STYLE
812 case SUPERDOM_UP:
813 if(y==0) {
814 #if CONFIG_KEYPAD == IRIVER_H10_PAD
815 if(x > 0)
816 x--;
817 else
818 x=2;
819 #endif
820 y=3;
821 } else {
822 y--;
824 break;
825 case SUPERDOM_DOWN:
826 if(y==3) {
827 #if CONFIG_KEYPAD == IRIVER_H10_PAD
828 if(x < 2)
829 x++;
830 else
831 x=0;
832 #endif
833 y=0;
834 } else {
835 y++;
837 break;
838 #endif
839 default:
840 if (rb->default_event_handler(button) == SYS_USB_CONNECTED)
842 done = true;
843 ret = RET_VAL_USB;
845 break;
847 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
848 rb->lcd_fillrect(NUM_MARGIN_X+(NUM_BOX_WIDTH*x),
849 NUM_MARGIN_Y+(NUM_BOX_HEIGHT*y),
850 NUM_BOX_WIDTH+1, NUM_BOX_HEIGHT+1);
851 rb->lcd_set_drawmode(DRMODE_SOLID);
852 rb->lcd_update();
854 rb->lcd_setfont(FONT_UI);
855 rb->lcd_stop_scroll();
856 if (ret == RET_VAL_QUIT_ERR)
857 rb->splash(HZ, "Cancelled");
858 return ret;
861 bool tile_has_item(int type, int x, int y) {
862 switch(type) {
863 case 0:
864 return (board[x][y].men > 0);
865 break;
866 case 1:
867 return board[x][y].tank;
868 break;
869 case 2:
870 return board[x][y].plane;
871 break;
872 case 3:
873 return board[x][y].farm;
874 break;
875 case 4:
876 return board[x][y].ind;
877 break;
878 case 5:
879 return board[x][y].nuke;
880 break;
882 return false;
885 int buy_resources(int colour, int type, int x, int y, int nummen) {
886 const char *itemnames[][6] = {
888 "them",
889 "the tank",
890 "the plane",
891 "the farm",
892 "the industrial plant",
893 "the nuke",
894 }, {
895 "place men",
896 "place a tank",
897 "place a plane",
898 "build a farm",
899 "build an industrial plant",
900 "place a nuke",
901 }, {
902 NULL,
903 "a tank",
904 "a plane",
905 "a farm",
906 "an industrial plant",
907 "a nuke",
911 bool human = (colour == COLOUR_LIGHT);
912 int price = 0;
913 int temp;
914 struct resources *res;
916 if(human) {
917 res = &humanres;
918 } else {
919 res = &compres;
921 switch(type) {
922 case 0: /* men */
923 price = 1*nummen;
924 break;
925 case 1: /* tank */
926 price = 300;
927 break;
928 case 2: /* plane */
929 price = 600;
930 break;
931 case 3: /* Farm */
932 price = 1150;
933 break;
934 case 4: /* Factory */
935 price = 1300;
936 break;
937 case 5: /* nuke */
938 price = 2000;
939 break;
941 if(res->cash < price) {
942 if(human)
943 rb->splash(HZ, "Not enough money!");
944 return RET_VAL_QUIT_ERR;
946 if(human) {
947 rb->splashf(HZ, "Where do you want to place %s?", itemnames[0][type]);
948 if((temp = select_square()) != RET_VAL_OK)
949 return temp;
950 x = cursor.x;
951 y = cursor.y;
953 if(board[x][y].colour != colour) {
954 if(human)
955 rb->splashf(HZ, "Can't %s on enemy territory", itemnames[1][type]);
956 return RET_VAL_QUIT_ERR;
958 if(type != 0 && tile_has_item(type, x, y)) {
959 if(human)
960 rb->splashf(HZ, "There is already %s there", itemnames[2][type]);
961 return RET_VAL_QUIT_ERR;
963 switch(type) {
964 case 0:
965 board[x][y].men += nummen;
966 res->men += nummen;
967 break;
968 case 1:
969 board[x][y].tank = true;
970 res->tanks++;
971 break;
972 case 2:
973 board[x][y].plane = true;
974 res->planes++;
975 break;
976 case 3:
977 board[x][y].farm = true;
978 res->farms++;
979 break;
980 case 4:
981 board[x][y].ind = true;
982 res->inds++;
983 break;
984 case 5:
985 board[x][y].nuke = true;
986 res->nukes++;
987 break;
989 res->cash -= price;
991 draw_board();
992 rb->sleep(HZ);
994 return RET_VAL_OK;
997 int buy_resources_menu(void) {
998 int selection = 0,nummen;
1000 MENUITEM_STRINGLIST(menu, "Buy Resources", NULL,
1001 "Buy men ($1)", "Buy tank ($300)", "Buy plane ($600)",
1002 "Buy Farm ($1150)", "Buy Factory ($1300)",
1003 "Buy Nuke ($2000)",
1004 "Finish buying");
1006 while(1) {
1007 switch(rb->do_menu(&menu, &selection, NULL, false)) {
1008 case 0:
1009 nummen = 0;
1010 if(get_number("How many men would you like?", &nummen,
1011 humanres.cash) == RET_VAL_USB)
1012 return RET_VAL_USB;
1013 if(!nummen)
1014 break;
1015 /* fall through */
1016 case 1:
1017 case 2:
1018 case 3:
1019 case 4:
1020 case 5:
1021 if(buy_resources(COLOUR_LIGHT, selection, 0, 0, nummen)
1022 == RET_VAL_USB)
1023 return RET_VAL_USB;
1024 break;
1025 case 6:
1026 return RET_VAL_OK;
1027 break;
1028 case MENU_ATTACHED_USB:
1029 return RET_VAL_USB;
1030 break;
1031 case GO_TO_PREVIOUS:
1032 return RET_VAL_OK;
1033 break;
1036 return RET_VAL_OK;
1039 int move_unit(int colour, int type, int fromx, int fromy,
1040 int tox, int toy, int nummen) {
1041 const char *itemnames[][3] = {
1043 "troops",
1044 "the tank",
1045 "the plane",
1046 }, {
1047 "any troops",
1048 "a tank",
1049 "a plane",
1050 }, {
1051 "the troops",
1052 "the tank",
1053 "the plane",
1056 bool human = (colour == COLOUR_LIGHT);
1057 int temp;
1059 if(human) {
1060 rb->splashf(HZ, "Select where you want to move %s from",
1061 itemnames[0][type]);
1062 if((temp = select_square()) != RET_VAL_OK)
1063 return temp;
1064 fromx = cursor.x;
1065 fromy = cursor.y;
1067 if(board[fromx][fromy].colour != colour) {
1068 if(human)
1069 rb->splash(HZ, "That isn't your territory");
1070 return RET_VAL_QUIT_ERR;
1072 if(!tile_has_item(type, fromx, fromy)) {
1073 if(human)
1074 rb->splashf(HZ, "You don't have %s there", itemnames[1][type]);
1075 return RET_VAL_QUIT_ERR;
1077 if(type == 0) {
1078 if(human) {
1079 nummen = board[fromx][fromy].men;
1080 if((temp = get_number("How many men do you want to move?", &nummen,
1081 nummen)) != RET_VAL_OK)
1082 return temp;
1084 if(nummen > board[fromx][fromy].men) {
1085 if(human)
1086 rb->splash(HZ, "You don't have that many troops.");
1087 return RET_VAL_QUIT_ERR;
1090 if(human) {
1091 rb->splashf(HZ, "Select where you want to move %s to",
1092 itemnames[2][type]);
1093 if((temp = select_square()) != RET_VAL_OK)
1094 return temp;
1095 tox = cursor.x;
1096 toy = cursor.y;
1098 if((tox == fromx && toy == fromy) ||
1099 board[tox][toy].colour != colour ||
1100 (type != 2 && (abs(tox - fromx) > 1 || abs(toy - fromy) > 1))) {
1101 if(human)
1102 rb->splash(HZ, "Invalid move");
1103 return RET_VAL_QUIT_ERR;
1105 if(type != 0 && tile_has_item(type, tox, toy)) {
1106 if(human)
1107 rb->splashf(HZ, "There is already %s there", itemnames[1][type]);
1108 return RET_VAL_QUIT_ERR;
1110 switch(type) {
1111 case 0:
1112 board[fromx][fromy].men -= nummen;
1113 board[tox][toy].men += nummen;
1114 break;
1115 case 1:
1116 board[fromx][fromy].tank = false;
1117 board[tox][toy].tank = true;
1118 break;
1119 case 2:
1120 board[fromx][fromy].plane = false;
1121 board[tox][toy].plane = true;
1122 break;
1124 return RET_VAL_OK;
1127 int move_unit_menu(void) {
1128 int selection = 0;
1130 MENUITEM_STRINGLIST(menu, "Move unit", NULL,
1131 "Move men", "Move tank", "Move plane");
1132 switch(rb->do_menu(&menu, &selection, NULL, false)) {
1133 case 0:
1134 case 1:
1135 case 2:
1136 switch(move_unit(COLOUR_LIGHT, selection, 0, 0, 0, 0, 0)) {
1137 case RET_VAL_OK:
1138 humanres.moves--;
1139 break;
1140 case RET_VAL_USB:
1141 return RET_VAL_USB;
1142 break;
1144 break;
1145 case MENU_ATTACHED_USB:
1146 return RET_VAL_USB;
1148 return RET_VAL_OK;
1151 int launch_nuke(int colour, int nukex, int nukey, int targetx, int targety) {
1152 bool human = (colour == COLOUR_LIGHT);
1153 int temp;
1154 struct resources *res;
1156 if(board[nukex][nukey].colour != colour) {
1157 if(human)
1158 rb->splash(HZ, "That isn't your territory");
1159 return RET_VAL_QUIT_ERR;
1161 if(! board[nukex][nukey].nuke) {
1162 if(human)
1163 rb->splashf(HZ, "You don't have %s there", "a nuke");
1164 return RET_VAL_QUIT_ERR;
1166 if(human) {
1167 rb->splash(HZ, "Select place to target with nuke");
1168 if((temp = select_square()) != RET_VAL_OK)
1169 return temp;
1170 targetx = cursor.x;
1171 targety = cursor.y;
1173 if(human) {
1174 humanres.nukes--;
1175 } else {
1176 compres.nukes--;
1178 board[nukex][nukey].nuke = false;
1180 if(board[targetx][targety].colour == COLOUR_LIGHT) {
1181 res = &humanres;
1182 } else {
1183 res = &compres;
1185 res->men -= board[targetx][targety].men;
1186 res->tanks -= board[targetx][targety].tank;
1187 res->planes -= board[targetx][targety].plane;
1188 res->nukes -= board[targetx][targety].nuke;
1189 res->farms -= board[targetx][targety].farm;
1190 res->inds -= board[targetx][targety].ind;
1191 board[targetx][targety].men = 0;
1192 board[targetx][targety].tank = false;
1193 board[targetx][targety].plane = false;
1194 board[targetx][targety].ind = false;
1195 board[targetx][targety].nuke = false;
1196 board[targetx][targety].farm = false;
1197 /* TODO: Fallout carried by wind */
1199 return RET_VAL_OK;
1202 int movement_menu(void) {
1203 int selection = 0, temp;
1205 MENUITEM_STRINGLIST(menu, "Movement", NULL,
1206 "Move unit", "Buy additional moves ($100)",
1207 "Launch nuclear missile", "Check map",
1208 "Finish moving", "Game menu");
1210 while(1) {
1211 switch(rb->do_menu(&menu, &selection, NULL, false)) {
1212 case 0:
1213 if(humanres.moves) {
1214 if(move_unit_menu()==RET_VAL_USB)
1215 return RET_VAL_USB;
1216 } else {
1217 rb->splash(HZ, "You have no more moves left."
1218 " You can buy more for $100 each.");
1220 break;
1221 case 1:
1222 if(humanres.cash > 100) {
1223 humanres.moves++;
1224 humanres.cash -= 100;
1225 rb->snprintf(buf, sizeof(buf), "You now have %d moves",
1226 humanres.moves);
1227 rb->splash(HZ, buf);
1229 break;
1230 case 2:
1231 if(humanres.nukes==0) {
1232 rb->splash(HZ, "You do not have any nukes to launch");
1233 } else {
1234 rb->splash(HZ, "Select place to launch nuke from");
1235 switch(select_square()) {
1236 case RET_VAL_OK:
1237 if(launch_nuke(COLOUR_LIGHT, cursor.x, cursor.y,
1238 0, 0) == RET_VAL_USB)
1239 return RET_VAL_USB;
1240 break;
1241 case RET_VAL_USB:
1242 return RET_VAL_USB;
1243 break;
1246 break;
1247 case 3:
1248 if(select_square() == RET_VAL_USB)
1249 return RET_VAL_USB;
1250 break;
1251 case 4:
1252 return RET_VAL_OK;
1253 break;
1254 case 5:
1255 if((temp = ingame_menu()) != RET_VAL_OK)
1256 return temp;
1257 break;
1258 case MENU_ATTACHED_USB:
1259 return RET_VAL_USB;
1260 break;
1263 return RET_VAL_OK;
1266 static const char* inventory_data(int selected_item, void * data,
1267 char * buffer, size_t buffer_len) {
1268 (void)data;
1269 switch(selected_item) {
1270 case 0:
1271 rb->snprintf(buffer,buffer_len,"Men: %d", humanres.men);
1272 break;
1273 case 1:
1274 rb->snprintf(buffer,buffer_len,"Tanks: %d", humanres.tanks);
1275 break;
1276 case 2:
1277 rb->snprintf(buffer,buffer_len,"Planes: %d", humanres.planes);
1278 break;
1279 case 3:
1280 rb->snprintf(buffer,buffer_len,"Factories: %d", humanres.inds);
1281 break;
1282 case 4:
1283 rb->snprintf(buffer,buffer_len,"Farms: %d", humanres.farms);
1284 break;
1285 case 5:
1286 rb->snprintf(buffer,buffer_len,"Nukes: %d", humanres.nukes);
1287 break;
1288 case 6:
1289 rb->snprintf(buffer,buffer_len,"Cash: %d", humanres.cash);
1290 break;
1291 case 7:
1292 rb->snprintf(buffer,buffer_len,"Food: %d", humanres.food);
1293 break;
1294 case 8:
1295 rb->snprintf(buffer,buffer_len,"Bank: %d", humanres.bank);
1296 break;
1297 default:
1298 return NULL;
1300 return buffer;
1303 int show_inventory(void) {
1304 struct simplelist_info info;
1305 rb->simplelist_info_init(&info, "Inventory", 9, NULL);
1306 info.hide_selection = true;
1307 info.get_name = inventory_data;
1308 if(rb->simplelist_show_list(&info)) {
1309 return RET_VAL_USB;
1310 } else {
1311 return RET_VAL_OK;
1315 int production_menu(void) {
1316 int selection = 0, temp;
1318 MENUITEM_STRINGLIST(menu, "Production", NULL,
1319 "Buy resources", "Show inventory", "Check map",
1320 "Invest money", "Withdraw money",
1321 "Finish turn", "Game menu");
1323 while(1) {
1324 switch(rb->do_menu(&menu, &selection, NULL, false)) {
1325 case 0:
1326 if(buy_resources_menu() == RET_VAL_USB)
1327 return RET_VAL_USB;
1328 break;
1329 case 1:
1330 if(show_inventory() == RET_VAL_USB)
1331 return RET_VAL_USB;
1332 break;
1333 case 2:
1334 if(select_square() == RET_VAL_USB)
1335 return RET_VAL_USB;
1336 break;
1337 case 3:
1338 temp = humanres.cash;
1339 if(get_number("How much do you want to invest?", &temp,
1340 humanres.cash) == RET_VAL_USB)
1341 return RET_VAL_USB;
1342 if(temp > humanres.cash) {
1343 rb->splash(HZ, "You don't have that much cash to invest");
1344 } else {
1345 humanres.cash -= temp;
1346 humanres.bank += temp;
1348 break;
1349 case 4:
1350 temp = humanres.bank;
1351 if(get_number("How much do you want to withdraw?", &temp,
1352 humanres.bank) == RET_VAL_USB)
1353 return RET_VAL_USB;
1354 if(temp > humanres.bank) {
1355 rb->splash(HZ, "You don't have that much cash to withdraw");
1356 } else {
1357 humanres.cash += temp;
1358 humanres.bank -= temp;
1360 break;
1361 case 5:
1362 return RET_VAL_OK;
1363 break;
1364 case 6:
1365 if((temp = ingame_menu()) != RET_VAL_OK)
1366 return temp;
1367 break;
1368 case MENU_ATTACHED_USB:
1369 return RET_VAL_USB;
1370 break;
1373 return RET_VAL_OK;
1376 void init_resources(void) {
1377 humanres.cash = superdom_settings.startcash;
1378 humanres.food = superdom_settings.startfood;
1379 humanres.tanks = 0;
1380 humanres.planes = 0;
1381 humanres.nukes = 0;
1382 humanres.inds = 0;
1383 humanres.farms = 0;
1384 humanres.men = 0;
1385 humanres.bank = 0;
1386 humanres.moves = 0;
1387 compres.cash = superdom_settings.startcash;
1388 compres.food = superdom_settings.startfood;
1389 compres.tanks = 0;
1390 compres.planes = 0;
1391 compres.nukes = 0;
1392 compres.inds = 0;
1393 compres.farms = 0;
1394 compres.men = 0;
1395 compres.bank = 0;
1396 compres.moves = 0;
1399 int select_square(void) {
1400 int button = 0;
1401 draw_board();
1402 draw_cursor();
1403 update_score();
1404 #if LCD_WIDTH >= 220
1405 rb->lcd_setfont(FONT_SYSFIXED);
1406 rb->snprintf(buf, sizeof(buf), "Cash: %d", humanres.cash);
1407 rb->lcd_putsxy(125, LCD_HEIGHT-20, buf);
1408 rb->snprintf(buf, sizeof(buf), "Food: %d", humanres.food);
1409 rb->lcd_putsxy(125, LCD_HEIGHT-10, buf);
1410 rb->lcd_setfont(FONT_UI);
1411 #endif
1412 rb->lcd_update();
1413 while(1) {
1414 button = rb->button_get(true);
1415 switch(button) {
1416 case SUPERDOM_CANCEL:
1417 rb->splash(HZ, "Cancelled");
1418 return RET_VAL_QUIT_ERR;
1419 break;
1420 case SUPERDOM_OK:
1421 return RET_VAL_OK;
1422 break;
1423 #if CONFIG_KEYPAD != IRIVER_H10_PAD
1424 case SUPERDOM_LEFT:
1425 case (SUPERDOM_LEFT|BUTTON_REPEAT):
1426 draw_cursor(); /* Deselect the current tile */
1427 if(cursor.x>1) {
1428 cursor.x--;
1429 } else {
1430 #ifdef IPOD_STYLE
1431 if(cursor.y>1)
1432 cursor.y--;
1433 else
1434 cursor.y = 10;
1435 #endif
1436 cursor.x = 10;
1438 update_score();
1439 draw_cursor();
1440 break;
1441 case SUPERDOM_RIGHT:
1442 case (SUPERDOM_RIGHT|BUTTON_REPEAT):
1443 draw_cursor(); /* Deselect the current tile */
1444 if(cursor.x<10) {
1445 cursor.x++;
1446 } else {
1447 #ifdef IPOD_STYLE
1448 if(cursor.y<10)
1449 cursor.y++;
1450 else
1451 cursor.y = 1;
1452 #endif
1453 cursor.x = 1;
1455 update_score();
1456 draw_cursor();
1457 break;
1458 #endif
1459 #ifndef IPOD_STYLE
1460 case SUPERDOM_UP:
1461 case (SUPERDOM_UP|BUTTON_REPEAT):
1462 draw_cursor(); /* Deselect the current tile */
1463 if(cursor.y>1) {
1464 cursor.y--;
1465 } else {
1466 #if CONFIG_KEYPAD == IRIVER_H10_PAD
1467 if(cursor.x > 1)
1468 cursor.x--;
1469 else
1470 cursor.x = 10;
1471 #endif
1472 cursor.y = 10;
1474 update_score();
1475 draw_cursor();
1476 break;
1477 case SUPERDOM_DOWN:
1478 case (SUPERDOM_DOWN|BUTTON_REPEAT):
1479 draw_cursor(); /* Deselect the current tile */
1480 if(cursor.y<10) {
1481 cursor.y++;
1482 } else {
1483 #if CONFIG_KEYPAD == IRIVER_H10_PAD
1484 if(cursor.x < 10)
1485 cursor.x++;
1486 else
1487 cursor.x = 1;
1488 #endif
1489 cursor.y = 1;
1491 update_score();
1492 draw_cursor();
1493 break;
1494 #endif
1495 default:
1496 if (rb->default_event_handler(button) == SYS_USB_CONNECTED)
1498 return RET_VAL_USB;
1504 int killmen(int colour) {
1505 bool human = (colour == COLOUR_LIGHT);
1506 int menkilled,i,j;
1507 int percent;
1508 if(human) {
1509 percent = (humanres.food*1000)/humanres.men;
1510 humanres.food = 0;
1511 } else {
1512 percent = (compres.food*1000)/compres.men;
1513 compres.food = 0;
1515 menkilled = 0;
1516 for(i=1;i<11;i++) {
1517 for(j=1;j<11;j++) {
1518 if(board[i][j].colour == colour) {
1519 int nummen = ((board[i][j].men * percent)/1000);
1520 menkilled += board[i][j].men - nummen;
1521 board[i][j].men = nummen;
1526 if(human)
1527 humanres.men -= menkilled;
1528 else
1529 compres.men -= menkilled;
1530 return menkilled;
1533 /* return -1 if error, 1 if attack is succeeded, 0 otherwise */
1534 int attack_territory(int colour, int x, int y) {
1535 bool human = (colour == COLOUR_LIGHT);
1536 int str_diff;
1538 if(board[x][y].colour == colour) {
1539 if(human)
1540 rb->splash(HZ, "You can't attack your own territory");
1541 return -1;
1543 str_diff = calc_strength(COLOUR_DARK, x, y) -
1544 calc_strength(COLOUR_LIGHT, x, y);
1545 if(human) {
1546 str_diff = -str_diff;
1548 rb->srand(*rb->current_tick);
1549 if(str_diff > 0 || (str_diff == 0 && rb->rand()%2)) {
1550 struct resources *offres, *defres;
1551 if(human) {
1552 offres = &humanres;
1553 defres = &compres;
1554 } else {
1555 offres = &compres;
1556 defres = &humanres;
1558 defres->men -= board[x][y].men;
1559 defres->tanks -= board[x][y].tank;
1560 defres->planes -= board[x][y].plane;
1561 defres->nukes -= board[x][y].nuke;
1562 defres->farms -= board[x][y].farm;
1563 defres->inds -= board[x][y].ind;
1564 offres->farms += board[x][y].farm;
1565 offres->inds += board[x][y].ind;
1566 board[x][y].colour = colour;
1567 board[x][y].men = 0;
1568 board[x][y].tank = false;
1569 board[x][y].plane = false;
1570 board[x][y].nuke = false;
1571 draw_board();
1572 if(human)
1573 rb->sleep(HZ*2);
1574 else
1575 rb->sleep(HZ);
1576 return 1;
1577 } else {
1578 if(human)
1579 rb->splash(HZ, "Your troops were unable to overcome"
1580 " the enemy troops");
1581 else
1582 rb->splash(HZ*2, "The computer attempted to "
1583 "attack, but the invasion was"
1584 " pushed back");
1585 return 0;
1587 return 0;
1590 int war_menu(void) {
1591 int selection = 0, temp;
1593 MENUITEM_STRINGLIST(menu, "War!", NULL,
1594 "Select territory to attack",
1595 "Finish turn", "Game menu");
1597 while(humanres.moves) {
1598 switch(rb->do_menu(&menu, &selection, NULL, false)) {
1599 case 0:
1600 switch(select_square()) {
1601 case RET_VAL_OK:
1602 if(attack_territory(COLOUR_LIGHT, cursor.x, cursor.y)
1603 >= 0)
1604 humanres.moves--;
1605 break;
1606 case RET_VAL_USB:
1607 return RET_VAL_USB;
1608 break;
1610 break;
1611 case 1:
1612 return RET_VAL_OK;
1613 break;
1614 case 2:
1615 if((temp = ingame_menu()) != RET_VAL_OK)
1616 return temp;
1617 break;
1620 return RET_VAL_OK;
1623 struct threat {
1624 int x;
1625 int y;
1626 int str_diff;
1629 bool place_adjacent(bool tank, int x, int y) {
1630 int type = (tank? 1: 2);
1631 if(!buy_resources(COLOUR_DARK, type, x, y, 0)) {
1632 return true;
1634 if(!buy_resources(COLOUR_DARK, type, x-1, y, 0)) {
1635 return true;
1637 if(!buy_resources(COLOUR_DARK, type, x+1, y, 0)) {
1638 return true;
1640 if(!buy_resources(COLOUR_DARK, type, x, y-1, 0)) {
1641 return true;
1643 if(!buy_resources(COLOUR_DARK, type, x, y+1, 0)) {
1644 return true;
1646 return false;
1649 bool has_adjacent(int x, int y) {
1650 if((board[x][y].colour == COLOUR_LIGHT) &&
1651 ((board[x-1][y].colour == COLOUR_DARK) ||
1652 (board[x+1][y].colour == COLOUR_DARK) ||
1653 (board[x][y+1].colour == COLOUR_DARK) ||
1654 (board[x][y-1].colour == COLOUR_DARK)))
1655 return 1;
1656 else
1657 return 0;
1660 void find_adjacent(int x, int y, int* adj_x, int* adj_y) {
1661 /* Finds adjacent squares, returning squares without tanks on them
1662 * in preference to those with them */
1663 if(board[x-1][y].colour == COLOUR_DARK) {
1664 *adj_x = x-1;
1665 *adj_y = y;
1666 return;
1668 if(board[x+1][y].colour == COLOUR_DARK) {
1669 *adj_x = x+1;
1670 *adj_y = y;
1671 return;
1673 if(board[x][y-1].colour == COLOUR_DARK) {
1674 *adj_x = x;
1675 *adj_y = y-1;
1676 return;
1678 if(board[x][y+1].colour == COLOUR_DARK) {
1679 *adj_x = x;
1680 *adj_y = y+1;
1681 return;
1685 void computer_allocate(void) {
1686 /* Firstly, decide whether to go offensive or defensive.
1687 * This is primarily decided by the human player posing a threat to either
1688 * the computer's farms or factories */
1689 int i, j, k;
1690 bool offensive = true;
1691 struct threat threats[4];
1692 int numthreats = 0;
1693 int total_str_diff = 0;
1694 int numterritory = 0;
1695 int str_diff;
1696 int men_needed;
1697 struct threat targets[2];
1698 int numtargets;
1699 struct cursor adj;
1701 compres.cash += compres.bank;
1702 compres.bank = 0;
1703 for(i=1;i<11;i++) {
1704 for(j=1;j<11;j++) {
1705 if(board[i][j].colour == COLOUR_DARK) {
1706 numterritory++;
1707 str_diff = calc_strength(COLOUR_LIGHT,i,j) -
1708 calc_strength(COLOUR_DARK,i,j);
1709 if(str_diff > 0 && (board[i][j].ind || board[i][j].farm)) {
1710 if(numthreats < 3) {
1711 offensive = false;
1712 threats[numthreats].x = i;
1713 threats[numthreats].y = j;
1714 threats[numthreats].str_diff = str_diff;
1715 numthreats++;
1719 rb->yield();
1722 if(offensive) {
1723 /* The AI is going to go straight for the throat here and attack
1724 * the player's farms and factories. The amount of cash
1725 * the AI has to spend will determine how many targets there are */
1726 if(compres.cash > 1200) {
1727 /* 1200 is a figure I pulled out of nowhere. Adjust as needed */
1728 numtargets = 2;
1729 } else {
1730 numtargets = 1;
1732 /* Work out which target(s) to attack. They must have adjacent squares
1733 * owned by the computer. If none are found just place troops in
1734 * random places around the map until we run out of money */
1735 k = 0;
1736 for(i=1;i<11;i++) {
1737 for(j=1;j<11;j++) {
1738 if(has_adjacent(i,j) &&
1739 (board[i][j].ind || board[i][j].farm)) {
1740 if(k<numtargets) {
1741 targets[k].x = i;
1742 targets[k].y = j;
1743 targets[k].str_diff =
1744 calc_strength(COLOUR_LIGHT, i, j) -
1745 calc_strength(COLOUR_DARK, i, j);
1746 k++;
1749 rb->yield();
1752 if(k == 0) {
1753 /* No targets found! Randomly pick squares and if they're owned
1754 * by the computer then stick a tank on it. */
1755 rb->srand(*rb->current_tick);
1756 while(compres.cash >= 300 && compres.tanks < numterritory) {
1757 i = rb->rand()%10 + 1;
1758 j = rb->rand()%10 + 1;
1759 if(board[i][j].colour == COLOUR_DARK) {
1760 buy_resources(COLOUR_DARK, 1, i, j, 0);
1762 rb->yield();
1764 } else {
1765 for(i=0;i<k;i++) {
1766 str_diff = targets[i].str_diff;
1767 while(str_diff + 20 > 0 && compres.cash > 0) {
1768 /* While we still need them keep placing men */
1769 if(!place_adjacent(true, targets[i].x, targets[i].y)) {
1770 find_adjacent(targets[i].x, targets[i].y,
1771 &adj.x, &adj.y);
1772 men_needed = (str_diff + 20)*1000/133;
1773 if(compres.cash < men_needed) {
1774 men_needed = compres.cash;
1776 buy_resources(COLOUR_DARK, 0, adj.x, adj.y,
1777 men_needed);
1778 break;
1780 str_diff = calc_strength(COLOUR_LIGHT,
1781 targets[i].x, targets[i].y) -
1782 calc_strength(COLOUR_DARK,
1783 targets[i].x, targets[i].y);
1787 } else {
1788 /* Work out what to place on each square to defend it.
1789 * Tanks are preferential because they do not require food,
1790 * but if the budget is tight then we fall back onto troops.
1791 * Conversely if cash is not an issue and there are already tanks in
1792 * place planes will be deployed. We would like a margin of at least
1793 * 20 points to be safe. */
1795 for(i=0;i<numthreats;i++) {
1796 total_str_diff += threats[i].str_diff;
1798 if((total_str_diff+20)*10 > compres.cash) {
1799 /* Not enough cash to accomodate all threats using tanks alone -
1800 * use men as a backup */
1801 for(i=0;i<numthreats;i++) {
1802 men_needed = ((threats[i].str_diff + 20)*1000)/133;
1803 if(compres.cash < men_needed) {
1804 men_needed = compres.cash;
1806 buy_resources(COLOUR_DARK, 0, threats[i].x, threats[i].y,
1807 men_needed);
1809 } else {
1810 /* Tanks it is */
1811 /* Enough money to pay their way by planes? */
1812 bool tank = ((total_str_diff+20)*15 >= compres.cash);
1813 for(i=0;i<numthreats;i++) {
1814 str_diff = threats[i].str_diff;
1815 while(str_diff + 20 > 0) {
1816 if(!place_adjacent(tank, threats[i].x, threats[i].y)) {
1817 /* No room for any more planes or tanks, revert to
1818 * men */
1819 find_adjacent(threats[i].x, threats[i].y,
1820 &adj.x, &adj.y);
1821 men_needed = (str_diff + 20)*1000/133;
1822 if(compres.cash < men_needed) {
1823 men_needed = compres.cash;
1825 buy_resources(COLOUR_DARK, 0, threats[i].x,
1826 threats[i].y, men_needed);
1827 break;
1829 str_diff = calc_strength(COLOUR_LIGHT,
1830 threats[i].x, threats[i].y) -
1831 calc_strength(COLOUR_DARK,
1832 threats[i].x, threats[i].y);
1837 compres.bank += compres.cash;
1838 compres.cash = 0;
1841 int find_adj_target(int x, int y, struct cursor* adj) {
1842 /* Find a square next to a computer's farm or factory owned by the player
1843 * that is vulnerable. Return 1 on success, 0 otherwise */
1844 if(board[x+1][y].colour == COLOUR_LIGHT &&
1845 calc_strength(COLOUR_LIGHT,x+1,y)<=calc_strength(COLOUR_DARK,x+1,y)) {
1846 adj->x = x+1;
1847 adj->y = y;
1848 return 1;
1850 if(board[x-1][y].colour == COLOUR_LIGHT &&
1851 calc_strength(COLOUR_LIGHT,x-1,y)<=calc_strength(COLOUR_DARK,x-1,y)) {
1852 adj->x = x-1;
1853 adj->y = y;
1854 return 1;
1856 if(board[x][y+1].colour == COLOUR_LIGHT &&
1857 calc_strength(COLOUR_LIGHT,x,y+1)<=calc_strength(COLOUR_DARK,x,y+1)) {
1858 adj->x = x;
1859 adj->y = y+1;
1860 return 1;
1862 if(board[x][y-1].colour == COLOUR_LIGHT &&
1863 calc_strength(COLOUR_LIGHT,x,y-1)<=calc_strength(COLOUR_DARK,x,y-1)) {
1864 adj->x = x;
1865 adj->y = y-1;
1866 return 1;
1868 return 0;
1871 void computer_war(void) {
1872 /* Work out where to attack - prioritise the defence of buildings */
1873 int i, j;
1874 bool found_target = true;
1875 struct cursor adj;
1877 while(found_target) {
1878 found_target = false;
1879 for(i=1;i<11;i++) {
1880 for(j=1;j<11;j++) {
1881 if((board[i][j].colour == COLOUR_DARK) &&
1882 (board[i][j].farm || board[i][j].ind) &&
1883 find_adj_target(i, j, &adj)) {
1884 found_target = true;
1885 if(attack_territory(COLOUR_DARK, adj.x, adj.y) >= 0) {
1886 compres.moves--;
1887 if(!compres.moves)
1888 return;
1891 rb->yield();
1895 /* Defence stage done, move on to OFFENCE */
1896 found_target = true;
1897 while(found_target) {
1898 found_target = false;
1899 for(i=1;i<11;i++) {
1900 for(j=1;j<11;j++) {
1901 if(board[i][j].colour == COLOUR_LIGHT &&
1902 (board[i][j].ind || board[i][j].farm) &&
1903 (calc_strength(COLOUR_DARK, i, j) >=
1904 calc_strength(COLOUR_LIGHT, i, j))) {
1905 found_target = true;
1906 if(attack_territory(COLOUR_DARK, i, j) >= 0) {
1907 compres.moves--;
1908 if(!compres.moves)
1909 return;
1912 rb->yield();
1916 /* Spend leftover moves wherever attacking randomly */
1917 found_target = true;
1918 while(found_target) {
1919 found_target = false;
1920 for(i=1;i<11;i++) {
1921 for(j=1;j<11;j++) {
1922 if(board[i][j].colour == COLOUR_LIGHT &&
1923 (calc_strength(COLOUR_DARK, i, j) >=
1924 calc_strength(COLOUR_LIGHT, i, j))) {
1925 found_target = true;
1926 if(attack_territory(COLOUR_DARK, i, j) >= 0) {
1927 compres.moves--;
1928 if(!compres.moves)
1929 return;
1932 rb->yield();
1938 static int load_game(const char* file) {
1939 int fd;
1941 fd = rb->open(file, O_RDONLY);
1942 if(fd < 0) {
1943 DEBUGF("Couldn't open savegame\n");
1944 return -1;
1946 rb->read(fd, buf, 5);
1947 if(rb->strcmp(buf, "SSGv3")) {
1948 rb->splash(HZ, "Invalid/incompatible savegame");
1949 return -1;
1951 rb->read(fd, &gamestate, sizeof(gamestate));
1952 rb->read(fd, &humanres.cash, sizeof(humanres.cash));
1953 rb->read(fd, &humanres.food, sizeof(humanres.food));
1954 rb->read(fd, &humanres.bank, sizeof(humanres.bank));
1955 rb->read(fd, &humanres.planes, sizeof(humanres.planes));
1956 rb->read(fd, &humanres.tanks, sizeof(humanres.tanks));
1957 rb->read(fd, &humanres.men, sizeof(humanres.men));
1958 rb->read(fd, &humanres.nukes, sizeof(humanres.nukes));
1959 rb->read(fd, &humanres.inds, sizeof(humanres.inds));
1960 rb->read(fd, &humanres.farms, sizeof(humanres.farms));
1961 rb->read(fd, &humanres.moves, sizeof(humanres.moves));
1962 rb->read(fd, &compres.cash, sizeof(humanres.cash));
1963 rb->read(fd, &compres.food, sizeof(humanres.food));
1964 rb->read(fd, &compres.bank, sizeof(humanres.bank));
1965 rb->read(fd, &compres.planes, sizeof(humanres.planes));
1966 rb->read(fd, &compres.tanks, sizeof(humanres.tanks));
1967 rb->read(fd, &compres.men, sizeof(humanres.men));
1968 rb->read(fd, &compres.nukes, sizeof(humanres.nukes));
1969 rb->read(fd, &compres.inds, sizeof(humanres.inds));
1970 rb->read(fd, &compres.farms, sizeof(humanres.farms));
1971 rb->read(fd, &compres.moves, sizeof(humanres.moves));
1972 rb->read(fd, board, sizeof(board));
1973 rb->read(fd, &superdom_settings.compstartfarms, sizeof(int));
1974 rb->read(fd, &superdom_settings.compstartinds, sizeof(int));
1975 rb->read(fd, &superdom_settings.humanstartfarms, sizeof(int));
1976 rb->read(fd, &superdom_settings.humanstartinds, sizeof(int));
1977 rb->read(fd, &superdom_settings.startcash, sizeof(int));
1978 rb->read(fd, &superdom_settings.startfood, sizeof(int));
1979 rb->read(fd, &superdom_settings.movesperturn, sizeof(int));
1980 rb->close(fd);
1981 return 0;
1984 void default_settings(void) {
1985 superdom_settings.compstartfarms = 1;
1986 superdom_settings.compstartinds = 1;
1987 superdom_settings.humanstartfarms = 2;
1988 superdom_settings.humanstartinds = 2;
1989 superdom_settings.startcash = 0;
1990 superdom_settings.startfood = 0;
1991 superdom_settings.movesperturn = 2;
1994 int average_strength(int colour) {
1995 /* This function calculates the average strength of the given player,
1996 * used to determine when the computer wins or loses. */
1997 int i,j;
1998 int totalpower = 0;
1999 for(i=1;i<11;i++) {
2000 for(j=1;j<11;j++) {
2001 if(board[i][j].colour != -1) {
2002 totalpower += calc_strength(colour, i, j);
2006 return totalpower/100;
2009 enum plugin_status plugin_start(const void* parameter)
2011 #if LCD_DEPTH > 1
2012 rb->lcd_set_backdrop(NULL);
2013 rb->lcd_set_foreground(LCD_BLACK);
2014 rb->lcd_set_background(LCD_WHITE);
2015 #endif
2017 cursor.x = 1;
2018 cursor.y = 1;
2019 default_settings();
2020 if(parameter) {
2021 if(load_game(parameter) != 0) {
2022 DEBUGF("Loading failed, generating new game\n");
2023 } else {
2024 switch(gamestate) {
2025 case GS_PROD:
2026 goto startprod;
2027 break;
2028 case GS_MOVE:
2029 goto startmove;
2030 break;
2031 case GS_WAR:
2032 goto startwar;
2033 break;
2034 default:
2035 goto startyear;
2036 break;
2041 switch(start_menu()) {
2042 case RET_VAL_OK: /* start playing */
2043 break;
2044 case RET_VAL_QUIT_ERR: /* quit */
2045 return PLUGIN_OK;
2046 break;
2047 case RET_VAL_USB:
2048 return PLUGIN_USB_CONNECTED;
2049 break;
2052 init_resources();
2053 init_board();
2054 gen_resources();
2055 startyear:
2056 while(1) {
2057 int avg_str_diff = (average_strength(COLOUR_LIGHT) -
2058 average_strength(COLOUR_DARK));
2059 if(avg_str_diff > 15) {
2060 rb->splash(HZ*4, "The computer has surrendered. You win.");
2061 return PLUGIN_OK;
2063 if(-avg_str_diff > 15) {
2064 rb->splash(HZ*4, "Your army have suffered terrible morale from"
2065 " the bleak prospects of winning. You lose.");
2066 return PLUGIN_OK;
2069 /* production */
2070 startprod:
2071 gamestate = GS_PROD;
2072 switch(production_menu()) {
2073 case RET_VAL_USB:
2074 return PLUGIN_USB_CONNECTED;
2075 break;
2076 case RET_VAL_QUIT_ERR:
2077 return PLUGIN_OK;
2078 break;
2080 computer_allocate();
2082 /* movement */
2083 humanres.moves = superdom_settings.movesperturn;
2084 startmove:
2085 gamestate = GS_MOVE;
2086 switch(movement_menu()) {
2087 case RET_VAL_USB:
2088 return PLUGIN_USB_CONNECTED;
2089 break;
2090 case RET_VAL_QUIT_ERR:
2091 return PLUGIN_OK;
2092 break;
2094 /* feed men */
2095 if(humanres.men) {
2096 if(humanres.food > humanres.men) {
2097 rb->snprintf(buf, sizeof(buf), "Your men ate %d units of food",
2098 humanres.men);
2099 humanres.food -= humanres.men;
2100 } else {
2101 rb->snprintf(buf, sizeof(buf), "There was not enough food"
2102 " to feed all your men, %d men have died of starvation",
2103 killmen(COLOUR_LIGHT));
2105 rb->splash(HZ*2, buf);
2107 if(compres.men) {
2108 if(compres.food > compres.men) {
2109 compres.food -= compres.men;
2110 } else {
2111 rb->snprintf(buf, sizeof(buf), "The computer does not have"
2112 " enough food to feed its men. %d have died of starvation",
2113 killmen(COLOUR_DARK));
2114 rb->splash(HZ, buf);
2117 /* war */
2118 humanres.moves = superdom_settings.movesperturn;
2119 startwar:
2120 gamestate = GS_WAR;
2121 switch(war_menu()) {
2122 case RET_VAL_USB:
2123 return PLUGIN_USB_CONNECTED;
2124 break;
2125 case RET_VAL_QUIT_ERR:
2126 return PLUGIN_OK;
2127 break;
2129 compres.moves = superdom_settings.movesperturn;
2130 computer_war();
2131 gen_resources();
2133 return PLUGIN_OK;