Add a png viewer plugin
[kugel-rb.git] / apps / plugins / superdom.c
blob3e1e23785a5cd8175694917dc39decd3ef161573
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 STRIDE BMPWIDTH_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 == COWOND2_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 == ONDAVX747_PAD) || (CONFIG_KEYPAD == MROBE500_PAD)
143 #define SUPERDOM_CANCEL BUTTON_POWER
145 #endif
147 #ifdef HAVE_TOUCHSCREEN
148 #ifndef SUPERDOM_OK
149 #define SUPERDOM_OK BUTTON_CENTER
150 #endif
151 #ifndef SUPERDOM_UP
152 #define SUPERDOM_UP BUTTON_TOPMIDDLE
153 #endif
154 #ifndef SUPERDOM_LEFT
155 #define SUPERDOM_LEFT BUTTON_MIDLEFT
156 #endif
157 #ifndef SUPERDOM_RIGHT
158 #define SUPERDOM_RIGHT BUTTON_MIDRIGHT
159 #endif
160 #ifndef SUPERDOM_DOWN
161 #define SUPERDOM_DOWN BUTTON_BOTTOMMIDDLE
162 #endif
163 #ifndef SUPERDOM_CANCEL
164 #define SUPERDOM_CANCEL BUTTON_TOPLEFT
165 #endif
166 #endif
168 #define SUPERDOM_QUIT 23
170 void gen_interest(void);
171 int production_menu(void);
172 void init_resources(void);
173 int select_square(void);
174 void update_score(void);
175 void gen_resources(void);
176 void draw_cursor(void);
177 int calc_strength(int colour, int x, int y);
178 void draw_board(void);
180 struct tile{
181 signed int colour; /* -1 = Unset */
182 bool tank;
183 bool plane;
184 bool nuke;
185 bool ind;
186 bool farm;
187 int men;
190 struct resources {
191 int cash;
192 int food;
193 int farms;
194 int inds;
195 int men;
196 int tanks;
197 int planes;
198 int nukes;
199 int bank;
200 int moves;
203 struct settings {
204 int compstartfarms;
205 int compstartinds;
206 int humanstartfarms;
207 int humanstartinds;
208 int startcash;
209 int startfood;
210 int movesperturn;
211 } superdom_settings;
213 struct resources humanres;
214 struct resources compres;
215 enum { GS_PROD, GS_MOVE, GS_WAR } gamestate;
217 struct cursor{
218 int x;
219 int y;
220 } cursor;
222 struct tile board[12][12];
224 void init_board(void) {
225 int i,j;
226 rb->srand(*rb->current_tick);
227 for(i=0;i<12;i++) { /* Hopefully about 50% each colour */
228 for(j=0;j<12;j++) {
229 if((i<1)||(j<1)||(i>10)||(j>10))
230 board[i][j].colour = -1; /* Unset */
231 else
232 board[i][j].colour = rb->rand()%2;
233 board[i][j].tank = false;
234 board[i][j].plane = false;
235 board[i][j].nuke = false;
236 board[i][j].ind = false;
237 board[i][j].farm = false;
238 board[i][j].men = 0;
242 while(compres.farms < superdom_settings.compstartfarms) {
243 i = rb->rand()%10 + 1;
244 j = rb->rand()%10 + 1;
245 if((board[i][j].colour == COLOUR_DARK) && (board[i][j].farm == false)) {
246 board[i][j].farm = true;
247 compres.farms++;
250 while(compres.inds < superdom_settings.compstartinds) {
251 i = rb->rand()%10 + 1;
252 j = rb->rand()%10 + 1;
253 if((board[i][j].colour == COLOUR_DARK) && (board[i][j].ind == false)) {
254 board[i][j].ind = true;
255 compres.inds++;
258 while(humanres.farms<superdom_settings.humanstartfarms) {
259 i = rb->rand()%10 + 1;
260 j = rb->rand()%10 + 1;
261 if((board[i][j].colour == COLOUR_LIGHT)&&(board[i][j].farm == false)) {
262 board[i][j].farm = true;
263 humanres.farms++;
266 while(humanres.inds<superdom_settings.humanstartfarms) {
267 i = rb->rand()%10 + 1;
268 j = rb->rand()%10 + 1;
269 if((board[i][j].colour == COLOUR_LIGHT) && (board[i][j].ind == false)) {
270 board[i][j].ind = true;
271 humanres.inds++;
276 void draw_board(void) {
277 int i,j;
278 rb->lcd_clear_display();
279 for(i=1;i<11;i++) {
280 for(j=1;j<11;j++) {
281 if(board[i][j].colour == COLOUR_DARK) {
282 rb->lcd_set_foreground(LCD_DARKGRAY);
283 } else {
284 rb->lcd_set_foreground(LCD_LIGHTGRAY);
286 rb->lcd_fillrect(MARGIN+(BOX_WIDTH*(i-1)),
287 MARGIN+(BOX_HEIGHT*(j-1)), BOX_WIDTH,
288 BOX_HEIGHT);
289 #if LCD_DEPTH != 16
290 rb->lcd_set_drawmode(DRMODE_BG | DRMODE_INVERSEVID);
291 #endif
292 if(board[i][j].ind) {
293 MY_BITMAP_PART(superdom_boarditems,
294 board[i][j].colour?ICON_WIDTH:0, 0, STRIDE,
295 #if LCD_WIDTH > LCD_HEIGHT
296 MARGIN+(BOX_WIDTH*(i-1))+1,
297 MARGIN+(BOX_HEIGHT*(j-1))+ICON_HEIGHT+1,
298 #else
299 MARGIN+(BOX_WIDTH*(i-1))+1+ICON_WIDTH,
300 MARGIN+(BOX_HEIGHT*(j-1))+1,
301 #endif
302 ICON_WIDTH, ICON_HEIGHT);
304 if(board[i][j].farm) {
305 MY_BITMAP_PART(superdom_boarditems,
306 board[i][j].colour?ICON_WIDTH:0, ICON_HEIGHT,
307 STRIDE, MARGIN+(BOX_WIDTH*(i-1))+1,
308 MARGIN+(BOX_HEIGHT*(j-1))+1,
309 ICON_WIDTH, ICON_HEIGHT);
311 if(board[i][j].tank) {
312 MY_BITMAP_PART(superdom_boarditems,
313 board[i][j].colour?ICON_WIDTH:0, ICON_HEIGHT*2,
314 STRIDE, MARGIN+(BOX_WIDTH*(i-1))+ICON_WIDTH+1,
315 MARGIN+(BOX_HEIGHT*(j-1))+ICON_HEIGHT+1,
316 ICON_WIDTH, ICON_HEIGHT);
318 if(board[i][j].men) {
319 MY_BITMAP_PART(superdom_boarditems,
320 board[i][j].colour?ICON_WIDTH:0, ICON_HEIGHT*3,
321 #if LCD_WIDTH > LCD_HEIGHT
322 STRIDE, MARGIN+(BOX_WIDTH*(i-1))+ICON_WIDTH+1,
323 MARGIN+(BOX_HEIGHT*(j-1))+1,
324 #else
325 STRIDE, MARGIN+(BOX_WIDTH*(i-1))+1,
326 MARGIN+(BOX_HEIGHT*(j-1))+1+ICON_HEIGHT,
327 #endif
328 ICON_WIDTH, ICON_HEIGHT);
330 if(board[i][j].plane) {
331 MY_BITMAP_PART(superdom_boarditems,
332 board[i][j].colour?ICON_WIDTH:0, ICON_HEIGHT*4,
333 #if LCD_WIDTH > LCD_HEIGHT
334 STRIDE,MARGIN+(BOX_WIDTH*(i-1))+ICON_WIDTH*2+1,
335 MARGIN+(BOX_HEIGHT*(j-1))+ICON_HEIGHT+1,
336 #else
337 STRIDE,MARGIN+(BOX_WIDTH*(i-1))+ICON_WIDTH+1,
338 MARGIN+(BOX_HEIGHT*(j-1))+ICON_HEIGHT*2+1,
339 #endif
340 ICON_WIDTH, ICON_HEIGHT);
342 if(board[i][j].nuke) {
343 MY_BITMAP_PART(superdom_boarditems,
344 board[i][j].colour?ICON_WIDTH:0, ICON_HEIGHT*5,
345 #if LCD_WIDTH > LCD_HEIGHT
346 STRIDE,MARGIN+(BOX_WIDTH*(i-1))+ICON_WIDTH*2+1,
347 MARGIN+(BOX_HEIGHT*(j-1))+1,
348 #else
349 STRIDE,MARGIN+(BOX_WIDTH*(i-1))+1,
350 MARGIN+(BOX_HEIGHT*(j-1))+ICON_HEIGHT*2+1,
351 #endif
352 ICON_WIDTH, ICON_HEIGHT);
354 #if LCD_DEPTH != 16
355 rb->lcd_set_drawmode(DRMODE_SOLID);
356 #endif
359 rb->lcd_set_foreground(LCD_BLACK);
360 for(i=0;i<=10;i++) { /* Draw Horizontal lines */
361 rb->lcd_hline(MARGIN, MARGIN+(BOX_WIDTH*10), MARGIN+(BOX_HEIGHT*i));
363 for(i=0;i<=10;i++) { /* Draw Vertical lines */
364 rb->lcd_vline(MARGIN+(BOX_WIDTH*i), MARGIN, MARGIN+(BOX_HEIGHT*10));
366 rb->lcd_update();
369 int calc_strength(int colour, int x, int y) {
370 int a, b, score=0;
371 for (a = -1; a < 2; a++) {
372 for (b = -1; b < 2; b++) {
373 if ((b == 0 || a == 0) &&
374 (board[x + a][y + b].colour == colour)) {
375 score += 10;
376 if(board[x + a][y + b].tank || board[x + a][y + b].farm)
377 score += 30;
378 if(board[x + a][y + b].plane || board[x + a][y + b].ind)
379 score += 40;
380 if(board[x + a][y + b].nuke)
381 score += 20;
382 if(board[x + a][y + b].men)
383 score += (board[x + a][y + b].men*133/1000);
387 return score;
390 void gen_interest(void) {
391 /* Interest should be around 10% */
392 rb->srand(*rb->current_tick);
393 int interest = 7+rb->rand()%6;
394 humanres.bank = humanres.bank+(interest*humanres.bank/100);
395 compres.bank = compres.bank+(interest*compres.bank/100);
398 void draw_cursor(void) {
399 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
400 rb->lcd_fillrect(MARGIN+((cursor.x-1)*BOX_WIDTH),
401 MARGIN+((cursor.y-1)*BOX_HEIGHT), BOX_WIDTH+1, BOX_HEIGHT+1);
402 rb->lcd_set_drawmode(DRMODE_SOLID);
403 rb->lcd_update();
406 void gen_resources(void) {
407 int inccash = 0;
408 int incfood = 0;
409 int ratecash = 0;
410 int ratefood = 0;
411 int i;
412 gen_interest();
413 rb->srand(*rb->current_tick);
414 /* Generate Human's resources */
415 for(i=0;i<humanres.inds;i++) {
416 inccash += (300+rb->rand()%200);
418 for(i=0;i<humanres.farms;i++) {
419 incfood += (200+rb->rand()%200);
421 if(humanres.inds)
422 ratecash = inccash/humanres.inds;
423 if(humanres.farms)
424 ratefood = incfood/humanres.farms;
425 if(ratecash > 450) {
426 if(ratefood > 350) {
427 rb->splash(HZ*2, "Patriotism sweeps the land, all production"
428 " is up this year!");
429 } else {
430 rb->splash(HZ*2, "Factories working at maximum efficiency,"
431 " cash production up this year!");
433 } else if(ratecash > 350) {
434 if(ratefood > 350) {
435 rb->splash(HZ*2, "Record crop harvest this year!");
436 } else if(ratefood > 250) {
437 rb->splash(HZ*2, "Production continues as normal");
438 } else {
439 rb->splash(HZ*2, "Spoilage of crops leads to reduced farm"
440 " output this year");
442 } else {
443 if(ratefood > 350) {
444 rb->splash(HZ*2, "Record crop harvest this year!");
445 } else if(ratefood > 250) {
446 rb->splash(HZ*2, "Factory unions introduced. Industrial"
447 " production is down this year.");
448 } else {
449 rb->splash(HZ*2, "Internet created. All production is down"
450 " due to time wasted.");
453 humanres.cash += inccash;
454 humanres.food += incfood;
456 /* Generate Computer's resources */
457 inccash = 0;
458 incfood = 0;
459 for(i=0;i<compres.inds;i++) {
460 inccash += (300+rb->rand()%200);
462 for(i=0;i<compres.farms;i++) {
463 incfood += (200+rb->rand()%200);
465 compres.cash += inccash;
466 compres.food += incfood;
469 void update_score(void) {
470 int strength;
471 rb->lcd_setfont(FONT_SYSFIXED);
472 rb->lcd_set_drawmode(DRMODE_BG|DRMODE_INVERSEVID);
473 rb->lcd_fillrect(5,LCD_HEIGHT-20,105,20);
474 rb->lcd_set_drawmode(DRMODE_SOLID);
475 strength = calc_strength(COLOUR_LIGHT, cursor.x, cursor.y);
476 rb->snprintf(buf, sizeof(buf), "Your power: %d.%d",
477 strength/10, strength%10);
478 rb->lcd_putsxy(5,LCD_HEIGHT-20, buf);
479 strength = calc_strength(COLOUR_DARK, cursor.x, cursor.y);
480 rb->snprintf(buf, sizeof(buf), "Comp power: %d.%d",
481 strength/10, strength%10);
482 rb->lcd_putsxy(5,LCD_HEIGHT-10, buf);
483 rb->lcd_setfont(FONT_UI);
486 int settings_menu_function(void) {
487 int selection = 0;
489 MENUITEM_STRINGLIST(settings_menu,"Super Domination Settings",NULL,
490 "Computer starting farms","Computer starting factories",
491 "Human starting farms","Human starting factories",
492 "Starting cash","Starting food","Moves per turn");
494 while(1) {
495 selection=rb->do_menu(&settings_menu,&selection, NULL, false);
496 switch(selection) {
497 case 0:
498 rb->set_int("Computer starting farms", "", UNIT_INT,
499 &superdom_settings.compstartfarms, NULL,
500 1, 0, 5, NULL);
501 break;
502 case 1:
503 rb->set_int("Computer starting factories", "", UNIT_INT,
504 &superdom_settings.compstartinds, NULL,
505 1, 0, 5, NULL);
506 break;
507 case 2:
508 rb->set_int("Human starting farms", "", UNIT_INT,
509 &superdom_settings.humanstartfarms, NULL,
510 1, 0, 5, NULL);
511 break;
512 case 3:
513 rb->set_int("Human starting factories", "", UNIT_INT,
514 &superdom_settings.humanstartinds, NULL,
515 1, 0, 5, NULL);
516 break;
517 case 4:
518 rb->set_int("Starting cash", "", UNIT_INT,
519 &superdom_settings.startcash, NULL,
520 250, 0, 5000, NULL);
521 break;
522 case 5:
523 rb->set_int("Starting food", "", UNIT_INT,
524 &superdom_settings.startfood, NULL,
525 250, 0, 5000, NULL);
526 break;
527 case 6:
528 rb->set_int("Moves per turn", "", UNIT_INT,
529 &superdom_settings.movesperturn, NULL,
530 1, 1, 5, NULL);
531 break;
532 case MENU_ATTACHED_USB:
533 return PLUGIN_USB_CONNECTED;
534 break;
535 case GO_TO_PREVIOUS:
536 return 0;
537 break;
540 return 0;
543 static int do_help(void) {
544 int button;
545 #define WORDS (sizeof help_text / sizeof (char*))
546 static char* help_text[] = {
547 "Super", "domination", "is", "a", "turn", "based", "strategy", "game,",
548 "where", "the", "aim", "is", "to", "overpower", "the", "computer",
549 "player", "by", "taking", "their", "territory.", "",
550 "Each", "year", "you", "are", "allocated", "an", "amount", "of", "cash",
551 "and", "food,", "depending", "on", "how", "many", "farms", "and",
552 "factories", "you", "control.", "",
553 "Use", "this", "cash", "and", "food", "to", "buy", "and", "feed", "your",
554 "army.", "Each", "tile", "has", "a", "strength,", "calculated", "by",
555 "the", "ownership", "of", "adjacent", "tiles,", "and", "the", "type",
556 "and", "number", "of", "troops", "on", "them.",
559 if (display_text(WORDS, help_text, NULL, NULL))
560 return PLUGIN_USB_CONNECTED;
561 do {
562 button = rb->button_get(true);
563 if ( rb->default_event_handler( button ) == SYS_USB_CONNECTED )
564 return PLUGIN_USB_CONNECTED;
565 } while( ( button == BUTTON_NONE )
566 || ( button & (BUTTON_REL|BUTTON_REPEAT) ) );
568 return PLUGIN_OK;
571 int menu(void) {
572 int selection = 0;
574 MENUITEM_STRINGLIST(main_menu,"Super Domination Menu",NULL,
575 "Play Super Domination","Settings","Help","Quit");
577 while(1) {
578 selection=rb->do_menu(&main_menu,&selection, NULL, false);
579 switch(selection) {
580 case 0:
581 return 0; /* start playing */
582 break;
583 case 1:
584 if(settings_menu_function()==PLUGIN_USB_CONNECTED)
585 return PLUGIN_USB_CONNECTED;
586 break;
587 case 2:
588 if(do_help()==PLUGIN_USB_CONNECTED)
589 return PLUGIN_USB_CONNECTED;
590 break;
591 default:
592 return 2; /* quit program */
593 break;
597 return 3;
600 int save_game(void) {
601 int fd;
602 char savepath[MAX_PATH];
604 rb->snprintf(savepath, sizeof(savepath), "/Savegame.ssg");
605 if(rb->kbd_input(savepath, MAX_PATH)) {
606 DEBUGF("Keyboard input failed\n");
607 return -1;
610 fd = rb->open(savepath, O_WRONLY|O_CREAT);
611 DEBUGF("savepath: %s\n", savepath);
612 if(fd < 0) {
613 DEBUGF("Couldn't create/open file\n");
614 return -1;
617 rb->write(fd, "SSGv3", 5);
618 rb->write(fd, &gamestate, sizeof(gamestate));
619 rb->write(fd, &humanres.cash, sizeof(humanres.cash));
620 rb->write(fd, &humanres.food, sizeof(humanres.food));
621 rb->write(fd, &humanres.bank, sizeof(humanres.bank));
622 rb->write(fd, &humanres.planes, sizeof(humanres.planes));
623 rb->write(fd, &humanres.tanks, sizeof(humanres.tanks));
624 rb->write(fd, &humanres.men, sizeof(humanres.men));
625 rb->write(fd, &humanres.nukes, sizeof(humanres.nukes));
626 rb->write(fd, &humanres.inds, sizeof(humanres.inds));
627 rb->write(fd, &humanres.farms, sizeof(humanres.farms));
628 rb->write(fd, &humanres.moves, sizeof(humanres.moves));
629 rb->write(fd, &compres.cash, sizeof(compres.cash));
630 rb->write(fd, &compres.food, sizeof(compres.food));
631 rb->write(fd, &compres.bank, sizeof(compres.bank));
632 rb->write(fd, &compres.planes, sizeof(compres.planes));
633 rb->write(fd, &compres.tanks, sizeof(compres.tanks));
634 rb->write(fd, &compres.men, sizeof(compres.men));
635 rb->write(fd, &compres.nukes, sizeof(compres.nukes));
636 rb->write(fd, &compres.inds, sizeof(compres.inds));
637 rb->write(fd, &compres.farms, sizeof(compres.farms));
638 rb->write(fd, &compres.moves, sizeof(compres.moves));
639 rb->write(fd, board, sizeof(board));
640 rb->write(fd, &superdom_settings.compstartfarms, sizeof(int));
641 rb->write(fd, &superdom_settings.compstartinds, sizeof(int));
642 rb->write(fd, &superdom_settings.humanstartfarms, sizeof(int));
643 rb->write(fd, &superdom_settings.humanstartfarms, sizeof(int));
644 rb->write(fd, &superdom_settings.startcash, sizeof(int));
645 rb->write(fd, &superdom_settings.startfood, sizeof(int));
646 rb->write(fd, &superdom_settings.movesperturn, sizeof(int));
647 rb->close(fd);
648 return 0;
651 int ingame_menu(void) {
652 int selection = 0;
654 MENUITEM_STRINGLIST(ingame_menu,"Super Domination Menu",NULL,
655 "Return to game","Save Game","Playback Control", "Quit");
657 selection=rb->do_menu(&ingame_menu,&selection, NULL, false);
658 switch(selection) {
659 case 0:
660 return 0;
661 break;
662 case 1:
663 if(!save_game())
664 rb->splash(HZ, "Game saved");
665 else
666 rb->splash(HZ, "Error in save");
667 break;
668 case 2:
669 playback_control(NULL);
670 break;
671 case 3:
672 return SUPERDOM_QUIT;
673 break;
674 case MENU_ATTACHED_USB:
675 return PLUGIN_USB_CONNECTED;
676 break;
677 case GO_TO_PREVIOUS:
678 return 0;
679 break;
681 return 0;
684 int get_number(char* param, int* value) {
685 //int numbers[3][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
686 int numbers[3][3];
687 int i,j,x=0,y=0;
688 int height, width;
689 int button = 0;
690 numbers[0][0] = 1;
691 numbers[0][1] = 2;
692 numbers[0][2] = 3;
693 numbers[1][0] = 4;
694 numbers[1][1] = 5;
695 numbers[1][2] = 6;
696 numbers[2][0] = 7;
697 numbers[2][1] = 8;
698 numbers[2][2] = 9;
699 rb->lcd_clear_display();
700 /* Draw a 3x4 grid */
701 for(i=0;i<=3;i++) { /* Vertical lines */
702 rb->lcd_vline(NUM_MARGIN_X+(NUM_BOX_WIDTH*i), NUM_MARGIN_Y,
703 NUM_MARGIN_Y+(4*NUM_BOX_HEIGHT));
705 for(i=0;i<=4;i++) { /* Horizontal lines */
706 rb->lcd_hline(NUM_MARGIN_X, NUM_MARGIN_X+(3*NUM_BOX_WIDTH),
707 NUM_MARGIN_Y+(NUM_BOX_HEIGHT*i));
709 for(i=0;i<3;i++) {
710 for(j=0;j<3;j++) {
711 rb->snprintf(buf, sizeof(buf), "%d", numbers[i][j]);
712 rb->lcd_putsxy(NUM_MARGIN_X+(j*NUM_BOX_WIDTH)+10,
713 NUM_MARGIN_Y+(i*NUM_BOX_HEIGHT)+8, buf);
716 rb->lcd_putsxy(NUM_MARGIN_X+5, NUM_MARGIN_Y+(3*NUM_BOX_HEIGHT)+8, "CLR");
717 rb->lcd_putsxy(NUM_MARGIN_X+NUM_BOX_WIDTH+10,
718 NUM_MARGIN_Y+(3*NUM_BOX_HEIGHT)+8, "0");
719 rb->lcd_putsxy(NUM_MARGIN_X+2*NUM_BOX_WIDTH+8,
720 NUM_MARGIN_Y+(3*NUM_BOX_HEIGHT)+8, "OK");
721 rb->snprintf(buf,sizeof(buf), "%d", *value);
722 rb->lcd_putsxy(NUM_MARGIN_X+10, NUM_MARGIN_Y+4*NUM_BOX_HEIGHT+10, buf);
723 rb->lcd_getstringsize(param, &width, &height);
724 rb->lcd_putsxy((LCD_WIDTH-width)/2, (NUM_MARGIN_Y-height)/2, param);
725 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
726 rb->lcd_fillrect(NUM_MARGIN_X+(NUM_BOX_WIDTH*x),
727 NUM_MARGIN_Y+(NUM_BOX_HEIGHT*y), NUM_BOX_WIDTH+1,
728 NUM_BOX_HEIGHT+1);
729 rb->lcd_set_drawmode(DRMODE_SOLID);
730 rb->lcd_update();
731 while(1) {
732 button = rb->button_get(true);
733 switch(button) {
734 case SUPERDOM_OK:
735 if(y!=3) {
736 *value *= 10;
737 *value += numbers[y][x];
738 } else if(x==0) {
739 *value /= 10;
740 } else if(x==1) {
741 *value *= 10;
742 } else if(x==2) {
743 return 0;
745 rb->lcd_set_drawmode(DRMODE_BG|DRMODE_INVERSEVID);
746 rb->lcd_fillrect(0, NUM_MARGIN_Y+4*NUM_BOX_HEIGHT+10,
747 LCD_WIDTH, 30);
748 rb->lcd_set_drawmode(DRMODE_SOLID);
749 rb->snprintf(buf,sizeof(buf), "%d", *value);
750 rb->lcd_putsxy(NUM_MARGIN_X+10,
751 NUM_MARGIN_Y+4*NUM_BOX_HEIGHT+10, buf);
752 break;
753 case SUPERDOM_CANCEL:
754 *value = 0;
755 rb->splash(HZ, "Cancelled");
756 return 2;
757 break;
758 #if CONFIG_KEYPAD != IRIVER_H10_PAD
759 case SUPERDOM_LEFT:
760 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
761 rb->lcd_fillrect(NUM_MARGIN_X+(NUM_BOX_WIDTH*x),
762 NUM_MARGIN_Y+(NUM_BOX_HEIGHT*y),
763 NUM_BOX_WIDTH+1, NUM_BOX_HEIGHT+1);
764 rb->lcd_set_drawmode(DRMODE_SOLID);
765 if(x==0) {
766 #ifdef IPOD_STYLE
767 if(y>0)
768 y--;
769 else
770 y=3;
771 #endif
772 x=2;
773 } else {
774 x--;
776 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
777 rb->lcd_fillrect(NUM_MARGIN_X+(NUM_BOX_WIDTH*x),
778 NUM_MARGIN_Y+(NUM_BOX_HEIGHT*y),
779 NUM_BOX_WIDTH+1, NUM_BOX_HEIGHT+1);
780 rb->lcd_set_drawmode(DRMODE_SOLID);
781 break;
782 case SUPERDOM_RIGHT:
783 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
784 rb->lcd_fillrect(NUM_MARGIN_X+(NUM_BOX_WIDTH*x),
785 NUM_MARGIN_Y+(NUM_BOX_HEIGHT*y),
786 NUM_BOX_WIDTH+1, NUM_BOX_HEIGHT+1);
787 rb->lcd_set_drawmode(DRMODE_SOLID);
788 if(x==2) {
789 #ifdef IPOD_STYLE
790 if(y==3)
791 y=0;
792 else
793 y++;
794 #endif
795 x=0;
796 } else {
797 x++;
799 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
800 rb->lcd_fillrect(NUM_MARGIN_X+(NUM_BOX_WIDTH*x),
801 NUM_MARGIN_Y+(NUM_BOX_HEIGHT*y),
802 NUM_BOX_WIDTH+1, NUM_BOX_HEIGHT+1);
803 rb->lcd_set_drawmode(DRMODE_SOLID);
804 break;
805 #endif
806 #ifndef IPOD_STYLE
807 case SUPERDOM_UP:
808 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
809 rb->lcd_fillrect(NUM_MARGIN_X+(NUM_BOX_WIDTH*x),
810 NUM_MARGIN_Y+(NUM_BOX_HEIGHT*y),
811 NUM_BOX_WIDTH+1, NUM_BOX_HEIGHT+1);
812 rb->lcd_set_drawmode(DRMODE_SOLID);
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 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
825 rb->lcd_fillrect(NUM_MARGIN_X+(NUM_BOX_WIDTH*x),
826 NUM_MARGIN_Y+(NUM_BOX_HEIGHT*y),
827 NUM_BOX_WIDTH+1, NUM_BOX_HEIGHT+1);
828 rb->lcd_set_drawmode(DRMODE_SOLID);
829 break;
830 case SUPERDOM_DOWN:
831 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
832 rb->lcd_fillrect(NUM_MARGIN_X+(NUM_BOX_WIDTH*x),
833 NUM_MARGIN_Y+(NUM_BOX_HEIGHT*y),
834 NUM_BOX_WIDTH+1, NUM_BOX_HEIGHT+1);
835 rb->lcd_set_drawmode(DRMODE_SOLID);
836 if(y==3) {
837 #if CONFIG_KEYPAD == IRIVER_H10_PAD
838 if(x < 2)
839 x++;
840 else
841 x=0;
842 #endif
843 y=0;
844 } else {
845 y++;
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 break;
853 #endif
854 default:
855 if (rb->default_event_handler(button) == SYS_USB_CONNECTED)
857 return PLUGIN_USB_CONNECTED;
859 break;
861 rb->lcd_update();
863 return 0;
866 bool tile_has_item(int type, int x, int y) {
867 switch(type) {
868 case 0:
869 return (board[x][y].men > 0);
870 break;
871 case 1:
872 return board[x][y].tank;
873 break;
874 case 2:
875 return board[x][y].plane;
876 break;
877 case 3:
878 return board[x][y].farm;
879 break;
880 case 4:
881 return board[x][y].ind;
882 break;
883 case 5:
884 return board[x][y].nuke;
885 break;
887 return false;
890 int buy_resources(int colour, int type, int x, int y, int nummen) {
891 const char *itemnames[][6] = {
893 "them",
894 "the tank",
895 "the plane",
896 "the farm",
897 "the industrial plant",
898 "the nuke",
899 }, {
900 "place men",
901 "place a tank",
902 "place a plane",
903 "build a farm",
904 "build an industrial plant",
905 "place a nuke",
906 }, {
907 NULL,
908 "a tank",
909 "a plane",
910 "a farm",
911 "an industrial plant",
912 "a nuke",
916 bool human = (colour == COLOUR_LIGHT);
917 int price = 0;
918 struct resources *res;
920 if(human) {
921 res = &humanres;
922 } else {
923 res = &compres;
925 switch(type) {
926 case 0: /* men */
927 price = 1*nummen;
928 break;
929 case 1: /* tank */
930 price = 300;
931 break;
932 case 2: /* plane */
933 price = 600;
934 break;
935 case 3: /* Farm */
936 price = 1150;
937 break;
938 case 4: /* Factory */
939 price = 1300;
940 break;
941 case 5: /* nuke */
942 price = 2000;
943 break;
945 if(res->cash < price) {
946 if(human)
947 rb->splash(HZ, "Not enough money!");
948 return 2;
950 if(human) {
951 rb->splashf(HZ, "Where do you want to place %s?", itemnames[0][type]);
952 switch(select_square()) {
953 case 2:
954 return 2;
955 break;
956 case PLUGIN_USB_CONNECTED:
957 return PLUGIN_USB_CONNECTED;
958 break;
960 x = cursor.x;
961 y = cursor.y;
963 if(board[x][y].colour != colour) {
964 if(human)
965 rb->splashf(HZ, "Can't %s on enemy territory", itemnames[1][type]);
966 return 2;
968 if(type != 0 && tile_has_item(type, x, y)) {
969 if(human)
970 rb->splashf(HZ, "There is already %s there", itemnames[2][type]);
971 return 2;
973 switch(type) {
974 case 0:
975 board[x][y].men += nummen;
976 res->men += nummen;
977 break;
978 case 1:
979 board[x][y].tank = true;
980 res->tanks++;
981 break;
982 case 2:
983 board[x][y].plane = true;
984 res->planes++;
985 break;
986 case 3:
987 board[x][y].farm = true;
988 res->farms++;
989 break;
990 case 4:
991 board[x][y].ind = true;
992 res->inds++;
993 break;
994 case 5:
995 board[x][y].nuke = true;
996 res->nukes++;
997 break;
999 res->cash -= price;
1001 draw_board();
1002 rb->sleep(HZ);
1004 return 0;
1007 int buy_resources_menu(void) {
1008 int selection,nummen;
1010 MENUITEM_STRINGLIST(res_menu, "Buy Resources", NULL, "Buy men ($1)",
1011 "Buy tank ($300)", "Buy plane ($600)", "Buy Farm ($1150)",
1012 "Buy Factory ($1300)", "Buy Nuke ($2000)",
1013 "Finish buying");
1015 while(1) {
1016 selection=rb->do_menu(&res_menu,&selection, NULL, false);
1017 switch(selection) {
1018 case 0:
1019 nummen = 0;
1020 if(get_number("How many men would you like?", &nummen)
1021 == PLUGIN_USB_CONNECTED)
1022 return PLUGIN_USB_CONNECTED;
1023 if(!nummen)
1024 break;
1025 /* fall through */
1026 case 1:
1027 case 2:
1028 case 3:
1029 case 4:
1030 case 5:
1031 if(buy_resources(COLOUR_LIGHT, selection, 0, 0, nummen)
1032 == PLUGIN_USB_CONNECTED)
1033 return PLUGIN_USB_CONNECTED;
1034 break;
1035 case 6:
1036 return 0;
1037 break;
1038 case MENU_ATTACHED_USB:
1039 return PLUGIN_USB_CONNECTED;
1040 break;
1041 case GO_TO_PREVIOUS:
1042 return 0;
1043 break;
1046 return 0;
1049 int move_unit(int colour, int type, int fromx, int fromy,
1050 int tox, int toy, int nummen) {
1051 const char *itemnames[][3] = {
1053 "troops",
1054 "the tank",
1055 "the plane",
1056 }, {
1057 "any troops",
1058 "a tank",
1059 "a plane",
1060 }, {
1061 "the troops",
1062 "the tank",
1063 "the plane",
1066 bool human = (colour == COLOUR_LIGHT);
1068 if(human) {
1069 rb->splashf(HZ, "Select where you want to move %s from",
1070 itemnames[0][type]);
1071 switch(select_square()) {
1072 case 2:
1073 return 2;
1074 break;
1075 case PLUGIN_USB_CONNECTED:
1076 return PLUGIN_USB_CONNECTED;
1077 break;
1079 fromx = cursor.x;
1080 fromy = cursor.y;
1082 if(board[fromx][fromy].colour != colour) {
1083 if(human)
1084 rb->splash(HZ, "That isn't your territory");
1085 return 2;
1087 if(!tile_has_item(type, fromx, fromy)) {
1088 if(human)
1089 rb->splashf(HZ, "You don't have %s there", itemnames[1][type]);
1090 return 2;
1092 if(type == 0) {
1093 if(human) {
1094 nummen = board[fromx][fromy].men;
1095 switch(get_number("How many men do you want to move?", &nummen)) {
1096 case 2:
1097 return 2;
1098 break;
1099 case PLUGIN_USB_CONNECTED:
1100 return PLUGIN_USB_CONNECTED;
1101 break;
1104 if(nummen > board[fromx][fromy].men) {
1105 if(human)
1106 rb->splash(HZ, "You don't have that many troops.");
1107 return 2;
1110 if(human) {
1111 rb->splashf(HZ, "Select where you want to move %s to",
1112 itemnames[2][type]);
1113 switch(select_square()) {
1114 case 2:
1115 return 2;
1116 break;
1117 case PLUGIN_USB_CONNECTED:
1118 return PLUGIN_USB_CONNECTED;
1119 break;
1121 tox = cursor.x;
1122 toy = cursor.y;
1124 if((tox == fromx && toy == fromy) ||
1125 board[tox][toy].colour != colour ||
1126 (type != 2 && (abs(tox - fromx) > 1 || abs(toy - fromy) > 1))) {
1127 if(human)
1128 rb->splash(HZ, "Invalid move");
1129 return 2;
1131 if(type != 0 && tile_has_item(type, tox, toy)) {
1132 if(human)
1133 rb->splashf(HZ, "There is already %s there", itemnames[1][type]);
1134 return 2;
1136 switch(type) {
1137 case 0:
1138 board[fromx][fromy].men -= nummen;
1139 board[tox][toy].men += nummen;
1140 break;
1141 case 1:
1142 board[fromx][fromy].tank = false;
1143 board[tox][toy].tank = true;
1144 break;
1145 case 2:
1146 board[fromx][fromy].plane = false;
1147 board[tox][toy].plane = true;
1148 break;
1150 return 0;
1153 int move_unit_menu(void) {
1154 int selection;
1156 MENUITEM_STRINGLIST(move_unit_menu, "Move unit", NULL, "Move men",
1157 "Move tank", "Move plane");
1158 selection=rb->do_menu(&move_unit_menu,&selection, NULL, false);
1159 switch(selection) {
1160 case 0:
1161 case 1:
1162 case 2:
1163 switch(move_unit(COLOUR_LIGHT, selection, 0, 0, 0, 0, 0)) {
1164 case 0:
1165 humanres.moves--;
1166 break;
1167 case PLUGIN_USB_CONNECTED:
1168 return PLUGIN_USB_CONNECTED;
1169 break;
1171 break;
1172 case MENU_ATTACHED_USB:
1173 return PLUGIN_USB_CONNECTED;
1175 return 0;
1178 int launch_nuke(int colour, int nukex, int nukey, int targetx, int targety) {
1179 bool human = (colour == COLOUR_LIGHT);
1180 struct resources *res;
1182 if(board[nukex][nukey].colour != colour) {
1183 if(human)
1184 rb->splash(HZ, "That isn't your territory");
1185 return 2;
1187 if(! board[nukex][nukey].nuke) {
1188 if(human)
1189 rb->splashf(HZ, "You don't have %s there", "a nuke");
1190 return 2;
1192 if(human) {
1193 rb->splash(HZ, "Select place to target with nuke");
1194 switch(select_square()) {
1195 case 2:
1196 return 2;
1197 break;
1198 case PLUGIN_USB_CONNECTED:
1199 return PLUGIN_USB_CONNECTED;
1200 break;
1202 targetx = cursor.x;
1203 targety = cursor.y;
1205 if(human) {
1206 humanres.nukes--;
1207 } else {
1208 compres.nukes--;
1210 board[nukex][nukey].nuke = false;
1212 if(board[targetx][targety].colour == COLOUR_LIGHT) {
1213 res = &humanres;
1214 } else {
1215 res = &compres;
1217 res->men -= board[targetx][targety].men;
1218 res->tanks -= board[targetx][targety].tank;
1219 res->planes -= board[targetx][targety].plane;
1220 res->nukes -= board[targetx][targety].nuke;
1221 res->farms -= board[targetx][targety].farm;
1222 res->inds -= board[targetx][targety].ind;
1223 board[targetx][targety].men = 0;
1224 board[targetx][targety].tank = false;
1225 board[targetx][targety].plane = false;
1226 board[targetx][targety].ind = false;
1227 board[targetx][targety].nuke = false;
1228 board[targetx][targety].farm = false;
1229 /* TODO: Fallout carried by wind */
1231 return 0;
1234 int movement_menu(void) {
1235 int selection, tempmenu;
1237 MENUITEM_STRINGLIST(move_menu, "Movement", NULL, "Move unit",
1238 "Buy additional moves ($100)", "Launch nuclear missile",
1239 "Check map", "Finish moving", "Game menu");
1241 while(1) {
1242 selection=rb->do_menu(&move_menu,&selection, NULL, false);
1243 switch(selection) {
1244 case 0:
1245 if(humanres.moves) {
1246 if(move_unit_menu()==PLUGIN_USB_CONNECTED)
1247 return PLUGIN_USB_CONNECTED;
1248 } else {
1249 rb->splash(HZ, "You have no more moves left."
1250 " You can buy more for $100 each.");
1252 break;
1253 case 1:
1254 if(humanres.cash > 100) {
1255 humanres.moves++;
1256 humanres.cash -= 100;
1257 rb->snprintf(buf, sizeof(buf), "You now have %d moves",
1258 humanres.moves);
1259 rb->splash(HZ, buf);
1261 break;
1262 case 2:
1263 if(humanres.nukes==0) {
1264 rb->splash(HZ, "You do not have any nukes to launch");
1265 } else {
1266 rb->splash(HZ, "Select place to launch nuke from");
1267 switch(select_square()) {
1268 case 0:
1269 if(launch_nuke(COLOUR_LIGHT, cursor.x, cursor.y,
1270 0, 0) == PLUGIN_USB_CONNECTED)
1271 return PLUGIN_USB_CONNECTED;
1272 break;
1273 case PLUGIN_USB_CONNECTED:
1274 return PLUGIN_USB_CONNECTED;
1275 break;
1278 break;
1279 case 3:
1280 if(select_square() == PLUGIN_USB_CONNECTED)
1281 return PLUGIN_USB_CONNECTED;
1282 break;
1283 case 4:
1284 return 0;
1285 break;
1286 case 5:
1287 tempmenu = ingame_menu();
1288 switch(tempmenu) {
1289 case PLUGIN_USB_CONNECTED:
1290 return PLUGIN_USB_CONNECTED;
1291 break;
1292 case SUPERDOM_QUIT:
1293 return SUPERDOM_QUIT;
1294 break;
1296 break;
1297 case MENU_ATTACHED_USB:
1298 return PLUGIN_USB_CONNECTED;
1299 break;
1302 return 0;
1305 int show_inventory(void) {
1306 char men[20], tanks[20], planes[20], inds[20], farms[20], nukes[20],
1307 cash[20], food[20], bank[20];
1308 rb->snprintf(men, sizeof(men), "Men: %d", humanres.men);
1309 rb->snprintf(tanks, sizeof(tanks), "Tanks: %d", humanres.tanks);
1310 rb->snprintf(planes, sizeof(planes), "Planes: %d", humanres.planes);
1311 rb->snprintf(inds, sizeof(inds), "Factories: %d", humanres.inds);
1312 rb->snprintf(farms, sizeof(farms), "Farms: %d", humanres.farms);
1313 rb->snprintf(nukes, sizeof(nukes), "Nukes: %d", humanres.nukes);
1314 rb->snprintf(cash, sizeof(cash), "Cash: %d", humanres.cash);
1315 rb->snprintf(food, sizeof(food), "Food: %d", humanres.food);
1316 rb->snprintf(bank, sizeof(bank), "Bank: %d", humanres.bank);
1317 rb->lcd_clear_display();
1318 rb->lcd_puts(1, 0, "Inventory");
1319 rb->lcd_puts(2, 1, men);
1320 rb->lcd_puts(2, 2, tanks);
1321 rb->lcd_puts(2, 3, planes);
1322 rb->lcd_puts(2, 4, inds);
1323 rb->lcd_puts(2, 5, farms);
1324 rb->lcd_puts(2, 6, nukes);
1325 rb->lcd_puts(2, 7, cash);
1326 rb->lcd_puts(2, 8, food);
1327 rb->lcd_puts(2, 9, bank);
1328 rb->lcd_update();
1329 if(rb->default_event_handler(rb->button_get(true)) == SYS_USB_CONNECTED) {
1330 return PLUGIN_USB_CONNECTED;
1331 } else {
1332 return 0;
1336 int production_menu(void) {
1337 int selection, tempbank, tempmenu;
1339 MENUITEM_STRINGLIST(prod_menu, "Production", NULL, "Buy resources",
1340 "Show inventory", "Check map", "Invest money",
1341 "Withdraw money", "Finish turn", "Game menu");
1343 while(1) {
1344 selection=rb->do_menu(&prod_menu,&selection, NULL, false);
1345 switch(selection) {
1346 case 0:
1347 if(buy_resources_menu() == PLUGIN_USB_CONNECTED)
1348 return PLUGIN_USB_CONNECTED;
1349 break;
1350 case 1:
1351 if(show_inventory() == PLUGIN_USB_CONNECTED)
1352 return PLUGIN_USB_CONNECTED;
1353 break;
1354 case 2:
1355 if(select_square() == PLUGIN_USB_CONNECTED)
1356 return PLUGIN_USB_CONNECTED;
1357 break;
1358 case 3:
1359 tempbank = humanres.cash;
1360 if(get_number("How much do you want to invest?", &tempbank)
1361 == PLUGIN_USB_CONNECTED)
1362 return PLUGIN_USB_CONNECTED;
1363 if(tempbank>humanres.cash) {
1364 rb->splash(HZ, "You don't have that much cash to invest");
1365 } else {
1366 humanres.cash -= tempbank;
1367 humanres.bank += tempbank;
1369 break;
1370 case 4:
1371 tempbank = 0;
1372 if(get_number("How much do you want to withdraw?", &tempbank)
1373 == PLUGIN_USB_CONNECTED)
1374 return PLUGIN_USB_CONNECTED;
1375 if(tempbank>humanres.bank) {
1376 rb->splash(HZ, "You don't have that much cash to withdraw");
1377 } else {
1378 humanres.cash += tempbank;
1379 humanres.bank -= tempbank;
1381 break;
1382 case 5:
1383 return 0;
1384 break;
1385 case 6:
1386 tempmenu = ingame_menu();
1387 switch(tempmenu) {
1388 case PLUGIN_USB_CONNECTED:
1389 return PLUGIN_USB_CONNECTED;
1390 break;
1391 case SUPERDOM_QUIT:
1392 return SUPERDOM_QUIT;
1393 break;
1395 break;
1396 case MENU_ATTACHED_USB:
1397 return PLUGIN_USB_CONNECTED;
1398 break;
1401 return 0;
1404 void init_resources(void) {
1405 humanres.cash = superdom_settings.startcash;
1406 humanres.food = superdom_settings.startfood;
1407 humanres.tanks = 0;
1408 humanres.planes = 0;
1409 humanres.nukes = 0;
1410 humanres.inds = 0;
1411 humanres.farms = 0;
1412 humanres.men = 0;
1413 humanres.bank = 0;
1414 humanres.moves = 0;
1415 compres.cash = superdom_settings.startcash;
1416 compres.food = superdom_settings.startfood;
1417 compres.tanks = 0;
1418 compres.planes = 0;
1419 compres.nukes = 0;
1420 compres.inds = 0;
1421 compres.farms = 0;
1422 compres.men = 0;
1423 compres.bank = 0;
1424 compres.moves = 0;
1427 int select_square(void) {
1428 int button = 0;
1429 draw_board();
1430 draw_cursor();
1431 update_score();
1432 #if LCD_WIDTH >= 220
1433 rb->lcd_setfont(FONT_SYSFIXED);
1434 rb->snprintf(buf, sizeof(buf), "Cash: %d", humanres.cash);
1435 rb->lcd_putsxy(125, LCD_HEIGHT-20, buf);
1436 rb->snprintf(buf, sizeof(buf), "Food: %d", humanres.food);
1437 rb->lcd_putsxy(125, LCD_HEIGHT-10, buf);
1438 rb->lcd_setfont(FONT_UI);
1439 #endif
1440 rb->lcd_update();
1441 while(1) {
1442 button = rb->button_get(true);
1443 switch(button) {
1444 case SUPERDOM_CANCEL:
1445 rb->splash(HZ, "Cancelled");
1446 return 2;
1447 break;
1448 case SUPERDOM_OK:
1449 return 0;
1450 break;
1451 #if CONFIG_KEYPAD != IRIVER_H10_PAD
1452 case SUPERDOM_LEFT:
1453 case (SUPERDOM_LEFT|BUTTON_REPEAT):
1454 draw_cursor(); /* Deselect the current tile */
1455 if(cursor.x>1) {
1456 cursor.x--;
1457 } else {
1458 #ifdef IPOD_STYLE
1459 if(cursor.y>1)
1460 cursor.y--;
1461 else
1462 cursor.y = 10;
1463 #endif
1464 cursor.x = 10;
1466 update_score();
1467 draw_cursor();
1468 break;
1469 case SUPERDOM_RIGHT:
1470 case (SUPERDOM_RIGHT|BUTTON_REPEAT):
1471 draw_cursor(); /* Deselect the current tile */
1472 if(cursor.x<10) {
1473 cursor.x++;
1474 } else {
1475 #ifdef IPOD_STYLE
1476 if(cursor.y<10)
1477 cursor.y++;
1478 else
1479 cursor.y = 1;
1480 #endif
1481 cursor.x = 1;
1483 update_score();
1484 draw_cursor();
1485 break;
1486 #endif
1487 #ifndef IPOD_STYLE
1488 case SUPERDOM_UP:
1489 case (SUPERDOM_UP|BUTTON_REPEAT):
1490 draw_cursor(); /* Deselect the current tile */
1491 if(cursor.y>1) {
1492 cursor.y--;
1493 } else {
1494 #if CONFIG_KEYPAD == IRIVER_H10_PAD
1495 if(cursor.x > 1)
1496 cursor.x--;
1497 else
1498 cursor.x = 10;
1499 #endif
1500 cursor.y = 10;
1502 update_score();
1503 draw_cursor();
1504 break;
1505 case SUPERDOM_DOWN:
1506 case (SUPERDOM_DOWN|BUTTON_REPEAT):
1507 draw_cursor(); /* Deselect the current tile */
1508 if(cursor.y<10) {
1509 cursor.y++;
1510 } else {
1511 #if CONFIG_KEYPAD == IRIVER_H10_PAD
1512 if(cursor.x < 10)
1513 cursor.x++;
1514 else
1515 cursor.x = 1;
1516 #endif
1517 cursor.y = 1;
1519 update_score();
1520 draw_cursor();
1521 break;
1522 #endif
1523 default:
1524 if (rb->default_event_handler(button) == SYS_USB_CONNECTED)
1526 return PLUGIN_USB_CONNECTED;
1532 int killmen(int colour) {
1533 bool human = (colour == COLOUR_LIGHT);
1534 int menkilled,i,j;
1535 int percent;
1536 if(human) {
1537 percent = (humanres.food*1000)/humanres.men;
1538 humanres.food = 0;
1539 } else {
1540 percent = (compres.food*1000)/compres.men;
1541 compres.food = 0;
1543 menkilled = 0;
1544 for(i=1;i<11;i++) {
1545 for(j=1;j<11;j++) {
1546 if(board[i][j].colour == colour) {
1547 int nummen = ((board[i][j].men * percent)/1000);
1548 menkilled += board[i][j].men - nummen;
1549 board[i][j].men = nummen;
1554 if(human)
1555 humanres.men -= menkilled;
1556 else
1557 compres.men -= menkilled;
1558 return menkilled;
1561 /* return -1 if error, 1 if attack is succeeded, 0 otherwise */
1562 int attack_territory(int colour, int x, int y) {
1563 bool human = (colour == COLOUR_LIGHT);
1564 int str_diff;
1566 if(board[x][y].colour == colour) {
1567 if(human)
1568 rb->splash(HZ, "You can't attack your own territory");
1569 return -1;
1571 str_diff = calc_strength(COLOUR_DARK, x, y) -
1572 calc_strength(COLOUR_LIGHT, x, y);
1573 if(human) {
1574 str_diff = -str_diff;
1576 rb->srand(*rb->current_tick);
1577 if(str_diff > 0 || (str_diff == 0 && rb->rand()%2)) {
1578 struct resources *offres, *defres;
1579 if(human) {
1580 offres = &humanres;
1581 defres = &compres;
1582 } else {
1583 offres = &compres;
1584 defres = &humanres;
1586 defres->men -= board[x][y].men;
1587 defres->tanks -= board[x][y].tank;
1588 defres->planes -= board[x][y].plane;
1589 defres->nukes -= board[x][y].nuke;
1590 defres->farms -= board[x][y].farm;
1591 defres->inds -= board[x][y].ind;
1592 offres->farms += board[x][y].farm;
1593 offres->inds += board[x][y].ind;
1594 board[x][y].colour = colour;
1595 board[x][y].men = 0;
1596 board[x][y].tank = false;
1597 board[x][y].plane = false;
1598 board[x][y].nuke = false;
1599 draw_board();
1600 if(human)
1601 rb->sleep(HZ*2);
1602 else
1603 rb->sleep(HZ);
1604 return 1;
1605 } else {
1606 if(human)
1607 rb->splash(HZ, "Your troops were unable to overcome"
1608 " the enemy troops");
1609 else
1610 rb->splash(HZ*2, "The computer attempted to "
1611 "attack, but the invasion was"
1612 " pushed back");
1613 return 0;
1615 return 0;
1618 int war_menu(void) {
1619 int selection, tempmenu;
1621 MENUITEM_STRINGLIST(wartime_menu, "War!", NULL,
1622 "Select territory to attack", "Finish turn", "Game menu");
1624 while(humanres.moves) {
1625 selection=rb->do_menu(&wartime_menu,&selection, NULL, false);
1626 switch(selection) {
1627 case 0:
1628 switch(select_square()) {
1629 case 0:
1630 if(attack_territory(COLOUR_LIGHT, cursor.x, cursor.y)
1631 >= 0)
1632 humanres.moves--;
1633 break;
1634 case PLUGIN_USB_CONNECTED:
1635 return PLUGIN_USB_CONNECTED;
1636 break;
1638 break;
1639 case 1:
1640 return 0;
1641 break;
1642 case 2:
1643 tempmenu = ingame_menu();
1644 switch(tempmenu) {
1645 case PLUGIN_USB_CONNECTED:
1646 return PLUGIN_USB_CONNECTED;
1647 break;
1648 case SUPERDOM_QUIT:
1649 return SUPERDOM_QUIT;
1650 break;
1652 break;
1655 return 0;
1658 struct threat {
1659 int x;
1660 int y;
1661 int str_diff;
1664 bool place_adjacent(bool tank, int x, int y) {
1665 int type = (tank? 1: 2);
1666 if(!buy_resources(COLOUR_DARK, type, x, y, 0)) {
1667 return true;
1669 if(!buy_resources(COLOUR_DARK, type, x-1, y, 0)) {
1670 return true;
1672 if(!buy_resources(COLOUR_DARK, type, x+1, y, 0)) {
1673 return true;
1675 if(!buy_resources(COLOUR_DARK, type, x, y-1, 0)) {
1676 return true;
1678 if(!buy_resources(COLOUR_DARK, type, x, y+1, 0)) {
1679 return true;
1681 return false;
1684 bool has_adjacent(int x, int y) {
1685 if((board[x][y].colour == COLOUR_LIGHT) &&
1686 ((board[x-1][y].colour == COLOUR_DARK) ||
1687 (board[x+1][y].colour == COLOUR_DARK) ||
1688 (board[x][y+1].colour == COLOUR_DARK) ||
1689 (board[x][y-1].colour == COLOUR_DARK)))
1690 return 1;
1691 else
1692 return 0;
1695 void find_adjacent(int x, int y, int* adj_x, int* adj_y) {
1696 /* Finds adjacent squares, returning squares without tanks on them
1697 * in preference to those with them */
1698 if(board[x-1][y].colour == COLOUR_DARK) {
1699 *adj_x = x-1;
1700 *adj_y = y;
1701 return;
1703 if(board[x+1][y].colour == COLOUR_DARK) {
1704 *adj_x = x+1;
1705 *adj_y = y;
1706 return;
1708 if(board[x][y-1].colour == COLOUR_DARK) {
1709 *adj_x = x;
1710 *adj_y = y-1;
1711 return;
1713 if(board[x][y+1].colour == COLOUR_DARK) {
1714 *adj_x = x;
1715 *adj_y = y+1;
1716 return;
1720 void computer_allocate(void) {
1721 /* Firstly, decide whether to go offensive or defensive.
1722 * This is primarily decided by the human player posing a threat to either
1723 * the computer's farms or factories */
1724 int i, j, k;
1725 bool offensive = true;
1726 struct threat threats[4];
1727 int numthreats = 0;
1728 int total_str_diff = 0;
1729 int numterritory = 0;
1730 int str_diff;
1731 int men_needed;
1732 struct threat targets[2];
1733 int numtargets;
1734 struct cursor adj;
1736 compres.cash += compres.bank;
1737 compres.bank = 0;
1738 for(i=1;i<11;i++) {
1739 for(j=1;j<11;j++) {
1740 if(board[i][j].colour == COLOUR_DARK) {
1741 numterritory++;
1742 str_diff = calc_strength(COLOUR_LIGHT,i,j) -
1743 calc_strength(COLOUR_DARK,i,j);
1744 if(str_diff > 0 && (board[i][j].ind || board[i][j].farm)) {
1745 if(numthreats < 3) {
1746 offensive = false;
1747 threats[numthreats].x = i;
1748 threats[numthreats].y = j;
1749 threats[numthreats].str_diff = str_diff;
1750 numthreats++;
1754 rb->yield();
1757 if(offensive) {
1758 /* The AI is going to go straight for the throat here and attack
1759 * the player's farms and factories. The amount of cash
1760 * the AI has to spend will determine how many targets there are */
1761 if(compres.cash > 1200) {
1762 /* 1200 is a figure I pulled out of nowhere. Adjust as needed */
1763 numtargets = 2;
1764 } else {
1765 numtargets = 1;
1767 /* Work out which target(s) to attack. They must have adjacent squares
1768 * owned by the computer. If none are found just place troops in
1769 * random places around the map until we run out of money */
1770 k = 0;
1771 for(i=1;i<11;i++) {
1772 for(j=1;j<11;j++) {
1773 if(has_adjacent(i,j) &&
1774 (board[i][j].ind || board[i][j].farm)) {
1775 if(k<numtargets) {
1776 targets[k].x = i;
1777 targets[k].y = j;
1778 targets[k].str_diff =
1779 calc_strength(COLOUR_LIGHT, i, j) -
1780 calc_strength(COLOUR_DARK, i, j);
1781 k++;
1784 rb->yield();
1787 if(k == 0) {
1788 /* No targets found! Randomly pick squares and if they're owned
1789 * by the computer then stick a tank on it. */
1790 rb->srand(*rb->current_tick);
1791 while(compres.cash >= 300 && compres.tanks < numterritory) {
1792 i = rb->rand()%10 + 1;
1793 j = rb->rand()%10 + 1;
1794 if(board[i][j].colour == COLOUR_DARK) {
1795 buy_resources(COLOUR_DARK, 1, i, j, 0);
1797 rb->yield();
1799 } else {
1800 for(i=0;i<k;i++) {
1801 str_diff = targets[i].str_diff;
1802 while(str_diff + 20 > 0 && compres.cash > 0) {
1803 /* While we still need them keep placing men */
1804 if(!place_adjacent(true, targets[i].x, targets[i].y)) {
1805 find_adjacent(targets[i].x, targets[i].y,
1806 &adj.x, &adj.y);
1807 men_needed = (str_diff + 20)*1000/133;
1808 if(compres.cash < men_needed) {
1809 men_needed = compres.cash;
1811 buy_resources(COLOUR_DARK, 0, adj.x, adj.y,
1812 men_needed);
1813 break;
1815 str_diff = calc_strength(COLOUR_LIGHT,
1816 targets[i].x, targets[i].y) -
1817 calc_strength(COLOUR_DARK,
1818 targets[i].x, targets[i].y);
1822 } else {
1823 /* Work out what to place on each square to defend it.
1824 * Tanks are preferential because they do not require food,
1825 * but if the budget is tight then we fall back onto troops.
1826 * Conversely if cash is not an issue and there are already tanks in
1827 * place planes will be deployed. We would like a margin of at least
1828 * 20 points to be safe. */
1830 for(i=0;i<numthreats;i++) {
1831 total_str_diff += threats[i].str_diff;
1833 if((total_str_diff+20)*10 > compres.cash) {
1834 /* Not enough cash to accomodate all threats using tanks alone -
1835 * use men as a backup */
1836 for(i=0;i<numthreats;i++) {
1837 men_needed = ((threats[i].str_diff + 20)*1000)/133;
1838 if(compres.cash < men_needed) {
1839 men_needed = compres.cash;
1841 buy_resources(COLOUR_DARK, 0, threats[i].x, threats[i].y,
1842 men_needed);
1844 } else {
1845 /* Tanks it is */
1846 /* Enough money to pay their way by planes? */
1847 bool tank = ((total_str_diff+20)*15 >= compres.cash);
1848 for(i=0;i<numthreats;i++) {
1849 str_diff = threats[i].str_diff;
1850 while(str_diff + 20 > 0) {
1851 if(!place_adjacent(tank, threats[i].x, threats[i].y)) {
1852 /* No room for any more planes or tanks, revert to
1853 * men */
1854 find_adjacent(threats[i].x, threats[i].y,
1855 &adj.x, &adj.y);
1856 men_needed = (str_diff + 20)*1000/133;
1857 if(compres.cash < men_needed) {
1858 men_needed = compres.cash;
1860 buy_resources(COLOUR_DARK, 0, threats[i].x,
1861 threats[i].y, men_needed);
1862 break;
1864 str_diff = calc_strength(COLOUR_LIGHT,
1865 threats[i].x, threats[i].y) -
1866 calc_strength(COLOUR_DARK,
1867 threats[i].x, threats[i].y);
1872 compres.bank += compres.cash;
1873 compres.cash = 0;
1876 int find_adj_target(int x, int y, struct cursor* adj) {
1877 /* Find a square next to a computer's farm or factory owned by the player
1878 * that is vulnerable. Return 1 on success, 0 otherwise */
1879 if(board[x+1][y].colour == COLOUR_LIGHT &&
1880 calc_strength(COLOUR_LIGHT,x+1,y)<=calc_strength(COLOUR_DARK,x+1,y)) {
1881 adj->x = x+1;
1882 adj->y = y;
1883 return 1;
1885 if(board[x-1][y].colour == COLOUR_LIGHT &&
1886 calc_strength(COLOUR_LIGHT,x-1,y)<=calc_strength(COLOUR_DARK,x-1,y)) {
1887 adj->x = x-1;
1888 adj->y = y;
1889 return 1;
1891 if(board[x][y+1].colour == COLOUR_LIGHT &&
1892 calc_strength(COLOUR_LIGHT,x,y+1)<=calc_strength(COLOUR_DARK,x,y+1)) {
1893 adj->x = x;
1894 adj->y = y+1;
1895 return 1;
1897 if(board[x][y-1].colour == COLOUR_LIGHT &&
1898 calc_strength(COLOUR_LIGHT,x,y-1)<=calc_strength(COLOUR_DARK,x,y-1)) {
1899 adj->x = x;
1900 adj->y = y-1;
1901 return 1;
1903 return 0;
1906 void computer_war(void) {
1907 /* Work out where to attack - prioritise the defence of buildings */
1908 int i, j;
1909 bool found_target = true;
1910 struct cursor adj;
1912 while(found_target) {
1913 found_target = false;
1914 for(i=1;i<11;i++) {
1915 for(j=1;j<11;j++) {
1916 if((board[i][j].colour == COLOUR_DARK) &&
1917 (board[i][j].farm || board[i][j].ind) &&
1918 find_adj_target(i, j, &adj)) {
1919 found_target = true;
1920 if(attack_territory(COLOUR_DARK, adj.x, adj.y) >= 0) {
1921 compres.moves--;
1922 if(!compres.moves)
1923 return;
1926 rb->yield();
1930 /* Defence stage done, move on to OFFENCE */
1931 found_target = true;
1932 while(found_target) {
1933 found_target = false;
1934 for(i=1;i<11;i++) {
1935 for(j=1;j<11;j++) {
1936 if(board[i][j].colour == COLOUR_LIGHT &&
1937 (board[i][j].ind || board[i][j].farm) &&
1938 (calc_strength(COLOUR_DARK, i, j) >=
1939 calc_strength(COLOUR_LIGHT, i, j))) {
1940 found_target = true;
1941 if(attack_territory(COLOUR_DARK, i, j) >= 0) {
1942 compres.moves--;
1943 if(!compres.moves)
1944 return;
1947 rb->yield();
1951 /* Spend leftover moves wherever attacking randomly */
1952 found_target = true;
1953 while(found_target) {
1954 found_target = false;
1955 for(i=1;i<11;i++) {
1956 for(j=1;j<11;j++) {
1957 if(board[i][j].colour == COLOUR_LIGHT &&
1958 (calc_strength(COLOUR_DARK, i, j) >=
1959 calc_strength(COLOUR_LIGHT, i, j))) {
1960 found_target = true;
1961 if(attack_territory(COLOUR_DARK, i, j) >= 0) {
1962 compres.moves--;
1963 if(!compres.moves)
1964 return;
1967 rb->yield();
1973 static int load_game(const char* file) {
1974 int fd;
1976 fd = rb->open(file, O_RDONLY);
1977 if(fd == 0) {
1978 DEBUGF("Couldn't open savegame\n");
1979 return -1;
1981 rb->read(fd, buf, 5);
1982 if(rb->strcmp(buf, "SSGv3")) {
1983 rb->splash(HZ, "Invalid/incompatible savegame");
1984 return -1;
1986 rb->read(fd, &gamestate, sizeof(gamestate));
1987 rb->read(fd, &humanres.cash, sizeof(humanres.cash));
1988 rb->read(fd, &humanres.food, sizeof(humanres.food));
1989 rb->read(fd, &humanres.bank, sizeof(humanres.bank));
1990 rb->read(fd, &humanres.planes, sizeof(humanres.planes));
1991 rb->read(fd, &humanres.tanks, sizeof(humanres.tanks));
1992 rb->read(fd, &humanres.men, sizeof(humanres.men));
1993 rb->read(fd, &humanres.nukes, sizeof(humanres.nukes));
1994 rb->read(fd, &humanres.inds, sizeof(humanres.inds));
1995 rb->read(fd, &humanres.farms, sizeof(humanres.farms));
1996 rb->read(fd, &humanres.moves, sizeof(humanres.moves));
1997 rb->read(fd, &compres.cash, sizeof(humanres.cash));
1998 rb->read(fd, &compres.food, sizeof(humanres.food));
1999 rb->read(fd, &compres.bank, sizeof(humanres.bank));
2000 rb->read(fd, &compres.planes, sizeof(humanres.planes));
2001 rb->read(fd, &compres.tanks, sizeof(humanres.tanks));
2002 rb->read(fd, &compres.men, sizeof(humanres.men));
2003 rb->read(fd, &compres.nukes, sizeof(humanres.nukes));
2004 rb->read(fd, &compres.inds, sizeof(humanres.inds));
2005 rb->read(fd, &compres.farms, sizeof(humanres.farms));
2006 rb->read(fd, &compres.moves, sizeof(humanres.moves));
2007 rb->read(fd, board, sizeof(board));
2008 rb->read(fd, &superdom_settings.compstartfarms, sizeof(int));
2009 rb->read(fd, &superdom_settings.compstartinds, sizeof(int));
2010 rb->read(fd, &superdom_settings.humanstartfarms, sizeof(int));
2011 rb->read(fd, &superdom_settings.humanstartfarms, sizeof(int));
2012 rb->read(fd, &superdom_settings.startcash, sizeof(int));
2013 rb->read(fd, &superdom_settings.startfood, sizeof(int));
2014 rb->read(fd, &superdom_settings.movesperturn, sizeof(int));
2015 rb->close(fd);
2016 return 0;
2019 void default_settings(void) {
2020 superdom_settings.compstartfarms = 1;
2021 superdom_settings.compstartinds = 1;
2022 superdom_settings.humanstartfarms = 2;
2023 superdom_settings.humanstartinds = 2;
2024 superdom_settings.startcash = 0;
2025 superdom_settings.startfood = 0;
2026 superdom_settings.movesperturn = 2;
2029 int average_strength(int colour) {
2030 /* This function calculates the average strength of the given player,
2031 * used to determine when the computer wins or loses. */
2032 int i,j;
2033 int totalpower = 0;
2034 for(i=1;i<11;i++) {
2035 for(j=1;j<11;j++) {
2036 if(board[i][j].colour != -1) {
2037 totalpower += calc_strength(colour, i, j);
2041 return totalpower/100;
2044 enum plugin_status plugin_start(const void* parameter)
2046 #if LCD_DEPTH > 1
2047 rb->lcd_set_backdrop(NULL);
2048 rb->lcd_set_foreground(LCD_BLACK);
2049 rb->lcd_set_background(LCD_WHITE);
2050 #endif
2052 cursor.x = 1;
2053 cursor.y = 1;
2054 default_settings();
2055 if(parameter) {
2056 if(load_game(parameter) != 0) {
2057 DEBUGF("Loading failed, generating new game\n");
2058 } else {
2059 switch(gamestate) {
2060 case GS_PROD:
2061 goto startprod;
2062 break;
2063 case GS_MOVE:
2064 goto startmove;
2065 break;
2066 case GS_WAR:
2067 goto startwar;
2068 break;
2069 default:
2070 goto startyear;
2071 break;
2076 bool play = false;
2077 while(!play) {
2078 switch(menu()) {
2079 case 0:
2080 play = true;
2081 break;
2082 case 2:
2083 return PLUGIN_OK;
2084 break;
2085 case PLUGIN_USB_CONNECTED:
2086 return PLUGIN_USB_CONNECTED;
2087 break;
2090 init_resources();
2091 init_board();
2092 gen_resources();
2093 startyear:
2094 while(1) {
2095 int avg_str_diff = (average_strength(COLOUR_LIGHT) -
2096 average_strength(COLOUR_DARK));
2097 if(avg_str_diff > 15) {
2098 rb->splash(HZ*4, "The computer has surrendered. You win.");
2099 return PLUGIN_OK;
2101 if(-avg_str_diff > 15) {
2102 rb->splash(HZ*4, "Your army have suffered terrible morale from"
2103 " the bleak prospects of winning. You lose.");
2104 return PLUGIN_OK;
2107 /* production */
2108 startprod:
2109 gamestate = GS_PROD;
2110 switch(production_menu()) {
2111 case PLUGIN_USB_CONNECTED:
2112 return PLUGIN_USB_CONNECTED;
2113 break;
2114 case SUPERDOM_QUIT:
2115 return PLUGIN_OK;
2116 break;
2118 computer_allocate();
2120 /* movement */
2121 humanres.moves = superdom_settings.movesperturn;
2122 startmove:
2123 gamestate = GS_MOVE;
2124 switch(movement_menu()) {
2125 case PLUGIN_USB_CONNECTED:
2126 return PLUGIN_USB_CONNECTED;
2127 break;
2128 case SUPERDOM_QUIT:
2129 return PLUGIN_OK;
2130 break;
2132 /* feed men */
2133 if(humanres.men) {
2134 if(humanres.food > humanres.men) {
2135 rb->snprintf(buf, sizeof(buf), "Your men ate %d units of food",
2136 humanres.men);
2137 humanres.food -= humanres.men;
2138 } else {
2139 rb->snprintf(buf, sizeof(buf), "There was not enough food"
2140 " to feed all your men, %d men have died of starvation",
2141 killmen(COLOUR_LIGHT));
2143 rb->splash(HZ*2, buf);
2145 if(compres.men) {
2146 if(compres.food > compres.men) {
2147 compres.food -= compres.men;
2148 } else {
2149 rb->snprintf(buf, sizeof(buf), "The computer does not have"
2150 " enough food to feed its men. %d have died of starvation",
2151 killmen(COLOUR_DARK));
2152 rb->splash(HZ, buf);
2155 /* war */
2156 humanres.moves = superdom_settings.movesperturn;
2157 startwar:
2158 gamestate = GS_WAR;
2159 switch(war_menu()) {
2160 case PLUGIN_USB_CONNECTED:
2161 return PLUGIN_USB_CONNECTED;
2162 break;
2163 case SUPERDOM_QUIT:
2164 return PLUGIN_OK;
2165 break;
2167 compres.moves = superdom_settings.movesperturn;
2168 computer_war();
2169 gen_resources();
2171 return PLUGIN_OK;