summaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
authorWill Robertson <aliask@rockbox.org>2007-08-02 12:55:14 +0000
committerWill Robertson <aliask@rockbox.org>2007-08-02 12:55:14 +0000
commit1685da832f1cecba215296734aef91b3918f57bb (patch)
tree5981a5bb77e2af9f3133f2602b1df253971a4c8a /apps
parent8789ebc4f2c838ff12d13a043ff8d501b9bab2f8 (diff)
downloadrockbox-1685da832f1cecba215296734aef91b3918f57bb.tar.gz
rockbox-1685da832f1cecba215296734aef91b3918f57bb.zip
Accept FS#7136: Turn based strategy game - "Superdom" clone
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@14144 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps')
-rw-r--r--apps/plugins/SOURCES3
-rw-r--r--apps/plugins/bitmaps/mono/SOURCES4
-rw-r--r--apps/plugins/bitmaps/mono/superdom_boarditems.160x128x1.bmpbin0 -> 630 bytes
-rw-r--r--apps/plugins/bitmaps/native/SOURCES15
-rw-r--r--apps/plugins/bitmaps/native/superdom_boarditems.176x132x16.bmpbin0 -> 630 bytes
-rw-r--r--apps/plugins/bitmaps/native/superdom_boarditems.220x176x16.bmpbin0 -> 1902 bytes
-rw-r--r--apps/plugins/bitmaps/native/superdom_boarditems.240x320x16.bmpbin0 -> 3078 bytes
-rw-r--r--apps/plugins/bitmaps/native/superdom_boarditems.320x240x16.bmpbin0 -> 3654 bytes
-rw-r--r--apps/plugins/superdom.c2341
-rw-r--r--apps/plugins/viewers.config1
10 files changed, 2364 insertions, 0 deletions
diff --git a/apps/plugins/SOURCES b/apps/plugins/SOURCES
index 48d9417e7a..06c4b7ccdc 100644
--- a/apps/plugins/SOURCES
+++ b/apps/plugins/SOURCES
@@ -133,3 +133,6 @@ iriver_flash.c
133#endif 133#endif
134 134
135#endif /* iFP7xx */ 135#endif /* iFP7xx */
136#if (LCD_WIDTH == 220) || (LCD_WIDTH == 176) || (LCD_WIDTH == 160) || (LCD_WIDTH == 320) || (LCD_WIDTH == 240)
137superdom.c
138#endif
diff --git a/apps/plugins/bitmaps/mono/SOURCES b/apps/plugins/bitmaps/mono/SOURCES
index 626b6ca2d8..d74905fb0d 100644
--- a/apps/plugins/bitmaps/mono/SOURCES
+++ b/apps/plugins/bitmaps/mono/SOURCES
@@ -46,6 +46,10 @@ flipit_cursor.16x13x1.bmp
46#endif 46#endif
47#endif 47#endif
48 48
49#if LCD_WIDTH == 160 && LCD_HEIGHT == 128 && LCD_DEPTH < 16
50superdom_boarditems.160x128x1.bmp
51#endif
52
49#endif /* HAVE_LCD_BITMAP */ 53#endif /* HAVE_LCD_BITMAP */
50#if defined(SIMULATOR) && defined(__APPLE__) 54#if defined(SIMULATOR) && defined(__APPLE__)
51osx.dummy.bmp 55osx.dummy.bmp
diff --git a/apps/plugins/bitmaps/mono/superdom_boarditems.160x128x1.bmp b/apps/plugins/bitmaps/mono/superdom_boarditems.160x128x1.bmp
new file mode 100644
index 0000000000..c9196b22db
--- /dev/null
+++ b/apps/plugins/bitmaps/mono/superdom_boarditems.160x128x1.bmp
Binary files differ
diff --git a/apps/plugins/bitmaps/native/SOURCES b/apps/plugins/bitmaps/native/SOURCES
index 50866cb183..05029c430c 100644
--- a/apps/plugins/bitmaps/native/SOURCES
+++ b/apps/plugins/bitmaps/native/SOURCES
@@ -457,4 +457,19 @@ sudoku_inverse.320x240x16.bmp
457#endif 457#endif
458#endif 458#endif
459 459
460/* Superdom */
461#if LCD_DEPTH == 16
462#if ((LCD_WIDTH == 220) && (LCD_HEIGHT == 176))
463superdom_boarditems.220x176x16.bmp
464#elif ((LCD_WIDTH == 176) && (LCD_HEIGHT == 132)) || \
465 ((LCD_WIDTH == 160) && (LCD_HEIGHT == 128)) || \
466 ((LCD_WIDTH == 176) && (LCD_HEIGHT == 220))
467superdom_boarditems.176x132x16.bmp
468#elif (LCD_WIDTH == 320 && LCD_HEIGHT == 240)
469superdom_boarditems.320x240x16.bmp
470#elif (LCD_WIDTH == 240 && LCD_HEIGHT == 320)
471superdom_boarditems.240x320x16.bmp
472#endif
473#endif
474
460#endif /* HAVE_LCD_BITMAP */ 475#endif /* HAVE_LCD_BITMAP */
diff --git a/apps/plugins/bitmaps/native/superdom_boarditems.176x132x16.bmp b/apps/plugins/bitmaps/native/superdom_boarditems.176x132x16.bmp
new file mode 100644
index 0000000000..db95fb5f8d
--- /dev/null
+++ b/apps/plugins/bitmaps/native/superdom_boarditems.176x132x16.bmp
Binary files differ
diff --git a/apps/plugins/bitmaps/native/superdom_boarditems.220x176x16.bmp b/apps/plugins/bitmaps/native/superdom_boarditems.220x176x16.bmp
new file mode 100644
index 0000000000..47b4b90164
--- /dev/null
+++ b/apps/plugins/bitmaps/native/superdom_boarditems.220x176x16.bmp
Binary files differ
diff --git a/apps/plugins/bitmaps/native/superdom_boarditems.240x320x16.bmp b/apps/plugins/bitmaps/native/superdom_boarditems.240x320x16.bmp
new file mode 100644
index 0000000000..b39c69ba6e
--- /dev/null
+++ b/apps/plugins/bitmaps/native/superdom_boarditems.240x320x16.bmp
Binary files differ
diff --git a/apps/plugins/bitmaps/native/superdom_boarditems.320x240x16.bmp b/apps/plugins/bitmaps/native/superdom_boarditems.320x240x16.bmp
new file mode 100644
index 0000000000..36b53b6bb6
--- /dev/null
+++ b/apps/plugins/bitmaps/native/superdom_boarditems.320x240x16.bmp
Binary files differ
diff --git a/apps/plugins/superdom.c b/apps/plugins/superdom.c
new file mode 100644
index 0000000000..7c70aa7d96
--- /dev/null
+++ b/apps/plugins/superdom.c
@@ -0,0 +1,2341 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2006 Will Robertson
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19#include "plugin.h"
20PLUGIN_HEADER
21static struct plugin_api* rb;
22
23extern const fb_data superdom_boarditems[];
24char buf[255];
25
26#define COLOUR_DARK 0
27#define COLOUR_LIGHT 1
28
29#define MARGIN 5
30
31#if LCD_WIDTH > LCD_HEIGHT
32#define BOX_WIDTH ((LCD_WIDTH-(MARGIN*2))/10)
33#define BOX_HEIGHT ((BOX_WIDTH*2)/3)
34
35#else
36#define BOX_HEIGHT ((LCD_HEIGHT-(MARGIN*2)-15)/10)
37#define BOX_WIDTH ((BOX_HEIGHT*2)/3)
38
39#endif
40
41#if LCD_WIDTH == 220 && LCD_HEIGHT == 176
42#define NUM_BOX_HEIGHT 25
43#define NUM_BOX_WIDTH 30
44#define STRIDE 14
45#define ICON_HEIGHT 7
46#define ICON_WIDTH 7
47
48#elif (LCD_WIDTH == 160 && LCD_HEIGHT == 128) || \
49 (LCD_WIDTH == 176 && LCD_HEIGHT == 132) || \
50 (LCD_WIDTH == 176 && LCD_HEIGHT == 220)
51#define NUM_BOX_HEIGHT 20
52#define NUM_BOX_WIDTH 24
53#define STRIDE 8
54#define ICON_HEIGHT 4
55#define ICON_WIDTH 4
56
57#elif (LCD_WIDTH == 320 && LCD_HEIGHT == 240)
58#define NUM_BOX_HEIGHT 25
59#define NUM_BOX_WIDTH 30
60#define STRIDE 20
61#define ICON_HEIGHT 10
62#define ICON_WIDTH 10
63
64#elif (LCD_WIDTH == 240 && LCD_HEIGHT == 320)
65#define NUM_BOX_HEIGHT 25
66#define NUM_BOX_WIDTH 30
67#define STRIDE 18
68#define ICON_HEIGHT 9
69#define ICON_WIDTH 9
70
71#endif
72
73#define NUM_MARGIN_X (LCD_WIDTH-3*NUM_BOX_WIDTH)/2
74#define NUM_MARGIN_Y (LCD_HEIGHT-4*NUM_BOX_HEIGHT)/2
75
76#if CONFIG_KEYPAD == IPOD_4G_PAD
77#define SUPERDOM_OK BUTTON_SELECT
78#define SUPERDOM_CANCEL BUTTON_MENU
79#define SUPERDOM_LEFT BUTTON_LEFT
80#define SUPERDOM_RIGHT BUTTON_RIGHT
81
82#elif CONFIG_KEYPAD == IRIVER_H300_PAD || CONFIG_KEYPAD == IRIVER_H100_PAD
83#define SUPERDOM_OK BUTTON_SELECT
84#define SUPERDOM_LEFT BUTTON_LEFT
85#define SUPERDOM_RIGHT BUTTON_RIGHT
86#define SUPERDOM_UP BUTTON_UP
87#define SUPERDOM_DOWN BUTTON_DOWN
88#define SUPERDOM_CANCEL BUTTON_OFF
89
90#elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
91#define SUPERDOM_OK BUTTON_SELECT
92#define SUPERDOM_LEFT BUTTON_LEFT
93#define SUPERDOM_RIGHT BUTTON_RIGHT
94#define SUPERDOM_UP BUTTON_UP
95#define SUPERDOM_DOWN BUTTON_DOWN
96#define SUPERDOM_CANCEL BUTTON_REC
97
98#elif CONFIG_KEYPAD == IRIVER_H10_PAD
99#define SUPERDOM_OK BUTTON_RIGHT
100#define SUPERDOM_UP BUTTON_SCROLL_UP
101#define SUPERDOM_DOWN BUTTON_SCROLL_DOWN
102#define SUPERDOM_CANCEL BUTTON_LEFT
103
104#elif CONFIG_KEYPAD == GIGABEAT_PAD
105#define SUPERDOM_OK BUTTON_SELECT
106#define SUPERDOM_UP BUTTON_UP
107#define SUPERDOM_DOWN BUTTON_DOWN
108#define SUPERDOM_LEFT BUTTON_LEFT
109#define SUPERDOM_RIGHT BUTTON_RIGHT
110#define SUPERDOM_CANCEL BUTTON_POWER
111
112#elif CONFIG_KEYPAD == SANSA_E200_PAD
113#define SUPERDOM_OK BUTTON_SELECT
114#define SUPERDOM_UP BUTTON_SCROLL_UP
115#define SUPERDOM_DOWN BUTTON_SCROLL_DOWN
116#define SUPERDOM_LEFT BUTTON_LEFT
117#define SUPERDOM_RIGHT BUTTON_RIGHT
118#define SUPERDOM_CANCEL BUTTON_POWER
119
120#endif
121
122#define SUPERDOM_QUIT 23
123
124void gen_interest(void);
125int production_menu(void);
126void init_resources(void);
127int select_square(void);
128void update_score(void);
129void gen_resources(void);
130void draw_cursor(void);
131int calc_strength(bool colour, int x, int y);
132void draw_board(void);
133
134struct tile{
135 signed int colour; /* -1 = Unset */
136 bool tank;
137 bool plane;
138 bool nuke;
139 bool ind;
140 bool farm;
141 int men;
142};
143
144struct resources {
145 int cash;
146 int food;
147 int farms;
148 int inds;
149 int men;
150 int tanks;
151 int planes;
152 int nukes;
153 int bank;
154 int moves;
155};
156
157struct settings {
158 int compstartfarms;
159 int compstartinds;
160 int humanstartfarms;
161 int humanstartinds;
162 int startcash;
163 int startfood;
164 int movesperturn;
165} superdom_settings;
166
167struct resources humanres;
168struct resources compres;
169
170struct cursor{
171 int x;
172 int y;
173} cursor;
174
175struct tile board[12][12];
176
177void init_board(void) {
178 rb->srand(*rb->current_tick);
179 int i,j;
180 for(i=0;i<12;i++) { /* Hopefully about 50% each colour */
181 for(j=0;j<12;j++) {
182 if((i<1)||(j<1)||(i>10)||(j>10))
183 board[i][j].colour = -1; /* Unset */
184 else
185 board[i][j].colour = rb->rand()%2;
186 board[i][j].tank = false;
187 board[i][j].plane = false;
188 board[i][j].nuke = false;
189 board[i][j].ind = false;
190 board[i][j].farm = false;
191 board[i][j].men = 0;
192 }
193 }
194
195 while(compres.farms < superdom_settings.compstartfarms) {
196 i = rb->rand()%10 + 1;
197 j = rb->rand()%10 + 1;
198 if((board[i][j].colour == COLOUR_DARK) && (board[i][j].farm == false)) {
199 board[i][j].farm = true;
200 compres.farms++;
201 break;
202 }
203 }
204 while(compres.inds < superdom_settings.compstartinds) {
205 i = rb->rand()%10 + 1;
206 j = rb->rand()%10 + 1;
207 if((board[i][j].colour == COLOUR_DARK) && (board[i][j].ind == false)) {
208 board[i][j].ind = true;
209 compres.inds++;
210 break;
211 }
212 }
213 while(humanres.farms<superdom_settings.humanstartfarms) {
214 i = rb->rand()%10 + 1;
215 j = rb->rand()%10 + 1;
216 if((board[i][j].colour == COLOUR_LIGHT)&&(board[i][j].farm == false)) {
217 board[i][j].farm = true;
218 humanres.farms++;
219 }
220 }
221 while(humanres.inds<superdom_settings.humanstartfarms) {
222 i = rb->rand()%10 + 1;
223 j = rb->rand()%10 + 1;
224 if((board[i][j].colour == COLOUR_LIGHT) && (board[i][j].ind == false)) {
225 board[i][j].ind = true;
226 humanres.inds++;
227 }
228 }
229}
230
231void draw_board(void) {
232 rb->lcd_clear_display();
233 int i,j;
234 for(i=1;i<11;i++) {
235 for(j=1;j<11;j++) {
236 if(board[i][j].colour == COLOUR_DARK) {
237 rb->lcd_set_foreground(LCD_DARKGRAY);
238 } else {
239 rb->lcd_set_foreground(LCD_LIGHTGRAY);
240 }
241 rb->lcd_fillrect(MARGIN+(BOX_WIDTH*(i-1)),
242 MARGIN+(BOX_HEIGHT*(j-1)), BOX_WIDTH,
243 BOX_HEIGHT);
244#if LCD_DEPTH != 16
245 rb->lcd_set_drawmode(DRMODE_BG | DRMODE_INVERSEVID);
246#endif
247 if(board[i][j].ind) {
248#if (LCD_DEPTH == 16)
249 rb->lcd_bitmap_transparent_part(superdom_boarditems,
250#else
251 rb->lcd_mono_bitmap_part(superdom_boarditems,
252#endif
253 board[i][j].colour?ICON_WIDTH:0, 0, STRIDE,
254#if LCD_WIDTH > LCD_HEIGHT
255 MARGIN+(BOX_WIDTH*(i-1))+1,
256 MARGIN+(BOX_HEIGHT*(j-1))+ICON_HEIGHT+1,
257#else
258 MARGIN+(BOX_WIDTH*(i-1))+1+ICON_WIDTH,
259 MARGIN+(BOX_HEIGHT*(j-1))+1,
260#endif
261 ICON_WIDTH, ICON_HEIGHT);
262 }
263 if(board[i][j].farm) {
264#if (LCD_DEPTH == 16)
265 rb->lcd_bitmap_transparent_part(superdom_boarditems,
266#else
267 rb->lcd_mono_bitmap_part(superdom_boarditems,
268#endif
269 board[i][j].colour?ICON_WIDTH:0, ICON_HEIGHT,
270 STRIDE, MARGIN+(BOX_WIDTH*(i-1))+1,
271 MARGIN+(BOX_HEIGHT*(j-1))+1,
272 ICON_WIDTH, ICON_HEIGHT);
273 }
274 if(board[i][j].tank) {
275#if (LCD_DEPTH == 16)
276 rb->lcd_bitmap_transparent_part(superdom_boarditems,
277#else
278 rb->lcd_mono_bitmap_part(superdom_boarditems,
279#endif
280 board[i][j].colour?ICON_WIDTH:0, ICON_HEIGHT*2,
281 STRIDE, MARGIN+(BOX_WIDTH*(i-1))+ICON_WIDTH+1,
282 MARGIN+(BOX_HEIGHT*(j-1))+ICON_HEIGHT+1,
283 ICON_WIDTH, ICON_HEIGHT);
284 }
285 if(board[i][j].men) {
286#if (LCD_DEPTH == 16)
287 rb->lcd_bitmap_transparent_part(superdom_boarditems,
288#else
289 rb->lcd_mono_bitmap_part(superdom_boarditems,
290#endif
291 board[i][j].colour?ICON_WIDTH:0, ICON_HEIGHT*3,
292#if LCD_WIDTH > LCD_HEIGHT
293 STRIDE, MARGIN+(BOX_WIDTH*(i-1))+ICON_WIDTH+1,
294 MARGIN+(BOX_HEIGHT*(j-1))+1,
295#else
296 STRIDE, MARGIN+(BOX_WIDTH*(i-1))+1,
297 MARGIN+(BOX_HEIGHT*(j-1))+1+ICON_HEIGHT,
298#endif
299 ICON_WIDTH, ICON_HEIGHT);
300 }
301 if(board[i][j].plane) {
302#if (LCD_DEPTH == 16)
303 rb->lcd_bitmap_transparent_part(superdom_boarditems,
304#else
305 rb->lcd_mono_bitmap_part(superdom_boarditems,
306#endif
307 board[i][j].colour?ICON_WIDTH:0, ICON_HEIGHT*4,
308#if LCD_WIDTH > LCD_HEIGHT
309 STRIDE,MARGIN+(BOX_WIDTH*(i-1))+ICON_WIDTH*2+1,
310 MARGIN+(BOX_HEIGHT*(j-1))+ICON_HEIGHT+1,
311#else
312 STRIDE,MARGIN+(BOX_WIDTH*(i-1))+ICON_WIDTH+1,
313 MARGIN+(BOX_HEIGHT*(j-1))+ICON_HEIGHT*2+1,
314#endif
315 ICON_WIDTH, ICON_HEIGHT);
316 }
317 if(board[i][j].nuke) {
318#if (LCD_DEPTH == 16)
319 rb->lcd_bitmap_transparent_part(superdom_boarditems,
320#else
321 rb->lcd_mono_bitmap_part(superdom_boarditems,
322#endif
323 board[i][j].colour?ICON_WIDTH:0, ICON_HEIGHT*5,
324#if LCD_WIDTH > LCD_HEIGHT
325 STRIDE,MARGIN+(BOX_WIDTH*(i-1))+ICON_WIDTH*2+1,
326 MARGIN+(BOX_HEIGHT*(j-1))+1,
327#else
328 STRIDE,MARGIN+(BOX_WIDTH*(i-1))+1,
329 MARGIN+(BOX_HEIGHT*(j-1))+ICON_HEIGHT*2+1,
330#endif
331 ICON_WIDTH, ICON_HEIGHT);
332 }
333#if LCD_DEPTH != 16
334 rb->lcd_set_drawmode(DRMODE_SOLID);
335#endif
336 }
337 }
338 rb->lcd_set_foreground(LCD_BLACK);
339 for(i=0;i<=10;i++) { /* Draw Horizontal lines */
340 rb->lcd_drawline(MARGIN, MARGIN+(BOX_HEIGHT*i), MARGIN+(BOX_WIDTH*10),
341 MARGIN+(BOX_HEIGHT*i));
342 }
343 for(i=0;i<=10;i++) { /* Draw Vertical lines */
344 rb->lcd_drawline(MARGIN+(BOX_WIDTH*i),MARGIN, MARGIN+(BOX_WIDTH*i),
345 MARGIN+(BOX_HEIGHT*10));
346 }
347 rb->lcd_update();
348}
349
350int calc_strength(bool colour, int x, int y) {
351 /* Yes, I know. Please, if you know how, fix it. */
352 int score=0;
353 if(board[x][y].colour == colour) {
354 score+=10;
355 }
356 if(board[x+1][y].colour == colour) {
357 score+=10;
358 }
359 if(board[x][y+1].colour == colour) {
360 score+=10;
361 }
362 if(board[x-1][y].colour == colour) {
363 score+=10;
364 }
365 if(board[x][y-1].colour == colour) {
366 score+=10;
367 }
368 if((board[x][y].colour == colour) && board[x][y].tank) {
369 score+=30;
370 }
371 if((board[x+1][y].colour == colour) && board[x+1][y].tank) {
372 score+=30;
373 }
374 if((board[x][y+1].colour == colour) && board[x][y+1].tank) {
375 score+=30;
376 }
377 if((board[x-1][y].colour == colour) && board[x-1][y].tank) {
378 score+=30;
379 }
380 if((board[x][y-1].colour == colour) && board[x][y-1].tank) {
381 score+=30;
382 }
383 if((board[x][y].colour == colour) && board[x][y].plane) {
384 score+=40;
385 }
386 if((board[x+1][y].colour == colour) && board[x+1][y].plane) {
387 score+=40;
388 }
389 if((board[x][y+1].colour == colour) && board[x][y+1].plane) {
390 score+=40;
391 }
392 if((board[x-1][y].colour == colour) && board[x-1][y].plane) {
393 score+=40;
394 }
395 if((board[x][y-1].colour == colour) && board[x][y-1].plane) {
396 score+=40;
397 }
398 if((board[x][y].colour == colour) && board[x][y].ind) {
399 score+=40;
400 }
401 if((board[x+1][y].colour == colour) && board[x+1][y].ind) {
402 score+=40;
403 }
404 if((board[x][y+1].colour == colour) && board[x][y+1].ind) {
405 score+=40;
406 }
407 if((board[x-1][y].colour == colour) && board[x-1][y].ind) {
408 score+=40;
409 }
410 if((board[x][y-1].colour == colour) && board[x][y-1].ind) {
411 score+=40;
412 }
413 if((board[x][y].colour == colour) && board[x][y].farm) {
414 score+=30;
415 }
416 if((board[x+1][y].colour == colour) && board[x+1][y].farm) {
417 score+=30;
418 }
419 if((board[x][y+1].colour == colour) && board[x][y+1].farm) {
420 score+=30;
421 }
422 if((board[x-1][y].colour == colour) && board[x-1][y].farm) {
423 score+=30;
424 }
425 if((board[x][y-1].colour == colour) && board[x][y-1].farm) {
426 score+=30;
427 }
428 if((board[x][y].colour == colour) && board[x][y].nuke) {
429 score+=20;
430 }
431 if((board[x+1][y].colour == colour) && board[x+1][y].nuke) {
432 score+=20;
433 }
434 if((board[x][y+1].colour == colour) && board[x][y+1].nuke) {
435 score+=20;
436 }
437 if((board[x-1][y].colour == colour) && board[x-1][y].nuke) {
438 score+=20;
439 }
440 if((board[x][y-1].colour == colour) && board[x][y-1].nuke) {
441 score+=20;
442 }
443 if((board[x][y].colour == colour) && board[x][y].men) {
444 score+=(board[x][y].men*133/1000);
445 }
446 if((board[x+1][y].colour == colour) && board[x+1][y].men) {
447 score+=(board[x+1][y].men*133/1000);
448 }
449 if((board[x][y+1].colour == colour) && board[x][y+1].men) {
450 score+=(board[x][y+1].men*133/1000);
451 }
452 if((board[x-1][y].colour == colour) && board[x-1][y].men) {
453 score+=(board[x-1][y].men*133/1000);
454 }
455 if((board[x][y-1].colour == colour) && board[x][y-1].men) {
456 score+=(board[x][y-1].men*133/1000);
457 }
458 return score;
459}
460
461void gen_interest(void) {
462 /* Interest should be around 10% */
463 rb->srand(*rb->current_tick);
464 int interest = 7+rb->rand()%6;
465 humanres.bank = humanres.bank+(interest*humanres.bank/100);
466}
467
468void draw_cursor(void) {
469 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
470 rb->lcd_fillrect(MARGIN+((cursor.x-1)*BOX_WIDTH),
471 MARGIN+((cursor.y-1)*BOX_HEIGHT), BOX_WIDTH+1, BOX_HEIGHT+1);
472 rb->lcd_set_drawmode(DRMODE_SOLID);
473 rb->lcd_update();
474}
475
476void gen_resources(void) {
477 gen_interest();
478 int inccash = 0;
479 int incfood = 0;
480 int i;
481 rb->srand(*rb->current_tick);
482 /* Generate Human's resources */
483 for(i=0;i<humanres.inds;i++) {
484 inccash += (300+rb->rand()%200);
485 }
486 for(i=0;i<humanres.farms;i++) {
487 incfood += (200+rb->rand()%200);
488 }
489 if(inccash/humanres.inds > 450) {
490 if(incfood/humanres.farms > 350) {
491 rb->splash(HZ*2, "Patriotism sweeps the land, all production"
492 " is up this year!");
493 } else {
494 rb->splash(HZ*2, "Factories working at maximum efficiency,"
495 " cash production up this year!");
496 }
497 } else if((inccash/humanres.inds>350)&&(inccash/humanres.inds<=450)) {
498 if(incfood/humanres.farms > 350) {
499 rb->splash(HZ*2, "Record crop harvest this year!");
500 } else if((incfood/humanres.farms > 250) &&
501 (incfood/humanres.farms <= 350)) {
502 rb->splash(HZ*2, "Production continues as normal");
503 } else {
504 rb->splash(HZ*2, "Spoilage of crops leads to reduced farm"
505 " output this year");
506 }
507 } else {
508 if(incfood/humanres.farms > 350) {
509 rb->splash(HZ*2, "Record crop harvest this year!");
510 } else if((incfood/humanres.farms > 250) &&
511 (incfood/humanres.farms <= 350)) {
512 rb->splash(HZ*2, "Factory unions introduced. Industrial"
513 " production is down this year.");
514 } else {
515 rb->splash(HZ*2, "Internet created. All production is down"
516 " due to time wasted.");
517 }
518 }
519 humanres.cash += inccash;
520 humanres.food += incfood;
521
522 /* Generate Computer's resources */
523 inccash = 0;
524 incfood = 0;
525 for(i=0;i<compres.inds;i++) {
526 inccash += (300+rb->rand()%200);
527 }
528 for(i=0;i<compres.farms;i++) {
529 incfood += (200+rb->rand()%200);
530 }
531 compres.cash += inccash;
532 compres.food += incfood;
533}
534
535void update_score(void) {
536 rb->lcd_set_drawmode(DRMODE_BG|DRMODE_INVERSEVID);
537 rb->lcd_fillrect(5,LCD_HEIGHT-20,105,20);
538 rb->lcd_set_drawmode(DRMODE_SOLID);
539 rb->snprintf(buf, sizeof(buf), "Your power: %d.%d",
540 calc_strength(COLOUR_LIGHT, cursor.x, cursor.y)/10,
541 calc_strength(COLOUR_LIGHT, cursor.x, cursor.y)%10);
542 rb->lcd_putsxy(5,LCD_HEIGHT-20, buf);
543 rb->snprintf(buf, sizeof(buf), "Comp power: %d.%d",
544 calc_strength(COLOUR_DARK, cursor.x, cursor.y)/10,
545 calc_strength(COLOUR_DARK, cursor.x, cursor.y)%10);
546 rb->lcd_putsxy(5,LCD_HEIGHT-10, buf);
547}
548
549int settings_menu_function(void) {
550 int selection = 0;
551
552 MENUITEM_STRINGLIST(settings_menu,"Super Domination Settings",NULL,
553 "Computer starting farms","Computer starting factories",
554 "Human starting farms","Human starting factories",
555 "Starting cash","Starting food","Moves per turn");
556settings_menu:
557 selection=rb->do_menu(&settings_menu,&selection);
558 switch(selection) {
559 case 0:
560 rb->set_int("Computer starting farms", "", UNIT_INT,
561 &superdom_settings.compstartfarms, NULL,
562 1, 0, 5, NULL);
563 goto settings_menu;
564 break;
565 case 1:
566 rb->set_int("Computer starting factories", "", UNIT_INT,
567 &superdom_settings.compstartinds, NULL,
568 1, 0, 5, NULL);
569 goto settings_menu;
570 break;
571 case 2:
572 rb->set_int("Human starting farms", "", UNIT_INT,
573 &superdom_settings.humanstartfarms, NULL,
574 1, 0, 5, NULL);
575 goto settings_menu;
576 break;
577 case 3:
578 superdom_settings.humanstartinds =
579 rb->set_int("Human starting factories", "", UNIT_INT,
580 &superdom_settings.humanstartinds, NULL,
581 1, 0, 5, NULL);
582 goto settings_menu;
583 break;
584 case 4:
585 rb->set_int("Starting cash", "", UNIT_INT,
586 &superdom_settings.startcash, NULL,
587 250, 0, 5000, NULL);
588 goto settings_menu;
589 break;
590 case 5:
591 rb->set_int("Starting food", "", UNIT_INT,
592 &superdom_settings.startfood, NULL,
593 250, 0, 5000, NULL);
594 goto settings_menu;
595 break;
596 case 6:
597 rb->set_int("Moves per turn", "", UNIT_INT,
598 &superdom_settings.movesperturn, NULL,
599 1, 1, 5, NULL);
600 goto settings_menu;
601 break;
602 case MENU_ATTACHED_USB:
603 return PLUGIN_USB_CONNECTED;
604 break;
605 }
606 return 0;
607}
608
609int do_help(void) {
610 int selection = 0;
611
612 MENUITEM_STRINGLIST(help_menu,"Help",NULL,"Super domination is a turn",
613 "based strategy game, where the aim is to overpower the",
614 "computer player by taking their territory.",
615 "Each year you are allocated an amount of cash and food,",
616 "depending on how many farms and factories you control."
617 "Use this cash and food to buy and feed your army.",
618 "Each tile has a strength, calculated by the ownership",
619 "of adjacent tiles, and the type and number of troops",
620 "on them.");
621 rb->do_menu(&help_menu,&selection);
622 switch(selection) {
623 case MENU_ATTACHED_USB:
624 return PLUGIN_USB_CONNECTED;
625 break;
626 }
627 return 0;
628}
629
630int menu(void) {
631 int selection = 0;
632
633 MENUITEM_STRINGLIST(main_menu,"Super Domination Menu",NULL,
634 "Play Super Domination","Settings","Help","Quit");
635
636 while(1) {
637 selection=rb->do_menu(&main_menu,&selection);
638 switch(selection) {
639 case 0:
640 return 0; /* start playing */
641 break;
642 case 1:
643 if(settings_menu_function()==PLUGIN_USB_CONNECTED)
644 return PLUGIN_USB_CONNECTED;
645 break;
646 case 2:
647 if(do_help()==PLUGIN_USB_CONNECTED)
648 return PLUGIN_USB_CONNECTED;
649 break;
650 default:
651 return 2; /* quit program */
652 break;
653 }
654 }
655
656 return 3;
657}
658
659int save_game(void) {
660 int fd;
661 char savepath[MAX_PATH];
662
663 rb->snprintf(savepath, sizeof(savepath), "/Savegame.ssg");
664 if(rb->kbd_input(savepath, MAX_PATH)) {
665 DEBUGF("Keyboard input failed\n");
666 return -1;
667 }
668
669 fd = rb->open(savepath, O_WRONLY|O_CREAT);
670 DEBUGF("savepath: %s\n", savepath);
671 if(fd < 0) {
672 DEBUGF("Couldn't create/open file\n");
673 return -1;
674 }
675
676 rb->write(fd, "SSGv2", 5);
677 rb->write(fd, &humanres.cash, sizeof(humanres.cash));
678 rb->write(fd, &humanres.food, sizeof(humanres.food));
679 rb->write(fd, &humanres.bank, sizeof(humanres.bank));
680 rb->write(fd, &humanres.planes, sizeof(humanres.planes));
681 rb->write(fd, &humanres.tanks, sizeof(humanres.tanks));
682 rb->write(fd, &humanres.men, sizeof(humanres.men));
683 rb->write(fd, &humanres.nukes, sizeof(humanres.nukes));
684 rb->write(fd, &humanres.inds, sizeof(humanres.inds));
685 rb->write(fd, &humanres.farms, sizeof(humanres.farms));
686 rb->write(fd, &humanres.moves, sizeof(humanres.moves));
687 rb->write(fd, &compres.cash, sizeof(compres.cash));
688 rb->write(fd, &compres.food, sizeof(compres.food));
689 rb->write(fd, &compres.bank, sizeof(compres.bank));
690 rb->write(fd, &compres.planes, sizeof(compres.planes));
691 rb->write(fd, &compres.tanks, sizeof(compres.tanks));
692 rb->write(fd, &compres.men, sizeof(compres.men));
693 rb->write(fd, &compres.nukes, sizeof(compres.nukes));
694 rb->write(fd, &compres.inds, sizeof(compres.inds));
695 rb->write(fd, &compres.farms, sizeof(compres.farms));
696 rb->write(fd, &compres.moves, sizeof(compres.moves));
697 rb->write(fd, board, sizeof(board));
698 rb->write(fd, &superdom_settings.compstartfarms, sizeof(int));
699 rb->write(fd, &superdom_settings.compstartinds, sizeof(int));
700 rb->write(fd, &superdom_settings.humanstartfarms, sizeof(int));
701 rb->write(fd, &superdom_settings.humanstartfarms, sizeof(int));
702 rb->write(fd, &superdom_settings.startcash, sizeof(int));
703 rb->write(fd, &superdom_settings.startfood, sizeof(int));
704 rb->write(fd, &superdom_settings.movesperturn, sizeof(int));
705 rb->close(fd);
706 return 0;
707}
708
709int ingame_menu(void) {
710 int selection = 0;
711
712 MENUITEM_STRINGLIST(ingame_menu,"Super Domination Menu",NULL,
713 "Return to game","Save Game", "Quit");
714
715 selection=rb->do_menu(&ingame_menu,&selection);
716 switch(selection) {
717 case 0:
718 return 0;
719 break;
720 case 1:
721 if(!save_game())
722 rb->splash(HZ, "Game saved");
723 else
724 rb->splash(HZ, "Error in save");
725 break;
726 case 2:
727 return SUPERDOM_QUIT;
728 break;
729 case MENU_ATTACHED_USB:
730 return PLUGIN_USB_CONNECTED;
731 break;
732 }
733 return 0;
734}
735
736int get_number(char* param, int* value) {
737 //int numbers[3][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
738 int numbers[3][3];
739 numbers[0][0] = 1;
740 numbers[0][1] = 2;
741 numbers[0][2] = 3;
742 numbers[1][0] = 4;
743 numbers[1][1] = 5;
744 numbers[1][2] = 6;
745 numbers[2][0] = 7;
746 numbers[2][1] = 8;
747 numbers[2][2] = 9;
748 rb->lcd_clear_display();
749 /* Draw a 3x4 grid */
750 int i,j,x=0,y=0;
751 for(i=0;i<=3;i++) { /* Vertical lines */
752 rb->lcd_drawline(NUM_MARGIN_X+(NUM_BOX_WIDTH*i), NUM_MARGIN_Y,
753 NUM_MARGIN_X+(NUM_BOX_WIDTH*i),
754 NUM_MARGIN_Y+(4*NUM_BOX_HEIGHT));
755 }
756 for(i=0;i<=4;i++) { /* Horizontal lines */
757 rb->lcd_drawline(NUM_MARGIN_X, NUM_MARGIN_Y+(i*NUM_BOX_HEIGHT),
758 NUM_MARGIN_X+(3*NUM_BOX_WIDTH),
759 NUM_MARGIN_Y+(NUM_BOX_HEIGHT*i));
760 }
761 int temp = 1;
762 for(i=0;i<3;i++) {
763 for(j=0;j<3;j++) {
764 rb->snprintf(buf, sizeof(buf), "%d", temp);
765 rb->lcd_putsxy(NUM_MARGIN_X+(j*NUM_BOX_WIDTH)+10,
766 NUM_MARGIN_Y+(i*NUM_BOX_HEIGHT)+8, buf);
767 temp++;
768 }
769 }
770 rb->lcd_putsxy(NUM_MARGIN_X+5, NUM_MARGIN_Y+(3*NUM_BOX_HEIGHT)+8, "CLR");
771 rb->lcd_putsxy(NUM_MARGIN_X+NUM_BOX_WIDTH+10,
772 NUM_MARGIN_Y+(3*NUM_BOX_HEIGHT)+8, "0");
773 rb->lcd_putsxy(NUM_MARGIN_X+2*NUM_BOX_WIDTH+8,
774 NUM_MARGIN_Y+(3*NUM_BOX_HEIGHT)+8, "OK");
775 rb->snprintf(buf,sizeof(buf), "%d", *value);
776 rb->lcd_putsxy(NUM_MARGIN_X+10, NUM_MARGIN_Y+4*NUM_BOX_HEIGHT+10, buf);
777 int height, width;
778 rb->lcd_getstringsize(param, &width, &height);
779 rb->lcd_putsxy((LCD_WIDTH-width)/2, (NUM_MARGIN_Y-height)/2, param);
780 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
781 rb->lcd_fillrect(NUM_MARGIN_X+(NUM_BOX_WIDTH*x),
782 NUM_MARGIN_Y+(NUM_BOX_HEIGHT*y), NUM_BOX_WIDTH+1,
783 NUM_BOX_HEIGHT+1);
784 rb->lcd_set_drawmode(DRMODE_SOLID);
785 int button = 0;
786 rb->lcd_update();
787 while(1) {
788 button = rb->button_get(true);
789 switch(button) {
790 case SUPERDOM_OK:
791 *value *= 10;
792 if(y!=3) {
793 *value += numbers[y][x];
794 } else if(y==3 && x==0) {
795 *value /= 100;
796 } else if(y==3 && x==2) {
797 *value /= 10;
798 return 0;
799 }
800 rb->lcd_set_drawmode(DRMODE_BG|DRMODE_INVERSEVID);
801 rb->lcd_fillrect(0, NUM_MARGIN_Y+4*NUM_BOX_HEIGHT+10,
802 LCD_WIDTH, 30);
803 rb->lcd_set_drawmode(DRMODE_SOLID);
804 rb->snprintf(buf,sizeof(buf), "%d", *value);
805 rb->lcd_putsxy(NUM_MARGIN_X+10,
806 NUM_MARGIN_Y+4*NUM_BOX_HEIGHT+10, buf);
807 break;
808 case SUPERDOM_CANCEL:
809 return 0;
810 break;
811#if CONFIG_KEYPAD != IRIVER_H10_PAD
812 case SUPERDOM_LEFT:
813 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
814 rb->lcd_fillrect(NUM_MARGIN_X+(NUM_BOX_WIDTH*x),
815 NUM_MARGIN_Y+(NUM_BOX_HEIGHT*y),
816 NUM_BOX_WIDTH+1, NUM_BOX_HEIGHT+1);
817 rb->lcd_set_drawmode(DRMODE_SOLID);
818 if(x==0) {
819#if CONFIG_KEYPAD == IPOD_4G_PAD
820 if(y>0)
821 y--;
822 else
823 y=3;
824#endif
825 x=2;
826 } else {
827 x--;
828 }
829 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
830 rb->lcd_fillrect(NUM_MARGIN_X+(NUM_BOX_WIDTH*x),
831 NUM_MARGIN_Y+(NUM_BOX_HEIGHT*y),
832 NUM_BOX_WIDTH+1, NUM_BOX_HEIGHT+1);
833 rb->lcd_set_drawmode(DRMODE_SOLID);
834 break;
835 case SUPERDOM_RIGHT:
836 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
837 rb->lcd_fillrect(NUM_MARGIN_X+(NUM_BOX_WIDTH*x),
838 NUM_MARGIN_Y+(NUM_BOX_HEIGHT*y),
839 NUM_BOX_WIDTH+1, NUM_BOX_HEIGHT+1);
840 rb->lcd_set_drawmode(DRMODE_SOLID);
841 if(x==2) {
842#if CONFIG_KEYPAD == IPOD_4G_PAD
843 if(y==3)
844 y=0;
845 else
846 y++;
847#endif
848 x=0;
849 } else {
850 x++;
851 }
852 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
853 rb->lcd_fillrect(NUM_MARGIN_X+(NUM_BOX_WIDTH*x),
854 NUM_MARGIN_Y+(NUM_BOX_HEIGHT*y),
855 NUM_BOX_WIDTH+1, NUM_BOX_HEIGHT+1);
856 rb->lcd_set_drawmode(DRMODE_SOLID);
857 break;
858#endif
859#if CONFIG_KEYPAD != IPOD_4G_PAD
860 case SUPERDOM_UP:
861 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
862 rb->lcd_fillrect(NUM_MARGIN_X+(NUM_BOX_WIDTH*x),
863 NUM_MARGIN_Y+(NUM_BOX_HEIGHT*y),
864 NUM_BOX_WIDTH+1, NUM_BOX_HEIGHT+1);
865 rb->lcd_set_drawmode(DRMODE_SOLID);
866 if(y==0) {
867#if CONFIG_KEYPAD == IRIVER_H10_PAD
868 if(x > 0)
869 x--;
870 else
871 x=2;
872#endif
873 y=3;
874 } else {
875 y--;
876 }
877 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
878 rb->lcd_fillrect(NUM_MARGIN_X+(NUM_BOX_WIDTH*x),
879 NUM_MARGIN_Y+(NUM_BOX_HEIGHT*y),
880 NUM_BOX_WIDTH+1, NUM_BOX_HEIGHT+1);
881 rb->lcd_set_drawmode(DRMODE_SOLID);
882 break;
883 case SUPERDOM_DOWN:
884 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
885 rb->lcd_fillrect(NUM_MARGIN_X+(NUM_BOX_WIDTH*x),
886 NUM_MARGIN_Y+(NUM_BOX_HEIGHT*y),
887 NUM_BOX_WIDTH+1, NUM_BOX_HEIGHT+1);
888 rb->lcd_set_drawmode(DRMODE_SOLID);
889 if(y==3) {
890#if CONFIG_KEYPAD == IRIVER_H10_PAD
891 if(x < 2)
892 x++;
893 else
894 x=0;
895#endif
896 y=0;
897 } else {
898 y++;
899 }
900 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
901 rb->lcd_fillrect(NUM_MARGIN_X+(NUM_BOX_WIDTH*x),
902 NUM_MARGIN_Y+(NUM_BOX_HEIGHT*y),
903 NUM_BOX_WIDTH+1, NUM_BOX_HEIGHT+1);
904 rb->lcd_set_drawmode(DRMODE_SOLID);
905 break;
906#endif
907 default:
908 if (rb->default_event_handler(button) == SYS_USB_CONNECTED)
909 {
910 return PLUGIN_USB_CONNECTED;
911 }
912 break;
913 }
914 rb->lcd_update();
915 }
916 return 0;
917}
918
919int buy_resources_menu(void) {
920 int selection,tempmenu,nummen;
921
922 MENUITEM_STRINGLIST(res_menu, "Buy Resources", NULL, "Buy men ($1)",
923 "Buy tank ($300)", "Buy plane ($600)", "Buy Farm ($1150)",
924 "Buy Factory ($1300)", "Buy Nuke ($2000)",
925 "Finish buying", "Game menu");
926
927resources_menu:
928 selection=rb->do_menu(&res_menu,&selection);
929 switch(selection) {
930 case 0:
931 nummen = 0;
932 if(get_number("How many men would you like?", &nummen)
933 == PLUGIN_USB_CONNECTED)
934 return PLUGIN_USB_CONNECTED;
935 if(humanres.cash>=nummen) {
936 rb->splash(HZ, "Where do you want to place them?");
937 tempmenu = select_square();
938 switch(tempmenu) {
939 case 0:
940 rb->splash(HZ, "Cancelled");
941 break;
942 case 2:
943 if(board[cursor.x][cursor.y].colour == COLOUR_LIGHT) {
944 humanres.men += nummen;
945 board[cursor.x][cursor.y].men += nummen;
946 humanres.cash -= nummen;
947 } else {
948 rb->splash(HZ,"Can't place men on enemy territory");
949 }
950 break;
951 case PLUGIN_USB_CONNECTED:
952 return PLUGIN_USB_CONNECTED;
953 break;
954 }
955 } else {
956 rb->splash(HZ, "Not enough money!");
957 }
958 goto resources_menu;
959 break;
960 case 1:
961 if(humanres.cash>=300) {
962 rb->splash(HZ, "Where do you want to place the tank?");
963 tempmenu = select_square();
964 switch(tempmenu) {
965 case 0:
966 rb->splash(HZ, "Cancelled");
967 goto resources_menu;
968 break;
969 case PLUGIN_USB_CONNECTED:
970 return PLUGIN_USB_CONNECTED;
971 break;
972 }
973 if(board[cursor.x][cursor.y].colour == COLOUR_LIGHT) {
974 if(board[cursor.x][cursor.y].tank) {
975 rb->splash(HZ, "There is already a tank there");
976 } else {
977 board[cursor.x][cursor.y].tank = true;
978 humanres.cash -= 300;
979 humanres.tanks++;
980 }
981 } else {
982 rb->splash(HZ, "Can't place men on enemy territory");
983 }
984 } else {
985 rb->splash(HZ, "Not enough money!");
986 }
987 goto resources_menu;
988 break;
989 case 2:
990 if(humanres.cash>=600) {
991 rb->splash(HZ, "Where do you want to place the plane?");
992 tempmenu = select_square();
993 switch(tempmenu) {
994 case 0:
995 rb->splash(HZ, "Cancelled");
996 goto resources_menu;
997 break;
998 case PLUGIN_USB_CONNECTED:
999 return PLUGIN_USB_CONNECTED;
1000 break;
1001 }
1002 if(board[cursor.x][cursor.y].colour == COLOUR_LIGHT) {
1003 if(board[cursor.x][cursor.y].plane) {
1004 rb->splash(HZ, "There is already a plane there");
1005 } else {
1006 board[cursor.x][cursor.y].plane = true;
1007 humanres.cash -= 600;
1008 humanres.planes++;
1009 }
1010 } else {
1011 rb->splash(HZ, "Can't place men on enemy territory");
1012 }
1013 } else {
1014 rb->splash(HZ, "Not enough money!");
1015 }
1016 goto resources_menu;
1017 break;
1018 case 3:
1019 if(humanres.cash>=1150) {
1020 rb->splash(HZ, "Where do you want to place the farm?");
1021 tempmenu = select_square();
1022 switch(tempmenu) {
1023 case 0:
1024 rb->splash(HZ, "Cancelled");
1025 goto resources_menu;
1026 break;
1027 case PLUGIN_USB_CONNECTED:
1028 return PLUGIN_USB_CONNECTED;
1029 break;
1030 }
1031 if(board[cursor.x][cursor.y].colour == COLOUR_LIGHT) {
1032 if(board[cursor.x][cursor.y].farm) {
1033 rb->splash(HZ, "There is already a farm there");
1034 } else {
1035 board[cursor.x][cursor.y].farm = true;
1036 humanres.cash -= 1150;
1037 humanres.farms++;
1038 }
1039 } else {
1040 rb->splash(HZ, "Can't build on enemy territory");
1041 }
1042 } else {
1043 rb->splash(HZ, "Not enough money!");
1044 }
1045 goto resources_menu;
1046 break;
1047 case 4:
1048 if(humanres.cash>=1300) {
1049 rb->splash(HZ, "Where do you want to place the industrial"
1050 " plant?");
1051 tempmenu = select_square();
1052 switch(tempmenu) {
1053 case 0:
1054 rb->splash(HZ, "Cancelled");
1055 goto resources_menu;
1056 break;
1057 case PLUGIN_USB_CONNECTED:
1058 return PLUGIN_USB_CONNECTED;
1059 break;
1060 }
1061 if(board[cursor.x][cursor.y].colour == COLOUR_LIGHT) {
1062 if(board[cursor.x][cursor.y].ind) {
1063 rb->splash(HZ, "There is already an industrial"
1064 " plant there");
1065 } else {
1066 board[cursor.x][cursor.y].ind = true;
1067 humanres.cash -= 1300;
1068 humanres.inds++;
1069 }
1070 } else {
1071 rb->splash(HZ, "Can't build on enemy territory");
1072 }
1073 } else {
1074 rb->splash(HZ, "Not enough money!");
1075 }
1076 goto resources_menu;
1077 break;
1078 case 5:
1079 if(humanres.cash>=2000) {
1080 rb->splash(HZ, "Where do you want to place the nuke?");
1081 tempmenu = select_square();
1082 switch(tempmenu) {
1083 case 0:
1084 rb->splash(HZ, "Cancelled");
1085 goto resources_menu;
1086 break;
1087 case PLUGIN_USB_CONNECTED:
1088 return PLUGIN_USB_CONNECTED;
1089 break;
1090 }
1091 if(board[cursor.x][cursor.y].colour == COLOUR_LIGHT) {
1092 if(board[cursor.x][cursor.y].nuke) {
1093 rb->splash(HZ, "There is already a nuke there");
1094 } else {
1095 board[cursor.x][cursor.y].nuke = true;
1096 humanres.cash -= 2000;
1097 humanres.nukes++;
1098 }
1099 } else {
1100 rb->splash(HZ, "Can't place a nuke on enemy territory");
1101 }
1102 } else {
1103 rb->splash(HZ, "Not enough money!");
1104 }
1105 goto resources_menu;
1106 break;
1107 case 6:
1108 return 0;
1109 break;
1110 case MENU_ATTACHED_USB:
1111 return PLUGIN_USB_CONNECTED;
1112 break;
1113 }
1114 return 0;
1115}
1116
1117int move_unit(void) {
1118 int selection, nummen;
1119 struct cursor from;
1120
1121 MENUITEM_STRINGLIST(move_unit_menu, "Move unit", NULL, "Move men",
1122 "Move tank", "Move plane");
1123 selection=rb->do_menu(&move_unit_menu,&selection);
1124 switch(selection) {
1125 case 0:
1126 rb->splash(HZ, "Select where to move troops from");
1127 if(select_square() == PLUGIN_USB_CONNECTED)
1128 return PLUGIN_USB_CONNECTED;
1129 if(board[cursor.x][cursor.y].colour == COLOUR_LIGHT) {
1130 if(board[cursor.x][cursor.y].men) {
1131 from.x = cursor.x;
1132 from.y = cursor.y;
1133 nummen = board[from.x][from.y].men;
1134 if(get_number("How many men do you want to move?",
1135 &nummen) == PLUGIN_USB_CONNECTED)
1136 return PLUGIN_USB_CONNECTED;
1137 if(nummen > board[from.x][from.y].men) {
1138 rb->splash(HZ, "You don't have that many troops.");
1139 } else {
1140 rb->splash(HZ,"Select where to move the troops to");
1141 if(select_square() == PLUGIN_USB_CONNECTED)
1142 return PLUGIN_USB_CONNECTED;
1143 if((board[cursor.x][cursor.y].colour == COLOUR_LIGHT) &&
1144 (abs(cursor.x - from.x) <= 1) &&
1145 abs(cursor.y - from.y) <= 1) {
1146 board[from.x][from.y].men -= nummen;
1147 board[cursor.x][cursor.y].men += nummen;
1148 humanres.moves--;
1149 return 0;
1150 }
1151 }
1152 } else {
1153 rb->splash(HZ, "You don't have any troops there");
1154 }
1155 } else {
1156 rb->splash(HZ, "Can't move enemy troops");
1157 }
1158 break;
1159 case 1:
1160 rb->splash(HZ, "Select where you want to move the tank from");
1161 if(select_square() == PLUGIN_USB_CONNECTED)
1162 return PLUGIN_USB_CONNECTED;
1163 if(board[cursor.x][cursor.y].colour == COLOUR_LIGHT) {
1164 if(board[cursor.x][cursor.y].tank) {
1165 from.x = cursor.x;
1166 from.y = cursor.y;
1167 rb->splash(HZ, "Select where you want"
1168 " to move the tank to");
1169 if(select_square() == PLUGIN_USB_CONNECTED)
1170 return PLUGIN_USB_CONNECTED;
1171 if((board[cursor.x][cursor.y].colour == COLOUR_LIGHT)&&
1172 (abs(cursor.x-from.x) <= 1) &&
1173 (abs(cursor.y-from.y) <= 1)) {
1174 if(board[cursor.x][cursor.y].tank) {
1175 rb->splash(HZ, "There is already a tank there");
1176 } else {
1177 board[from.x][from.y].tank = false;
1178 board[cursor.x][cursor.y].tank = true;
1179 humanres.moves--;
1180 return 0;
1181 }
1182 } else {
1183 rb->splash(HZ, "Invalid move");
1184 }
1185 } else {
1186 rb->splash(HZ, "You don't have a tank there");
1187 }
1188 } else {
1189 rb->splash(HZ, "That isn't your territory");
1190 }
1191 break;
1192 case 2:
1193 rb->splash(HZ, "Select where you want"
1194 " to move the plane from");
1195 if(select_square() == PLUGIN_USB_CONNECTED)
1196 return PLUGIN_USB_CONNECTED;
1197 if(board[cursor.x][cursor.y].colour == COLOUR_LIGHT) {
1198 if(board[cursor.x][cursor.y].plane) {
1199 from.x = cursor.x;
1200 from.y = cursor.y;
1201 rb->splash(HZ, "Select where you want"
1202 " to move the plane to");
1203 if(select_square() == PLUGIN_USB_CONNECTED)
1204 return PLUGIN_USB_CONNECTED;
1205 if(board[cursor.x][cursor.y].colour == COLOUR_LIGHT) {
1206 if(board[cursor.x][cursor.y].plane) {
1207 rb->splash(HZ,"There is already a plane there");
1208 } else {
1209 board[from.x][from.y].plane = false;
1210 board[cursor.x][cursor.y].plane = true;
1211 humanres.moves--;
1212 return 0;
1213 }
1214 } else {
1215 rb->splash(HZ, "Invalid move");
1216 }
1217 } else {
1218 rb->splash(HZ, "You don't have a plane there");
1219 }
1220 } else {
1221 rb->splash(HZ, "That isn't your territory");
1222 }
1223 break;
1224 }
1225 return 0;
1226}
1227
1228int movement_menu(void) {
1229 int selection, tempmenu;
1230 bool menu_quit = false;
1231
1232 MENUITEM_STRINGLIST(move_menu, "Movement", NULL, "Move unit",
1233 "Buy additional moves ($100)", "Launch nuclear missile",
1234 "Check map", "Finish moving", "Game menu");
1235
1236 while(!menu_quit) {
1237 selection=rb->do_menu(&move_menu,&selection);
1238 switch(selection) {
1239 case 0:
1240 if(humanres.moves) {
1241 if(move_unit()==PLUGIN_USB_CONNECTED)
1242 return PLUGIN_USB_CONNECTED;
1243 } else {
1244 rb->splash(HZ, "You have no more moves left."
1245 " You can buy more for $100 each.");
1246 }
1247 break;
1248 case 1:
1249 if(humanres.cash > 100) {
1250 humanres.moves++;
1251 humanres.cash -= 100;
1252 rb->snprintf(buf, sizeof(buf), "You now have %d moves",
1253 humanres.moves);
1254 rb->splash(HZ, buf);
1255 }
1256 break;
1257 case 2:
1258 if(humanres.nukes==0) {
1259 rb->splash(HZ, "You do not have any nukes to launch");
1260 } else {
1261 rb->splash(HZ, "Select place to launch nuke from");
1262 if(select_square() == PLUGIN_USB_CONNECTED) {
1263 return PLUGIN_USB_CONNECTED;
1264 }
1265 if(board[cursor.x][cursor.y].nuke) {
1266 rb->splash(HZ, "Select place to target with nuke");
1267 if(select_square() == PLUGIN_USB_CONNECTED) {
1268 return PLUGIN_USB_CONNECTED;
1269 }
1270 board[cursor.x][cursor.y].men = 0;
1271 board[cursor.x][cursor.y].tank = 0;
1272 board[cursor.x][cursor.y].plane = 0;
1273 board[cursor.x][cursor.y].ind = 0;
1274 board[cursor.x][cursor.y].nuke = 0;
1275 board[cursor.x][cursor.y].farm = 0;
1276 /* TODO: Fallout carried by wind */
1277 }
1278 }
1279 break;
1280 case 3:
1281 if(select_square() == PLUGIN_USB_CONNECTED)
1282 return PLUGIN_USB_CONNECTED;
1283 break;
1284 case 4:
1285 return 0;
1286 break;
1287 case 5:
1288 tempmenu = ingame_menu();
1289 switch(tempmenu) {
1290 case PLUGIN_USB_CONNECTED:
1291 return PLUGIN_USB_CONNECTED;
1292 break;
1293 case SUPERDOM_QUIT:
1294 return SUPERDOM_QUIT;
1295 break;
1296 }
1297 break;
1298 case MENU_ATTACHED_USB:
1299 return PLUGIN_USB_CONNECTED;
1300 break;
1301 }
1302 }
1303 return 0;
1304}
1305
1306int show_inventory(void) {
1307 rb->lcd_clear_display();
1308 rb->lcd_puts(1, 0, "Inventory");
1309 char men[20], tanks[20], planes[20], inds[20], farms[20], nukes[20],
1310 cash[20], food[20], bank[20];
1311 rb->snprintf(men, sizeof(men), "Men: %d", humanres.men);
1312 rb->snprintf(tanks, sizeof(tanks), "Tanks: %d", humanres.tanks);
1313 rb->snprintf(planes, sizeof(planes), "Planes: %d", humanres.planes);
1314 rb->snprintf(inds, sizeof(inds), "Factories: %d", humanres.inds);
1315 rb->snprintf(farms, sizeof(farms), "Farms: %d", humanres.farms);
1316 rb->snprintf(nukes, sizeof(nukes), "Nukes: %d", humanres.nukes);
1317 rb->snprintf(cash, sizeof(cash), "Cash: %d", humanres.cash);
1318 rb->snprintf(food, sizeof(food), "Food: %d", humanres.food);
1319 rb->snprintf(bank, sizeof(bank), "Bank: %d", humanres.bank);
1320 rb->lcd_puts(2, 1, men);
1321 rb->lcd_puts(2, 2, tanks);
1322 rb->lcd_puts(2, 3, planes);
1323 rb->lcd_puts(2, 4, inds);
1324 rb->lcd_puts(2, 5, farms);
1325 rb->lcd_puts(2, 6, nukes);
1326 rb->lcd_puts(2, 7, cash);
1327 rb->lcd_puts(2, 8, food);
1328 rb->lcd_puts(2, 9, bank);
1329 rb->lcd_update();
1330 if(rb->default_event_handler(rb->button_get(true)) == SYS_USB_CONNECTED) {
1331 return PLUGIN_USB_CONNECTED;
1332 } else {
1333 return 0;
1334 }
1335}
1336
1337int production_menu(void) {
1338 int selection, tempbank, tempmenu;
1339
1340 MENUITEM_STRINGLIST(prod_menu, "Production", NULL, "Buy resources",
1341 "Show inventory", "Check map", "Invest money",
1342 "Withdraw money", "Finish turn", "Game menu");
1343
1344 while(1) {
1345 selection=rb->do_menu(&prod_menu,&selection);
1346 switch(selection) {
1347 case 0:
1348 tempmenu = buy_resources_menu();
1349 switch(tempmenu) {
1350 case PLUGIN_USB_CONNECTED:
1351 return PLUGIN_USB_CONNECTED;
1352 break;
1353 case SUPERDOM_QUIT:
1354 return SUPERDOM_QUIT;
1355 break;
1356 }
1357 break;
1358 case 1:
1359 tempmenu = show_inventory();
1360 switch(tempmenu) {
1361 case 0:
1362 break;
1363 case PLUGIN_USB_CONNECTED:
1364 return PLUGIN_USB_CONNECTED;
1365 break;
1366 }
1367 break;
1368 case 2:
1369 tempmenu = select_square();
1370 switch(tempmenu) {
1371 case PLUGIN_USB_CONNECTED:
1372 return PLUGIN_USB_CONNECTED;
1373 break;
1374 case SUPERDOM_QUIT:
1375 return SUPERDOM_QUIT;
1376 break;
1377 case 0:
1378 break;
1379 }
1380 break;
1381 case 3:
1382 tempbank = humanres.cash;
1383 if(get_number("How much do you want to invest?", &tempbank)
1384 == PLUGIN_USB_CONNECTED)
1385 return PLUGIN_USB_CONNECTED;
1386 if(tempbank>humanres.cash) {
1387 rb->splash(HZ, "You don't have that much cash to invest");
1388 } else {
1389 humanres.cash -= tempbank;
1390 humanres.bank += tempbank;
1391 }
1392 break;
1393 case 4:
1394 tempbank = 0;
1395 if(get_number("How much do you want to withdraw?", &tempbank)
1396 == PLUGIN_USB_CONNECTED)
1397 return PLUGIN_USB_CONNECTED;
1398 if(tempbank>humanres.bank) {
1399 rb->splash(HZ, "You don't have that much cash to withdraw");
1400 } else {
1401 humanres.cash += tempbank;
1402 humanres.bank -= tempbank;
1403 }
1404 break;
1405 case 5:
1406 return 0;
1407 break;
1408 case 6:
1409 tempmenu = ingame_menu();
1410 switch(tempmenu) {
1411 case PLUGIN_USB_CONNECTED:
1412 return PLUGIN_USB_CONNECTED;
1413 break;
1414 case SUPERDOM_QUIT:
1415 return SUPERDOM_QUIT;
1416 break;
1417 }
1418 break;
1419 case MENU_ATTACHED_USB:
1420 return PLUGIN_USB_CONNECTED;
1421 break;
1422 }
1423 }
1424 return 0;
1425}
1426
1427void init_resources(void) {
1428 humanres.cash = superdom_settings.startcash;
1429 humanres.food = superdom_settings.startfood;
1430 humanres.tanks = 0;
1431 humanres.planes = 0;
1432 humanres.nukes = 0;
1433 humanres.inds = 0;
1434 humanres.farms = 0;
1435 humanres.men = 0;
1436 humanres.bank = 0;
1437 humanres.moves = 0;
1438 compres.cash = superdom_settings.startcash;
1439 compres.food = superdom_settings.startfood;
1440 compres.tanks = 0;
1441 compres.planes = 0;
1442 compres.nukes = 0;
1443 compres.inds = 0;
1444 compres.farms = 0;
1445 compres.men = 0;
1446 compres.bank = 0;
1447 compres.moves = 0;
1448}
1449
1450int select_square(void) {
1451 draw_board();
1452 draw_cursor();
1453 update_score();
1454#if LCD_WIDTH >= 220
1455 rb->snprintf(buf, sizeof(buf), "Cash: %d", humanres.cash);
1456 rb->lcd_putsxy(125, LCD_HEIGHT-20, buf);
1457 rb->snprintf(buf, sizeof(buf), "Food: %d", humanres.food);
1458 rb->lcd_putsxy(125, LCD_HEIGHT-10, buf);
1459#endif
1460 rb->lcd_update();
1461 int button = 0;
1462 while(1) {
1463 button = rb->button_get(true);
1464 switch(button) {
1465 case SUPERDOM_CANCEL:
1466 return 0;
1467 break;
1468 case SUPERDOM_OK:
1469 return 2;
1470 break;
1471#if CONFIG_KEYPAD != IRIVER_H10_PAD
1472 case SUPERDOM_LEFT:
1473 case (SUPERDOM_LEFT|BUTTON_REPEAT):
1474 draw_cursor(); /* Deselect the current tile */
1475 if(cursor.x>1) {
1476 cursor.x--;
1477 } else {
1478#if CONFIG_KEYPAD == IPOD_4G_PAD
1479 if(cursor.y>1)
1480 cursor.y--;
1481 else
1482 cursor.y = 10;
1483#endif
1484 cursor.x = 10;
1485 }
1486 update_score();
1487 draw_cursor();
1488 break;
1489 case SUPERDOM_RIGHT:
1490 case (SUPERDOM_RIGHT|BUTTON_REPEAT):
1491 draw_cursor(); /* Deselect the current tile */
1492 if(cursor.x<10) {
1493 cursor.x++;
1494 } else {
1495#if CONFIG_KEYPAD == IPOD_4G_PAD
1496 if(cursor.y<10)
1497 cursor.y++;
1498 else
1499 cursor.y = 1;
1500#endif
1501 cursor.x = 1;
1502 }
1503 update_score();
1504 draw_cursor();
1505 break;
1506#endif
1507#if CONFIG_KEYPAD != IPOD_4G_PAD
1508 case SUPERDOM_UP:
1509 case (SUPERDOM_UP|BUTTON_REPEAT):
1510 draw_cursor(); /* Deselect the current tile */
1511 if(cursor.y>1) {
1512 cursor.y--;
1513 } else {
1514#if CONFIG_KEYPAD == IRIVER_H10_PAD
1515 if(cursor.x > 1)
1516 cursor.x--;
1517 else
1518 cursor.x = 10;
1519#endif
1520 cursor.y = 10;
1521 }
1522 update_score();
1523 draw_cursor();
1524 break;
1525 case SUPERDOM_DOWN:
1526 case (SUPERDOM_DOWN|BUTTON_REPEAT):
1527 draw_cursor(); /* Deselect the current tile */
1528 if(cursor.y<10) {
1529 cursor.y++;
1530 } else {
1531#if CONFIG_KEYPAD == IRIVER_H10_PAD
1532 if(cursor.x < 10)
1533 cursor.x++;
1534 else
1535 cursor.x = 1;
1536#endif
1537 cursor.y = 1;
1538 }
1539 update_score();
1540 draw_cursor();
1541 break;
1542#endif
1543 default:
1544 if (rb->default_event_handler(button) == SYS_USB_CONNECTED)
1545 {
1546 return PLUGIN_USB_CONNECTED;
1547 }
1548 }
1549 }
1550}
1551
1552int killmen(bool human) {
1553 int menkilled,i,j;
1554 int percent;
1555 if(human) {
1556 percent = (humanres.food*1000)/humanres.men;
1557 humanres.food = 0;
1558 } else {
1559 percent = (compres.food*1000)/compres.men;
1560 compres.food = 0;
1561 }
1562 menkilled = 0;
1563 for(i=1;i<12;i++) {
1564 for(j=1;j<12;j++) {
1565 if(board[i][j].colour == human) {
1566 menkilled += ((board[i][j].men * percent)/1000);
1567 board[i][j].men = (board[i][j].men * percent)/1000;
1568 }
1569 }
1570 }
1571
1572 if(human)
1573 humanres.men -= menkilled;
1574 else
1575 compres.men -= menkilled;
1576 return menkilled;
1577}
1578
1579int war_menu(void) {
1580 int selection, tempmenu;
1581
1582 MENUITEM_STRINGLIST(wartime_menu, "War!", NULL,
1583 "Select territory to attack", "Finish turn", "Game menu");
1584
1585 humanres.moves = superdom_settings.movesperturn;
1586 while(humanres.moves) {
1587 selection=rb->do_menu(&wartime_menu,&selection);
1588 switch(selection) {
1589 case 0:
1590 if(select_square() == PLUGIN_USB_CONNECTED)
1591 return PLUGIN_USB_CONNECTED;
1592 if(board[cursor.x][cursor.y].colour == COLOUR_DARK) {
1593 if(calc_strength(COLOUR_LIGHT, cursor.x,
1594 cursor.y) > calc_strength(COLOUR_DARK,
1595 cursor.x, cursor.y)) {
1596 board[cursor.x][cursor.y].colour = COLOUR_LIGHT;
1597 board[cursor.x][cursor.y].tank = 0;
1598 board[cursor.x][cursor.y].men = 0;
1599 board[cursor.x][cursor.y].plane = 0;
1600 board[cursor.x][cursor.y].nuke = 0;
1601 draw_board();
1602 rb->sleep(HZ*2);
1603 humanres.moves--;
1604 } else if(calc_strength(COLOUR_LIGHT, cursor.x, cursor.y)==
1605 calc_strength(COLOUR_DARK, cursor.x, cursor.y)) {
1606 if(rb->rand()%2) {
1607 board[cursor.x][cursor.y].colour = COLOUR_LIGHT;
1608 board[cursor.x][cursor.y].tank = 0;
1609 board[cursor.x][cursor.y].men = 0;
1610 board[cursor.x][cursor.y].plane = 0;
1611 board[cursor.x][cursor.y].nuke = 0;
1612 draw_board();
1613 rb->sleep(HZ*2);
1614 humanres.moves--;
1615 } else {
1616 rb->splash(HZ, "Your troops were unable to"
1617 " overcome the enemy troops");
1618 humanres.moves--;
1619 }
1620 } else {
1621 rb->splash(HZ, "Your troops were unable to overcome"
1622 " the enemy troops");
1623 humanres.moves--;
1624 }
1625 } else {
1626 rb->splash(HZ, "You can't attack your own territory");
1627 }
1628 break;
1629 case 1:
1630 return 0;
1631 break;
1632 case 2:
1633 tempmenu = ingame_menu();
1634 switch(tempmenu) {
1635 case PLUGIN_USB_CONNECTED:
1636 return PLUGIN_USB_CONNECTED;
1637 break;
1638 case SUPERDOM_QUIT:
1639 return SUPERDOM_QUIT;
1640 break;
1641 }
1642 break;
1643 }
1644 }
1645 return 0;
1646}
1647
1648struct threat {
1649 int x;
1650 int y;
1651 int str_diff;
1652};
1653
1654bool place_adjacent(bool tank, int x, int y) {
1655 if(tank) {
1656 if(!board[x-1][y].tank && (board[x][y].colour==board[x-1][y].colour)) {
1657 compres.cash -= 300;
1658 board[x-1][y].tank = true;
1659 compres.tanks++;
1660 return 0;
1661 }
1662 if(!board[x+1][y].tank && (board[x][y].colour==board[x+1][y].colour)) {
1663 compres.cash -= 300;
1664 board[x+1][y].tank = true;
1665 compres.tanks++;
1666 return 0;
1667 }
1668 if(!board[x][y-1].tank && (board[x][y].colour==board[x][y-1].colour)) {
1669 compres.cash -= 300;
1670 board[x][y-1].tank = true;
1671 compres.tanks++;
1672 return 0;
1673 }
1674 if(!board[x][y+1].tank && (board[x][y].colour==board[x][y+1].colour)) {
1675 compres.cash -= 300;
1676 board[x][y+1].tank = true;
1677 compres.tanks++;
1678 return 0;
1679 }
1680 } else {
1681 if(!board[x-1][y].plane && (board[x][y].colour==board[x-1][y].colour)) {
1682 compres.cash -= 600;
1683 board[x-1][y].plane = true;
1684 compres.planes++;
1685 return 0;
1686 }
1687 if(!board[x+1][y].plane && (board[x][y].colour==board[x+1][y].colour)) {
1688 compres.cash -= 600;
1689 board[x+1][y].plane = true;
1690 compres.planes++;
1691 return 0;
1692 }
1693 if(!board[x][y-1].plane && (board[x][y].colour==board[x][y-1].colour)) {
1694 compres.cash -= 600;
1695 board[x][y-1].plane = true;
1696 compres.planes++;
1697 return 0;
1698 }
1699 if(!board[x][y+1].plane && (board[x][y].colour==board[x][y+1].colour)) {
1700 compres.cash -= 600;
1701 board[x][y+1].plane = true;
1702 compres.planes++;
1703 return 0;
1704 }
1705 }
1706 return 1;
1707}
1708
1709bool has_adjacent(int x, int y) {
1710 if((board[x][y].colour == COLOUR_LIGHT) &&
1711 ((board[x-1][y].colour == COLOUR_DARK) ||
1712 (board[x+1][y].colour == COLOUR_DARK) ||
1713 (board[x][y+1].colour == COLOUR_DARK) ||
1714 (board[x][y-1].colour == COLOUR_DARK)))
1715 return 1;
1716 else
1717 return 0;
1718}
1719
1720void find_adjacent(int x, int y, int* adj_x, int* adj_y, bool* full) {
1721 /* Finds adjacent squares, returning squares without tanks on them
1722 * in preference to those with them */
1723 if(((board[x-1][y].tank && (board[x-1][y].colour == COLOUR_DARK)) ||
1724 board[x-1][y].colour != COLOUR_DARK) &&
1725 ((board[x+1][y].tank && (board[x+1][y].colour == COLOUR_DARK)) ||
1726 board[x+1][y].colour != COLOUR_DARK) &&
1727 ((board[x][y-1].tank && (board[x][y-1].colour == COLOUR_DARK)) ||
1728 board[x][y-1].colour != COLOUR_DARK) &&
1729 ((board[x][y+1].tank && (board[x][y+1].colour == COLOUR_DARK)) ||
1730 board[x][y+1].colour != COLOUR_DARK)) {
1731 *full = true;
1732 } else {
1733 *full = false;
1734 }
1735
1736 if(board[x-1][y].colour == COLOUR_DARK) {
1737 *adj_x = x-1;
1738 *adj_y = y;
1739 if(board[x-1][y].tank) {
1740 if(*full)
1741 return;
1742 } else {
1743 return;
1744 }
1745 }
1746 if(board[x+1][y].colour == COLOUR_DARK) {
1747 *adj_x = x+1;
1748 *adj_y = y;
1749 if(board[x+1][y].tank) {
1750 if(*full)
1751 return;
1752 } else {
1753 return;
1754 }
1755 }
1756 if(board[x][y-1].colour == COLOUR_DARK) {
1757 *adj_x = x;
1758 *adj_y = y-1;
1759 if(board[x][y-1].tank) {
1760 if(*full)
1761 return;
1762 } else {
1763 return;
1764 }
1765 }
1766 if(board[x][y+1].colour == COLOUR_DARK) {
1767 *adj_x = x;
1768 *adj_y = y+1;
1769 if(board[x][y+1].tank) {
1770 if(*full)
1771 return;
1772 } else {
1773 return;
1774 }
1775 }
1776}
1777
1778void computer_allocate(void) {
1779 /* Firstly, decide whether to go offensive or defensive.
1780 * This is primarily decided by the human player posing a threat to either
1781 * the computer's farms or factories */
1782 int i, j, k;
1783 bool offensive = true;
1784 struct threat threats[4];
1785 int numthreats = 0;
1786 int total_str_diff = 0;
1787 int men_needed;
1788 struct threat targets[2];
1789 int numtargets;
1790 struct cursor adj;
1791 bool full = false;
1792 for(i=1;i<12;i++) {
1793 for(j=1;j<12;j++) {
1794 if((board[i][j].colour == COLOUR_DARK) &&
1795 (calc_strength(COLOUR_DARK,i,j) <
1796 calc_strength(COLOUR_LIGHT,i,j))) {
1797 if(board[i][j].ind || board[i][j].farm) {
1798 if(numthreats < 3) {
1799 offensive = false;
1800 threats[numthreats].x = i;
1801 threats[numthreats].y = j;
1802 threats[numthreats].str_diff =
1803 calc_strength(COLOUR_LIGHT,i,j) -
1804 calc_strength(COLOUR_DARK,i,j);
1805 numthreats++;
1806 }
1807 }
1808 }
1809 }
1810 }
1811 if(offensive) {
1812 /* The AI is going to go straight for the throat here and attack
1813 * the player's farms and factories. The amount of cash
1814 * the AI has to spend will determine how many targets there are */
1815 if(compres.cash > 1200) {
1816 /* 1200 is a figure I pulled out of nowhere. Adjust as needed */
1817 numtargets = 2;
1818 } else {
1819 numtargets = 1;
1820 }
1821 /* Work out which target(s) to attack. They must have adjacent squares
1822 * owned by the computer. If none are found just place troops in
1823 * random places around the map until we run out of money */
1824 k = 0;
1825 while(k<numtargets) {
1826 for(i=1;i<12;i++) {
1827 for(j=1;j<12;j++) {
1828 if((board[i][j].colour == COLOUR_LIGHT) &&
1829 (board[i][j].ind || board[i][j].farm) &&
1830 has_adjacent(i,j)) {
1831 targets[k].x = i;
1832 targets[k].y = j;
1833 targets[k].str_diff = abs(calc_strength(COLOUR_LIGHT,
1834 i, j) - calc_strength(COLOUR_DARK,
1835 i, j));
1836 k++;
1837 }
1838 }
1839 }
1840 }
1841 if(k == 0) {
1842 /* No targets found! Randomly pick squares and if they're owned
1843 * by the computer then stick a tank on it. */
1844 rb->srand(*rb->current_tick);
1845 while(compres.cash >= 300) {
1846 i = rb->rand()%11 + 1;
1847 j = rb->rand()%11 + 1;
1848 if(board[i][j].colour == COLOUR_DARK) {
1849 if(compres.cash >= 300) {
1850 if(!board[i][j].tank) {
1851 board[i][j].tank = true;
1852 compres.tanks++;
1853 compres.cash -= 300;
1854 draw_board();
1855 rb->sleep(HZ);
1856 }
1857 }
1858 }
1859 }
1860 compres.bank += compres.cash;
1861 compres.cash = 0;
1862 } else {
1863 for(i=0;i<k;i++) {
1864 men_needed = targets[i].str_diff + 20;
1865 find_adjacent(targets[i].x,targets[i].y, &adj.x, &adj.y, &full);
1866 while(((calc_strength(COLOUR_LIGHT, targets[i].x, targets[i].y)
1867 + 20) > calc_strength(COLOUR_DARK, targets[i].x,
1868 targets[i].y)) && compres.cash > 0) {
1869 /* While we still need them keep placing men */
1870 if(compres.cash >= 300 && !full) {
1871 if(board[adj.x][adj.y].tank) {
1872 find_adjacent(targets[i].x, targets[i].y,
1873 &adj.x, &adj.y, &full);
1874 } else {
1875 board[adj.x][adj.y].tank = true;
1876 compres.tanks++;
1877 compres.cash -= 300;
1878 draw_board();
1879 rb->sleep(HZ);
1880 }
1881 } else {
1882 men_needed = (calc_strength(COLOUR_LIGHT, targets[i].x,
1883 targets[i].y) + 20 -
1884 calc_strength(COLOUR_DARK, targets[i].x,
1885 targets[i].y))*1000/133;
1886 if(compres.cash >= men_needed) {
1887 board[adj.x][adj.y].men += men_needed;
1888 compres.men += men_needed;
1889 compres.cash -= men_needed;
1890 compres.bank += compres.cash;
1891 compres.cash = 0;
1892 } else {
1893 board[adj.x][adj.y].men += compres.cash;
1894 compres.men += compres.cash;
1895 compres.cash = 0;
1896 }
1897 draw_board();
1898 rb->sleep(HZ);
1899 }
1900 }
1901 }
1902 compres.bank += compres.cash;
1903 compres.cash = 0;
1904 }
1905 } else {
1906 /* Work out what to place on each square to defend it.
1907 * Tanks are preferential because they do not require food,
1908 * but if the budget is tight then we fall back onto troops.
1909 * Conversely if cash is not an issue and there are already tanks in
1910 * place planes will be deployed. We would like a margin of at least
1911 * 20 points to be safe. */
1912
1913 for(i=0;i<numthreats;i++) {
1914 total_str_diff += threats[i].str_diff;
1915 }
1916 if((total_str_diff+20)*10 > compres.cash) {
1917 /* Not enough cash to accomodate all threats using tanks alone -
1918 * use men as a backup */
1919 for(i=0;i<numthreats;i++) {
1920 men_needed = ((threats[i].str_diff + 20)*1000)/133;
1921 if(compres.cash >= men_needed) {
1922 board[threats[i].x][threats[i].y].men += men_needed;
1923 compres.cash -= men_needed;
1924 compres.men += men_needed;
1925 draw_board();
1926 rb->sleep(HZ);
1927 } else {
1928 board[threats[i].x][threats[i].y].men += compres.cash;
1929 compres.men += compres.cash;
1930 compres.cash = 0;
1931 draw_board();
1932 rb->sleep(HZ);
1933 }
1934 }
1935 } else if((total_str_diff+20)*15 < compres.cash) {
1936 /* Enough money to pay their way by planes */
1937 for(i=0;i<numthreats;i++) {
1938 while(calc_strength(COLOUR_DARK,threats[i].x, threats[i].y) <
1939 (calc_strength(COLOUR_LIGHT,threats[i].x, threats[i].y) +
1940 20)) {
1941 if(board[threats[i].x][threats[i].y].plane) {
1942 if(place_adjacent(0, threats[i].x, threats[i].y)) {
1943 /* No room for any more planes, revert to men */
1944 men_needed = (calc_strength(COLOUR_LIGHT,
1945 threats[i].x, threats[i].y) + 20 -
1946 calc_strength(COLOUR_DARK,
1947 threats[i].x, threats[i].y)*1000/133);
1948 if(compres.cash >= men_needed) {
1949 compres.cash -= men_needed;
1950 compres.men += men_needed;
1951 board[threats[i].x][threats[i].y].men +=
1952 men_needed;
1953 draw_board();
1954 rb->sleep(HZ);
1955 }
1956 }
1957 } else {
1958 if(compres.cash >= 600) {
1959 board[threats[i].x][threats[i].y].plane = true;
1960 compres.cash -= 600;
1961 compres.planes++;
1962 draw_board();
1963 rb->sleep(HZ);
1964 }
1965 }
1966 }
1967 }
1968 } else {
1969 /* Tanks it is */
1970 for(i=0;i<numthreats;i++) {
1971 while(calc_strength(COLOUR_DARK,threats[i].x, threats[i].y) <
1972 (calc_strength(COLOUR_LIGHT,threats[i].x, threats[i].y) +
1973 20) && compres.cash > 0) {
1974 if(board[threats[i].x][threats[i].y].tank) {
1975 if(place_adjacent(1, threats[i].x, threats[i].y)) {
1976 /* No room for any more tanks, revert to men */
1977 men_needed = (calc_strength(COLOUR_LIGHT,
1978 threats[i].x, threats[i].y) + 20 -
1979 calc_strength(COLOUR_DARK,
1980 threats[i].x, threats[i].y)*1000/133);
1981 if(compres.cash >= men_needed) {
1982 compres.cash -= men_needed;
1983 compres.men += men_needed;
1984 board[threats[i].x][threats[i].y].men +=
1985 men_needed;
1986 draw_board();
1987 rb->sleep(HZ);
1988 }
1989 }
1990 } else {
1991 if(compres.cash >= 300) {
1992 board[threats[i].x][threats[i].y].tank = true;
1993 compres.tanks++;
1994 compres.cash -= 300;
1995 draw_board();
1996 rb->sleep(HZ);
1997 }
1998 }
1999 }
2000 }
2001 }
2002 compres.bank += compres.cash;
2003 compres.cash = 0;
2004 }
2005}
2006
2007int find_adj_target(int x, int y, struct cursor* adj) {
2008 /* Find a square next to a computer's farm or factory owned by the player
2009 * that is vulnerable. Return 1 on success, 0 otherwise */
2010 if(board[x+1][y].colour == COLOUR_LIGHT &&
2011 calc_strength(COLOUR_LIGHT,x+1,y)<=calc_strength(COLOUR_DARK,x+1,y)) {
2012 adj->x = x+1;
2013 adj->y = y;
2014 return 1;
2015 }
2016 if(board[x-1][y].colour == COLOUR_LIGHT &&
2017 calc_strength(COLOUR_LIGHT,x-1,y)<=calc_strength(COLOUR_DARK,x-1,y)) {
2018 adj->x = x-1;
2019 adj->y = y;
2020 return 1;
2021 }
2022 if(board[x][y+1].colour == COLOUR_LIGHT &&
2023 calc_strength(COLOUR_LIGHT,x,y+1)<=calc_strength(COLOUR_DARK,x,y+1)) {
2024 adj->x = x;
2025 adj->y = y+1;
2026 return 1;
2027 }
2028 if(board[x][y-1].colour == COLOUR_LIGHT &&
2029 calc_strength(COLOUR_LIGHT,x,y-1)<=calc_strength(COLOUR_DARK,x,y-1)) {
2030 adj->x = x;
2031 adj->y = y-1;
2032 return 1;
2033 }
2034 return 0;
2035}
2036
2037void computer_war(void) {
2038 /* Work out where to attack - prioritise the defence of buildings */
2039 int i, j;
2040 struct cursor adj;
2041
2042 while(compres.moves) {
2043 for(i=1;i<12;i++) {
2044 for(j=1;j<12;j++) {
2045 if((board[i][j].colour == COLOUR_DARK) &&
2046 (board[i][j].farm || board[i][j].ind)) {
2047 if(find_adj_target(i, j, &adj) && compres.moves) {
2048 if(calc_strength(COLOUR_LIGHT, adj.x, adj.y) ==
2049 calc_strength(COLOUR_DARK, adj.x, adj.y)) {
2050 rb->srand(*rb->current_tick);
2051 if(rb->rand()%2) {
2052 board[adj.x][adj.y].colour = COLOUR_DARK;
2053 board[adj.x][adj.y].tank = false;
2054 board[adj.x][adj.y].plane = false;
2055 board[adj.x][adj.y].nuke = false;
2056 humanres.men -= board[adj.x][adj.y].men;
2057 board[adj.x][adj.y].men = 0;
2058 draw_board();
2059 rb->sleep(HZ);
2060 compres.moves--;
2061 } else {
2062 rb->splash(HZ*2, "The computer attempted"
2063 " to attack, but the"
2064 " invasion was pushed"
2065 " back");
2066 compres.moves--;
2067 }
2068 } else {
2069 if(compres.moves) {
2070 board[adj.x][adj.y].colour = COLOUR_DARK;
2071 board[adj.x][adj.y].tank = false;
2072 board[adj.x][adj.y].plane = false;
2073 board[adj.x][adj.y].nuke = false;
2074 humanres.men -= board[adj.x][adj.y].men;
2075 board[adj.x][adj.y].men = 0;
2076 draw_board();
2077 rb->sleep(HZ);
2078 compres.moves--;
2079 }
2080 }
2081 }
2082 }
2083 }
2084 }
2085 if(compres.moves) {
2086 /* Defence stage done, move on to OFFENCE */
2087 for(i=1;i<12;i++) {
2088 for(j=1;j<12;j++) {
2089 if(board[i][j].colour == COLOUR_LIGHT && compres.moves &&
2090 (board[i][j].ind || board[i][j].farm) &&
2091 (calc_strength(COLOUR_DARK, i, j) >=
2092 calc_strength(COLOUR_LIGHT, i, j))) {
2093 if(calc_strength(COLOUR_DARK, i, j) ==
2094 calc_strength(COLOUR_LIGHT, i, j)) {
2095 if(rb->rand()%2) {
2096 board[i][j].colour = COLOUR_DARK;
2097 board[i][j].tank = false;
2098 board[i][j].plane = false;
2099 board[i][j].nuke = false;
2100 board[i][j].men = 0;
2101 draw_board();
2102 rb->sleep(HZ);
2103 compres.moves--;
2104 } else {
2105 rb->splash(HZ*2, "The computer attempted to "
2106 "attack, but the invasion was"
2107 " pushed back");
2108 compres.moves--;
2109 }
2110 } else {
2111 board[i][j].colour = COLOUR_DARK;
2112 board[i][j].tank = false;
2113 board[i][j].plane = false;
2114 board[i][j].nuke = false;
2115 board[i][j].men = 0;
2116 draw_board();
2117 rb->sleep(HZ);
2118 compres.moves--;
2119 }
2120 }
2121 }
2122 }
2123 while(compres.moves > 0) {
2124 /* Spend leftover moves wherever attacking randomly */
2125 rb->srand(*rb->current_tick);
2126 i = (rb->rand()%10)+1;
2127 j = (rb->rand()%10)+1;
2128 if(board[i][j].colour == COLOUR_LIGHT &&
2129 (calc_strength(COLOUR_DARK, i, j) >=
2130 calc_strength(COLOUR_LIGHT, i, j))) {
2131 if(calc_strength(COLOUR_DARK, i, j) ==
2132 calc_strength(COLOUR_LIGHT, i, j)) {
2133 if(rb->rand()%2) {
2134 board[i][j].colour = COLOUR_DARK;
2135 board[i][j].tank = false;
2136 board[i][j].plane = false;
2137 board[i][j].nuke = false;
2138 board[i][j].men = 0;
2139 draw_board();
2140 rb->sleep(HZ);
2141 compres.moves--;
2142 } else {
2143 rb->splash(HZ*2, "The computer attempted to"
2144 " attack, but the invasion was"
2145 " pushed back");
2146 compres.moves--;
2147 }
2148 } else {
2149 board[i][j].colour = COLOUR_DARK;
2150 board[i][j].tank = false;
2151 board[i][j].plane = false;
2152 board[i][j].nuke = false;
2153 board[i][j].men = 0;
2154 draw_board();
2155 rb->sleep(HZ);
2156 compres.moves--;
2157 }
2158 }
2159 }
2160 }
2161 }
2162}
2163
2164int load_game(char* file) {
2165 int fd;
2166
2167 fd = rb->open(file, O_RDONLY);
2168 if(fd == 0) {
2169 DEBUGF("Couldn't open savegame\n");
2170 return -1;
2171 }
2172 rb->read(fd, buf, 5);
2173 if(rb->strcmp(buf, "SSGv2")) {
2174 rb->splash(HZ, "Invalid/incompatible savegame\n");
2175 return -1;
2176 }
2177 rb->read(fd, &humanres.cash, sizeof(humanres.cash));
2178 rb->read(fd, &humanres.food, sizeof(humanres.food));
2179 rb->read(fd, &humanres.bank, sizeof(humanres.bank));
2180 rb->read(fd, &humanres.planes, sizeof(humanres.planes));
2181 rb->read(fd, &humanres.tanks, sizeof(humanres.tanks));
2182 rb->read(fd, &humanres.men, sizeof(humanres.men));
2183 rb->read(fd, &humanres.nukes, sizeof(humanres.nukes));
2184 rb->read(fd, &humanres.inds, sizeof(humanres.inds));
2185 rb->read(fd, &humanres.farms, sizeof(humanres.farms));
2186 rb->read(fd, &humanres.moves, sizeof(humanres.moves));
2187 rb->read(fd, &compres.cash, sizeof(humanres.cash));
2188 rb->read(fd, &compres.food, sizeof(humanres.food));
2189 rb->read(fd, &compres.bank, sizeof(humanres.bank));
2190 rb->read(fd, &compres.planes, sizeof(humanres.planes));
2191 rb->read(fd, &compres.tanks, sizeof(humanres.tanks));
2192 rb->read(fd, &compres.men, sizeof(humanres.men));
2193 rb->read(fd, &compres.nukes, sizeof(humanres.nukes));
2194 rb->read(fd, &compres.inds, sizeof(humanres.inds));
2195 rb->read(fd, &compres.farms, sizeof(humanres.farms));
2196 rb->read(fd, &compres.moves, sizeof(humanres.moves));
2197 rb->read(fd, board, sizeof(board));
2198 rb->read(fd, &superdom_settings.compstartfarms, sizeof(int));
2199 rb->read(fd, &superdom_settings.compstartinds, sizeof(int));
2200 rb->read(fd, &superdom_settings.humanstartfarms, sizeof(int));
2201 rb->read(fd, &superdom_settings.humanstartfarms, sizeof(int));
2202 rb->read(fd, &superdom_settings.startcash, sizeof(int));
2203 rb->read(fd, &superdom_settings.startfood, sizeof(int));
2204 rb->read(fd, &superdom_settings.movesperturn, sizeof(int));
2205 return 0;
2206}
2207
2208void default_settings(void) {
2209 superdom_settings.compstartfarms = 1;
2210 superdom_settings.compstartinds = 1;
2211 superdom_settings.humanstartfarms = 2;
2212 superdom_settings.humanstartinds = 2;
2213 superdom_settings.startcash = 0;
2214 superdom_settings.startfood = 0;
2215 superdom_settings.movesperturn = 2;
2216}
2217
2218int average_strength(bool colour) {
2219 /* This function calculates the average strength of the given player,
2220 * used to determine when the computer wins or loses. */
2221 int i,j;
2222 int totalpower = 0;
2223 for(i=0;i<12;i++) {
2224 for(j=0;j<12;j++) {
2225 if(board[i][j].colour != -1) {
2226 totalpower += calc_strength(colour, i, j);
2227 }
2228 }
2229 }
2230 return totalpower/100;
2231}
2232
2233enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
2234{
2235 int tempmenu;
2236 rb = api;
2237 bool statusbar_setting;
2238 statusbar_setting = rb->global_settings->statusbar;
2239 rb->global_settings->statusbar = false;
2240 cursor.x = 1;
2241 cursor.y = 1;
2242 default_settings();
2243 if(parameter) {
2244 if(load_game(parameter) != 0) {
2245 DEBUGF("Loading failed, generating new game\n");
2246 init_resources();
2247 init_board();
2248 } else {
2249 goto startyear;
2250 }
2251 } else {
2252 init_resources();
2253 init_board();
2254 }
2255
2256 bool play = false;
2257 while(!play) {
2258 switch(menu()) {
2259 case 0:
2260 play = true;
2261 break;
2262 case 2:
2263 rb->global_settings->statusbar = statusbar_setting;
2264 return PLUGIN_OK;
2265 break;
2266 }
2267 }
2268 gen_resources();
2269startyear:
2270 if((average_strength(COLOUR_LIGHT) - average_strength(COLOUR_DARK)) > 15) {
2271 rb->splash(HZ*4, "The computer has surrendered. You win.");
2272 rb->global_settings->statusbar = statusbar_setting;
2273 return PLUGIN_OK;
2274 }
2275 if((average_strength(COLOUR_DARK) - average_strength(COLOUR_LIGHT)) > 15) {
2276 rb->splash(HZ*4, "Your army have suffered terrible morale from the bleak prospects of winning. You lose");
2277 rb->global_settings->statusbar = statusbar_setting;
2278 return PLUGIN_OK;
2279 }
2280 tempmenu = production_menu();
2281 switch(tempmenu) {
2282 case PLUGIN_USB_CONNECTED:
2283 rb->global_settings->statusbar = statusbar_setting;
2284 return PLUGIN_USB_CONNECTED;
2285 break;
2286 case SUPERDOM_QUIT:
2287 rb->global_settings->statusbar = statusbar_setting;
2288 return PLUGIN_OK;
2289 break;
2290 }
2291 computer_allocate();
2292 humanres.moves += superdom_settings.movesperturn;
2293 tempmenu = movement_menu();
2294 switch(tempmenu) {
2295 case PLUGIN_USB_CONNECTED:
2296 rb->global_settings->statusbar = statusbar_setting;
2297 return PLUGIN_USB_CONNECTED;
2298 break;
2299 case SUPERDOM_QUIT:
2300 rb->global_settings->statusbar = statusbar_setting;
2301 return PLUGIN_OK;
2302 break;
2303 }
2304 if(humanres.men) {
2305 if(humanres.food > humanres.men) {
2306 rb->snprintf(buf, sizeof(buf), "Your men ate %d units of food",
2307 humanres.men);
2308 humanres.food -= humanres.men;
2309 } else {
2310 rb->snprintf(buf, sizeof(buf), "There was not enough food to feed"
2311 " all your men, %d men have died of starvation",
2312 killmen(COLOUR_LIGHT));
2313 }
2314 rb->splash(HZ*2, buf);
2315 }
2316 if(compres.men) {
2317 if(compres.food < compres.men) {
2318 rb->snprintf(buf, sizeof(buf), "The computer does not have enough"
2319 " food to feed its men. %d have ided of starvation",
2320 killmen(COLOUR_DARK));
2321 rb->splash(HZ, buf);
2322 }
2323 }
2324 tempmenu = war_menu();
2325 switch(tempmenu) {
2326 case PLUGIN_USB_CONNECTED:
2327 rb->global_settings->statusbar = statusbar_setting;
2328 return PLUGIN_USB_CONNECTED;
2329 break;
2330 case SUPERDOM_QUIT:
2331 rb->global_settings->statusbar = statusbar_setting;
2332 return PLUGIN_OK;
2333 break;
2334 }
2335 compres.moves += superdom_settings.movesperturn;
2336 computer_war();
2337 gen_resources();
2338 goto startyear;
2339 rb->global_settings->statusbar = statusbar_setting;
2340 return PLUGIN_OK;
2341}
diff --git a/apps/plugins/viewers.config b/apps/plugins/viewers.config
index 143b593dc4..0f70dc737d 100644
--- a/apps/plugins/viewers.config
+++ b/apps/plugins/viewers.config
@@ -35,3 +35,4 @@ tzx,viewers/zxbox,12
35z80,viewers/zxbox,12 35z80,viewers/zxbox,12
36zzz,viewers/properties,- 36zzz,viewers/properties,-
37colours,rocks/text_editor,11 37colours,rocks/text_editor,11
38ssg,rocks/superdom,-