]> git.pond.sub.org Git - empserver/blob - src/util/fairland.c
fa9fd328ed3ab7bddc5681c50e41f449153cdaa3
[empserver] / src / util / fairland.c
1 /*
2  *  Empire - A multi-player, client/server Internet based war game.
3  *  Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak,
4  *                           Ken Stevens, Steve McClure
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 2 of the License, or
9  *  (at your option) any later version.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  *  ---
21  *
22  *  See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the
23  *  related information and legal notices. It is expected that any future
24  *  projects/authors will amend these files as needed.
25  *
26  *  ---
27  *
28  *  fairland.c: Create a nice, new world
29  * 
30  *  Known contributors to this file:
31  *     Ken Stevens, 1995
32  *     Steve McClure, 1998
33  */
34
35 /* define ORE 1 to add resources, define ORE 0 if you want to use another
36    program to add the resources */
37 static int ORE = 1;
38 static int quiet = 0;
39
40 /* If you don't specify these command line arguments, then these are the
41    defaults */
42 #define DEFAULT_SPIKE 10
43 #define DEFAULT_MOUNTAIN 0
44 #define DEFAULT_CONTDIST 2
45 #define DEFAULT_ISLDIST 1
46
47 /* The following five numbers refer to elevation under which (in the case of
48    fertility or oil) or over which (in the case of iron, gold, and uranium)
49    sectors with that elevation will contain that resource.  Elevation ranges
50    from 0 to 100 */
51
52 /* raise FERT_MAX for more fertility */
53 #define FERT_MAX   56
54
55 /* raise OIL_MAX for more oil */
56 #define OIL_MAX    33
57
58 /* lower IRON_MIN for more iron */
59 #define IRON_MIN   22
60
61 /* lower GOLD_MIN for more gold */
62 #define GOLD_MIN   36
63
64 /* lower URAN_MIN for more uranium */
65 #define URAN_MIN   56
66
67 #if defined(aix) || defined(linux) || defined(solaris)
68 #include <unistd.h>
69 #endif /* aix or linux */
70
71 #include <stdio.h>
72 #include <fcntl.h>
73 #include "var.h"
74 #include "misc.h"
75 #include "power.h"
76 #include "nat.h"
77 #include "sect.h"
78 #include "gamesdef.h"
79 #include "file.h"
80 #include "xy.h"
81 #include "optlist.h"
82 #include "prototypes.h"
83
84 /* do not change these 4 defines */
85 #define LANDMIN         1       /* plate altitude for normal land */
86 #define HILLMIN         34      /* plate altitude for hills */
87 #define PLATMIN         36      /* plate altitude for plateau */
88 #define HIGHMIN         98      /* plate altitude for mountains */
89
90 static void qprint(const char *str);
91
92 static const char *outfile = "newcap_script";
93 /* mark the continents with a * so you can tell them
94    from the islands 1 = mark, 0 = don't mark. */
95 static int AIRPORT_MARKER = 0;
96
97 /* don't let the islands crash into each other.
98    1 = don't merge, 0 = merge. */
99 static int DISTINCT_ISLANDS = 1;
100
101 #define XSIZE           ((WORLD_X) / 2) /* basically world x-y size */
102 #define YSIZE           (WORLD_Y)
103 #define STABLE_CYCLE 4          /* stability required for perterbed capitals */
104 #define INFINITY        999     /* a number which means "BIG" */
105
106 /* these defines prevent infinite loops:
107 */
108
109 #define COAST_SEARCH_MAX 200    /* how many times do we look for a coast sector
110                                    when growing continents and islands */
111 #define DRIFT_BEFORE_CHECK ((WORLD_X + WORLD_Y)/2)
112 #define DRIFT_MAX ((WORLD_X + WORLD_Y)*2)
113 #define MOUNTAIN_SEARCH_MAX 1000        /* how long do we try to place mountains */
114
115 /* handy macros:
116 */
117
118 #define new_x(newx) (((newx) + WORLD_X) % WORLD_X)
119 #define new_y(newy) (((newy) + WORLD_Y) % WORLD_Y)
120 #if !defined(_WIN32)
121 #define max(a,b) (a>b?a:b)
122 #endif
123 #define rnd(x) (random() % (x))
124
125 int secs;                       /* number of sectors grown */
126 int ctot;                       /* total number of continents and islands grown */
127 int *isecs;                     /* array of how large each island is */
128
129 int nc, sc, di, sp, pm, ni, is, id;     /* the 8 arguments to this program */
130 int *capx, *capy;               /* location of the nc capitals */
131 int *mc, mcc;                   /* array and counter used for stability
132                                    check when perturbing */
133 int spike;                      /* are we spiking? */
134 int mind;                       /* the final distance between capitals that
135                                    we achieved */
136 int dirx[] = { -2, -1, 1, 2, 1, -1 };   /* gyujnb */
137 int diry[] = { 0, -1, -1, 0, 1, 1 };
138
139 int **own;                      /* owner of the sector.  -1 means water */
140 int **elev;                     /* elevation of the sectors */
141 int **sectx, **secty;           /* the sectors for each continent */
142 int **sectc;                    /* which sectors are on the coast? */
143 int *vector;                    /* used for measuring distances */
144 int *weight;                    /* used for placing mountains */
145 int *dsea, *dmoun;              /* the dist to the ocean and mountain */
146 int the_file;                   /* the file we write everything to */
147 struct sctstr **sects;
148 struct sctstr *sectsbuf;
149 int fl_status;                  /* is anything wrong? */
150 #define STATUS_NO_ROOM (1)      /* there was no room to grow */
151 #define NUMTRIES 10             /* keep trying to grow this many times */
152
153 const char *numletter =
154     "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
155
156 void parse_args(int argc, char *argv[]);
157 int allocate_memory(void);
158 void init(void);
159 int drift(void);
160 void grow_continents(void);
161 void create_elevations(void);
162 void write_sects(void);
163 int write_file(void);
164 void output(void);
165 int write_newcap_script(void);
166 int stable(void);
167 void elevate_land(void);
168 void elevate_sea(void);
169 void translate_continents(void);
170 int map_symbol(int x, int y);
171 static void fl_sct_init(coord x, coord y, s_char *ptr);
172
173 void print_vars(void);
174 void fl_move(int);
175 void next_coast(int c, int x, int y, int *xp, int *yp);
176 void grow_islands(void);
177
178 /****************************************************************************
179   MAIN
180 ****************************************************************************/
181
182 int
183 main(int argc, char *argv[])
184 {
185     int opt;
186     extern int optind;
187     extern char *optarg;
188     extern s_char *datadir;
189     char *config_file = NULL;
190     char tbuf[512];
191     int i = 0;
192
193 #if !defined(_WIN32)
194     while ((opt = getopt(argc, argv, "ae:ioqs:")) != EOF) {
195         switch (opt) {
196         case 'a':
197             AIRPORT_MARKER = 1;
198             break;
199         case 'i':
200             DISTINCT_ISLANDS = 0;
201             break;
202         case 'e':
203             config_file = optarg;
204             break;
205         case 'o':
206             ORE = 0;
207             break;
208         case 'q':
209             quiet = 1;
210             break;
211         case 's':
212             outfile = optarg;
213             break;
214         }
215     }
216 #endif
217     if (config_file == NULL) {
218         sprintf(tbuf, "%s/econfig", datadir);
219         config_file = tbuf;
220     }
221     emp_config(config_file);
222
223 #if !defined(_WIN32)
224     parse_args(argc - optind, argv + optind);
225 #else
226     parse_args(argc - 1, argv + 1);
227 #endif
228     if (allocate_memory() == -1)
229         exit(-1);
230     print_vars();
231
232     do {
233         init();
234         if (!quiet && i)
235             printf("\ntry #%d (out of %d)...", i + 1, NUMTRIES);
236         qprint("\n\n        #*# ...fairland rips open a rift in the datumplane... #*#\n\n");
237         qprint("placing capitals...\n");
238         if (!drift())
239             qprint("fairland: unstable drift -- try increasisg DRIFT_MAX\n");
240         qprint("growing continents...\n");
241         grow_continents();
242     } while (fl_status && ++i < NUMTRIES);
243     if (fl_status) {
244         fputs("ERROR: World not large enough to hold continents\n",
245               stderr);
246         exit(1);
247     }
248     qprint("growing islands:");
249     grow_islands();
250     qprint("\nelevating land...\n");
251     create_elevations();
252     qprint("designating sectors...\n");
253     if (ORE)
254         qprint("adding resources...\n");
255     write_sects();
256     qprint("writing to sectors file...\n");
257     if (write_file() == -1)
258         exit(-1);
259     output();
260     write_newcap_script();
261     exit(0);
262 }
263
264 void
265 print_vars(void)
266 {
267     if (quiet)
268         return;
269     puts("Creating a planet with:\n");
270     printf("%d continents\n", nc);
271     printf("continent size: %d\n", sc);
272     printf("number of islands: %d\n", ni);
273     printf("average size of islands: %d\n", is);
274     printf("spike: %d%%\n", sp);
275     printf("%d%% of land is mountain (each continent will have %d mountains)\n",
276            pm, (pm * sc) / 100);
277     printf("minimum distance between continents: %d\n", di);
278     printf("minimum distance from islands to continents: %d\n", id);
279     printf("World dimensions: %dx%d\n", WORLD_X, WORLD_Y);
280 }
281
282 static int
283 my_sqrt(int n)
284 {
285     int i;
286
287     for (i = 1; i * i < n * 10000; ++i) ;
288     return (i + 50) / 100;
289 }
290
291 /****************************************************************************
292   PARSE COMMAND LINE ARGUMENTS
293 ****************************************************************************/
294
295 void
296 parse_args(int argc, char *argv[])
297 {
298     if (argc < 2 || argc > 8) {
299         puts("fairland syntax:\n");
300         puts("fairland [-e config] [-aiqo] [-s script] <nc> <sc> [<ni>] [<is>] [<sp>] [<pm>] [<di>] [<id>]");
301         puts("-q = quiet, -o = no ore produced");
302         puts("-a = Airport marker for continents, -i = islands not distinct");
303         printf("-e = read config file, -s = name of script (default %s)\n",
304                outfile);
305         puts("nc = number of continents [MANDATORY]");
306         puts("sc = continent size [MANDATORY]");
307         puts("ni = number of islands (default = nc)");
308         puts("is = average size of islands (default = sc/2)");
309         printf("sp = spike percentage: 0 = round, 100 = snake (default = %d)\n",
310                DEFAULT_SPIKE);
311         printf("pm = the percentage of land that is mountain (default = %d)\n",
312                DEFAULT_MOUNTAIN);
313         printf("di = the minimum distance between continents (default = %d)\n",
314                DEFAULT_CONTDIST);
315         printf("id = minimum distance from islands to continents (default = %d)\n",
316                DEFAULT_ISLDIST);
317         exit(1);
318     }
319     nc = atoi(argv[0]);
320     if (nc < 1) {
321         puts("fairland: error -- number of continents must be > 0");
322         exit(1);
323     }
324
325     sc = atoi(argv[1]);
326     if (sc < 1) {
327         puts("fairland: error -- size of continents must be > 0");
328         exit(1);
329     }
330
331     if (argc > 2)
332         ni = atoi(argv[2]);
333     else
334         ni = nc;
335
336     if (argc > 3)
337         is = atoi(argv[3]);
338     else
339         is = sc / 2;
340     if (is < 0)
341         is = 0;
342
343     if (argc > 4)
344         sp = atoi(argv[4]);
345     else
346         sp = DEFAULT_SPIKE;
347     if (sp < 0)
348         sp = 0;
349     if (sp > 100)
350         sp = 100;
351
352     if (argc > 5)
353         pm = atoi(argv[5]);
354     else
355         pm = DEFAULT_MOUNTAIN;
356     if (pm < 0)
357         pm = 0;
358
359     if (argc > 6)
360         di = atoi(argv[6]);
361     else
362         di = DEFAULT_CONTDIST;
363
364     if (di < 0) {
365         puts("fairland: error -- distance between continents must be >= 0");
366         exit(1);
367     }
368     if (di > WORLD_X / 2 || di > WORLD_Y / 2) {
369         puts("fairland: error -- distance between continents too large");
370         exit(1);
371     }
372
373     if (argc > 7)
374         id = atoi(argv[7]);
375     else
376         id = DEFAULT_ISLDIST;
377     if (id < 0) {
378         puts("fairland: error -- distance from islands to continents must be >= 0");
379         exit(1);
380     }
381     if (id > WORLD_X || id > WORLD_Y) {
382         puts("fairland: error -- distance from islands to continents too large");
383         exit(1);
384     }
385     if (nc * sc + nc * my_sqrt(sc) * 2 * (di + 1) > WORLD_X * WORLD_Y) {
386         puts("fairland: error -- world not big enough to fit continents.");
387         puts("arguments must satisfy:");
388         puts("nc*sc*sc + nc*sqrt(sc)*2*(di+1) < WORLD_X * WORLD_Y");
389         exit(1);
390     }
391 }
392
393 /****************************************************************************
394   VARIABLE INITIALIZATION
395 ****************************************************************************/
396
397 int
398 allocate_memory(void)
399 {
400     int i;
401     time_t now;
402
403 #if !defined(_WIN32)
404     the_file =
405         open(empfile[EF_SECTOR].file, O_RDWR | O_CREAT | O_TRUNC, 0660);
406 #else
407     the_file =
408         open(empfile[EF_SECTOR].file,
409              O_RDWR | O_CREAT | O_TRUNC | O_BINARY, 0660);
410 #endif
411     if (the_file < 0) {
412         perror(empfile[EF_SECTOR].file);
413         return -1;
414     }
415     sectsbuf =
416         (struct sctstr *)calloc((YSIZE * XSIZE), sizeof(struct sctstr));
417     sects = (struct sctstr **)calloc(YSIZE, sizeof(struct sctstr *));
418     for (i = 0; i < YSIZE; i++)
419         sects[i] = &sectsbuf[XSIZE * i];
420     time(&now);
421 #if !defined(_WIN32)
422     srandom(now + getpid());
423 #else
424     srandom(now);
425 #endif
426     capx = (int *)calloc(nc, sizeof(int));
427     capy = (int *)calloc(nc, sizeof(int));
428     vector = (int *)calloc(WORLD_X + WORLD_Y, sizeof(int));
429     mc = (int *)calloc(STABLE_CYCLE, sizeof(int));
430     own = (int **)calloc(WORLD_X, sizeof(int *));
431     elev = (int **)calloc(WORLD_X, sizeof(int *));
432     for (i = 0; i < WORLD_X; ++i) {
433         own[i] = (int *)calloc(WORLD_Y, sizeof(int));
434         elev[i] = (int *)calloc(WORLD_Y, sizeof(int));
435     }
436     sectx = (int **)calloc(nc + ni, sizeof(int *));
437     secty = (int **)calloc(nc + ni, sizeof(int *));
438     sectc = (int **)calloc(nc + ni, sizeof(int *));
439     isecs = (int *)calloc(nc + ni, sizeof(int));
440     weight = (int *)calloc(max(sc, is * 2), sizeof(int));
441     dsea = (int *)calloc(max(sc, is * 2), sizeof(int));
442     dmoun = (int *)calloc(max(sc, is * 2), sizeof(int));
443     for (i = 0; i < nc; ++i) {
444         sectx[i] = (int *)calloc(sc, sizeof(int));
445         secty[i] = (int *)calloc(sc, sizeof(int));
446         sectc[i] = (int *)calloc(sc, sizeof(int));
447     }
448     for (i = nc; i < nc + ni; ++i) {
449         sectx[i] = (int *)calloc(is * 2, sizeof(int));
450         secty[i] = (int *)calloc(is * 2, sizeof(int));
451         sectc[i] = (int *)calloc(is * 2, sizeof(int));
452     }
453
454     return 0;
455 }
456
457 void
458 init(void)
459 {
460     int i, j, xx = 0, yy = 0;
461
462     mcc = 0;
463     fl_status = 0;
464
465     for (i = 0; i < WORLD_X; ++i) {
466         for (j = 0; j < WORLD_Y; ++j) {
467             own[i][j] = -1;
468             elev[i][j] = -INFINITY;
469         }
470     }
471
472     for (i = 0; i < nc; ++i, xx += 2) {
473         if (xx >= WORLD_X) {
474             ++yy;
475             xx = yy % 2;
476             if (yy == WORLD_Y) {
477                 puts("fairland error: world not big enough for all the continents.\n");
478                 exit(1);
479             }
480         }
481         capx[i] = xx;
482         capy[i] = yy;
483     }
484     for (i = 0; i < STABLE_CYCLE; ++i)
485         mc[i] = i;
486 }
487
488 /****************************************************************************
489   DRIFT THE CAPITALS UNTIL THEY ARE AS FAR AWAY FROM EACH OTHER AS POSSIBLE
490 ****************************************************************************/
491
492 /* How isolated is capital j?
493 */
494 static int
495 iso(int j, int newx, int newy)
496 {
497     int i, md, d = WORLD_X + WORLD_Y;
498
499     for (i = 0; i < nc; ++i) {
500         if (i == j)
501             continue;
502         md = mapdist(capx[i], capy[i], newx, newy);
503         if (md < d)
504             d = md;
505     }
506
507     return d;
508 }
509
510 /* Drift all the capitals
511 */
512 int
513 drift(void)
514 {
515     int i, turns;
516
517     for (turns = 0; turns < DRIFT_MAX; ++turns) {
518         if (turns > DRIFT_BEFORE_CHECK && (mind = stable()))
519             return 1;
520         for (i = 0; i < nc; ++i)
521             fl_move(i);
522     }
523     return 0;
524 }
525
526 /* Check to see if we have stabilized--can we stop drifting the capitals?
527 */
528
529 int
530 stable(void)
531 {
532     int i, isod, d = 0, stab = 1;
533
534     for (i = 0; i < nc; ++i) {
535         isod = iso(i, capx[i], capy[i]);
536         if (isod > d)
537             d = isod;
538     }
539     for (i = 0; i < STABLE_CYCLE; ++i)
540         if (d != mc[i])
541             stab = 0;
542     mc[mcc] = d;
543     mcc = (mcc + 1) % STABLE_CYCLE;
544     return stab ? d : 0;
545 }
546
547 /* This routine does the actual drifting
548 */
549
550 void
551 fl_move(int j)
552 {
553     int i, n, newx, newy;
554
555     for (i = rnd(6), n = 0; n < 6; i = (i + 1) % 6, ++n) {
556         newx = new_x(capx[j] + dirx[i]);
557         newy = new_y(capy[j] + diry[i]);
558         if (iso(j, newx, newy) >= iso(j, capx[j], capy[j])) {
559             capx[j] = newx;
560             capy[j] = newy;
561             return;
562         }
563     }
564 }
565
566 /****************************************************************************
567   GROW THE CONTINENTS
568 ****************************************************************************/
569
570 /* Look for a coastal sector of continent c
571 */
572
573 static void
574 find_coast(int c)
575 {
576     int i, j;
577
578     for (i = 0; i < secs; ++i) {
579         sectc[c][i] = 0;
580         for (j = 0; j < 6; ++j)
581             if (own[new_x(sectx[c][i] + dirx[j])][new_y(secty[c][i] + diry[j])] == -1)
582                 sectc[c][i] = 1;
583     }
584 }
585
586 /* Used for measuring distances
587 */
588 static int
589 next_vector(int n)
590 {
591     int i;
592
593     if (n == 1) {
594         vector[0] += 1;
595         vector[0] %= 6;
596         return vector[0];
597     }
598     for (i = 1; i < n && vector[i] == vector[i - 1]; ++i) ;
599     vector[i - 1] += 1;
600     vector[i - 1] %= 6;
601     return i > 1 || vector[0] > 0;
602 }
603
604 /* Test to see if we're allowed to grow there: the arguments di and id
605 */
606 static int
607 try_to_grow(int c, int newx, int newy, int d)
608 {
609     int i, j, px, py;
610
611     for (i = 1; i <= d; ++i) {
612         for (j = 0; j < i; ++j)
613             vector[j] = 0;
614         do {
615             px = newx;
616             py = newy;
617             for (j = 0; j < i; ++j) {
618                 px = new_x(px + dirx[vector[j]]);
619                 py = new_y(py + diry[vector[j]]);
620             }
621             if (own[px][py] != -1 &&
622                 own[px][py] != c &&
623                 (DISTINCT_ISLANDS || own[px][py] < nc))
624                 return 0;
625         } while (next_vector(i));
626     }
627     sectx[c][secs] = newx;
628     secty[c][secs] = newy;
629     own[newx][newy] = c;
630     return 1;
631 }
632
633 /* Move along the coast in a clockwise direction.
634 */
635
636 void
637 next_coast(int c, int x, int y, int *xp, int *yp)
638 {
639     int i, nx, ny, wat = 0;
640
641     if (secs == 1) {
642         *xp = x;
643         *yp = y;
644         return;
645     }
646
647     for (i = 0; i < 12; ++i) {
648         nx = new_x(x + dirx[i % 6]);
649         ny = new_y(y + diry[i % 6]);
650         if (own[nx][ny] == -1)
651             wat = 1;
652         if (wat && own[nx][ny] == c) {
653             *xp = nx;
654             *yp = ny;
655             return;
656         }
657     }
658 }
659
660 /* Choose a sector to grow from
661 */
662
663 static int
664 new_try(int c)
665 {
666     int i, starti;
667
668     if (secs == 1) {
669         if (sectc[c][0])
670             return 0;
671     } else {
672         i = starti = (spike && sectc[c][secs - 1]) ? secs - 1 : rnd(secs);
673         do {
674             if (sectc[c][i])
675                 return i;
676             i = (i + 1) % secs;
677         } while (i != starti);
678         if (c < nc) {
679             printf("fairland: BUG -- couldn't find coast for continent %c, sector %d.\nPlease mail stevens@math.utoronto.ca.\n",
680                    c + 'a', secs);
681             exit(1);
682         } else
683             return -1;
684     }
685     return -1;
686 }
687
688 /* Grow continent c by 1 sector
689 */
690
691 static int
692 grow_one_sector(int c)
693 {
694     int done, coast_search, try1, x, y, newx, newy, i, n, sx, sy;
695
696     spike = rnd(100) < sp;
697     if ((try1 = new_try(c)) == -1)
698         return 0;
699     x = sx = sectx[c][try1];
700     y = sy = secty[c][try1];
701     coast_search = 0;
702     done = 0;
703     do {
704         if (spike) {
705             for (i = rnd(6), n = 0; n < 12 && !done; i = (i + 1) % 6, ++n) {
706                 newx = new_x(x + dirx[i]);
707                 newy = new_y(y + diry[i]);
708                 if (own[newx][newy] == -1 &&
709                     (n > 5 ||
710                      (own[new_x(x+dirx[(i+5)%6])][new_y(y+diry[(i+5)%6])] == -1 &&
711                       own[new_x(x+dirx[(i+1)%6])][new_y(y+diry[(i+1)%6])] == -1)))
712                     if (try_to_grow(c, newx, newy, c < nc ? di : id))
713                         done = 1;
714             }
715         } else
716             for (i = rnd(6), n = 0; n < 6 && !done; i = (i + 1) % 6, ++n) {
717                 newx = new_x(x + dirx[i]);
718                 newy = new_y(y + diry[i]);
719                 if (own[newx][newy] == -1)
720                     if (try_to_grow(c, newx, newy, c < nc ? di : id))
721                         done = 1;
722             }
723         next_coast(c, x, y, &x, &y);
724         ++coast_search;
725     } while (!done && coast_search < COAST_SEARCH_MAX &&
726              (secs == 1 || x != sx || y != sy));
727     if (!done && c < nc) {
728         if (!quiet)
729             printf("fairland: error -- continent %c had no room to grow!\n",
730                    numletter[c % 62]);
731         fl_status |= STATUS_NO_ROOM;
732     }
733     return done;
734 }
735
736 /* Grow all the continents
737 */
738 void
739 grow_continents(void)
740 {
741     int c;
742
743     for (c = 0; c < nc; ++c) {
744         sectx[c][0] = capx[c];
745         secty[c][0] = capy[c];
746         own[sectx[c][0]][secty[c][0]] = c;
747         sectx[c][1] = new_x(capx[c] + 2);
748         secty[c][1] = capy[c];
749         own[sectx[c][1]][secty[c][1]] = c;
750     }
751
752     for (secs = 2; secs < sc && !fl_status; ++secs) {
753         for (c = 0; c < nc; ++c) {
754             find_coast(c);
755             grow_one_sector(c);
756         }
757     }
758     if (fl_status && !quiet)
759         printf("Only managed to grow %d out of %d sectors.\n", secs, sc);
760     ctot = nc;
761 }
762
763 /****************************************************************************
764   GROW THE ISLANDS
765 ****************************************************************************/
766
767 /* Choose a place to start growing an island from
768 */
769 static int
770 place_island(int c, int *xp, int *yp)
771 {
772     int d, sx, sy;
773     int ssy = rnd(WORLD_Y);
774     int ssx = new_x(rnd(WORLD_X / 2) * 2 + ssy % 2);
775
776     if (ssx > WORLD_X - 2)
777         ssx = new_x(ssx + 2);
778     for (d = di + id; d >= id; --d) {
779         sx = ssx;
780         sy = ssy;
781         *xp = new_x(sx + 2);
782         for (*yp = sy; *xp != sx || *yp != sy; *xp += 2) {
783             if (*xp >= WORLD_X) {
784                 *yp = new_y(*yp + 1);
785                 *xp = (*yp) % 2;
786                 if (*xp == sx && *yp == sy)
787                     break;
788             }
789             if (own[*xp][*yp] == -1 && try_to_grow(c, *xp, *yp, d))
790                 return 1;
791         }
792     }
793     return 0;
794 }
795
796 /* Grow all the islands
797 */
798
799 void
800 grow_islands(void)
801 {
802     int c, x, y, isiz;
803
804     for (c = nc; c < nc + ni; ++c) {
805         secs = 0;
806         if (!place_island(c, &x, &y))
807             return;
808         isiz = 1 + rnd(2 * is - 1);
809         do {
810             ++secs;
811             find_coast(c);
812         } while (secs < isiz && grow_one_sector(c));
813         if (quiet == 0)
814             printf(" %d(%d)", c - nc + 1, secs);
815         isecs[c] = secs;
816         ctot = c;
817     }
818 }
819
820 /****************************************************************************
821   CREATE ELEVATIONS
822 ****************************************************************************/
823 void
824 create_elevations(void)
825 {
826     elevate_land();
827     elevate_sea();
828 }
829
830 /* Generic function for finding the distance to the closest sea, land, or
831    mountain
832 */
833 static int
834 distance_to_what(int x, int y, int flag)
835 {
836     int j, d, px, py;
837
838     for (d = 1; d < 5; ++d) {
839         for (j = 0; j < d; ++j)
840             vector[j] = 0;
841         do {
842             px = x;
843             py = y;
844             for (j = 0; j < d; ++j) {
845                 px = new_x(px + dirx[vector[j]]);
846                 py = new_y(py + diry[vector[j]]);
847             }
848             switch (flag) {
849             case 0:             /* distance to sea */
850                 if (own[px][py] == -1)
851                     return d;
852                 break;
853             case 1:             /* distance to land */
854                 if (own[px][py] != -1)
855                     return d;
856                 break;
857             case 2:             /* distance to mountain */
858                 if (elev[px][py] == INFINITY)
859                     return d;
860                 break;
861             }
862         } while (next_vector(d));
863     }
864     return d;
865 }
866
867 #define ELEV elev[sectx[c][i]][secty[c][i]]
868 #define distance_to_sea() (sectc[c][i]?1:distance_to_what(sectx[c][i], secty[c][i], 0))
869 #define distance_to_mountain() distance_to_what(sectx[c][i], secty[c][i], 2)
870
871 /* Decide where the mountains go
872 */
873 void
874 elevate_land(void)
875 {
876     int i, mountain_search, k, c, total, ns, nm, highest, where, h, newk,
877         r, dk;
878
879     for (c = 0; c < ctot; ++c) {
880         total = 0;
881         ns = (c < nc) ? sc : isecs[c];
882         nm = (pm * ns) / 100;
883
884 /* Place the mountains */
885
886         for (i = 0; i < ns; ++i) {
887             dsea[i] = distance_to_sea();
888             weight[i] = (total += (dsea[i] * dsea[i]));
889         }
890
891         for (k = nm, mountain_search = 0;
892              k && mountain_search < MOUNTAIN_SEARCH_MAX;
893              ++mountain_search) {
894             r = rnd(total);
895             for (i = 0; i < ns; ++i)
896                 if (r < weight[i] && ELEV == -INFINITY &&
897                     (c >= nc ||
898                      ((!(capx[c] == sectx[c][i] &&
899                          capy[c] == secty[c][i])) &&
900                       (!(new_x(capx[c] + 2) == sectx[c][i] &&
901                          capy[c] == secty[c][i]))))) {
902                     ELEV = INFINITY;
903                     break;
904                 }
905             --k;
906         }
907
908 /* Elevate land that is not mountain and not capital */
909
910         for (i = 0; i < ns; ++i)
911             dmoun[i] = distance_to_mountain();
912         dk = (ns - nm - ((c < nc) ? 3 : 1) > 0) ?
913           (100 * (HIGHMIN - LANDMIN)) / (ns - nm - ((c < nc) ? 3 : 1)) :
914           100 * INFINITY;
915         for (k = 100 * (HIGHMIN - 1);; k -= dk) {
916             highest = -INFINITY;
917             where = -1;
918             for (i = 0; i < ns; ++i) {
919                 if (ELEV != INFINITY &&
920                     (c >= nc || ((!(capx[c] == sectx[c][i] &&
921                                     capy[c] == secty[c][i])) &&
922                                  (!(new_x(capx[c] + 2) == sectx[c][i] &&
923                                     capy[c] == secty[c][i]))))) {
924                     h = 3 * (5 - dmoun[i]) + dsea[i];
925                     if (h > highest) {
926                         highest = h;
927                         where = i;
928                     }
929                 }
930             }
931             if (where == -1)
932                 break;
933             newk = k / 100;
934             if (newk >= HILLMIN && newk < PLATMIN)
935                 newk = PLATMIN;
936             if (newk < LANDMIN)
937                 newk = LANDMIN;
938             elev[sectx[c][where]][secty[c][where]] = newk;
939             dsea[where] = -INFINITY;
940             dmoun[where] = INFINITY;
941         }
942
943 /* Elevate the mountains and capitals */
944
945         for (i = 0; i < ns; ++i) {
946             if (ELEV == INFINITY) {
947                 if (dsea[i] == 1)
948                     ELEV = HILLMIN + rnd(PLATMIN - HILLMIN);
949                 else
950                     ELEV = HIGHMIN + rnd((256 - HIGHMIN) / 2) +
951                       rnd((256 - HIGHMIN) / 2);
952             } else if ((c < nc &&
953                         ((capx[c] == sectx[c][i] && capy[c] == secty[c][i]))) ||
954                        ((new_x(capx[c] + 2) == sectx[c][i] &&
955                          capy[c] == secty[c][i])))
956                 ELEV = PLATMIN;
957         }
958     }
959 }
960
961 #define distance_to_land() distance_to_what(x, y, 1)
962
963 void
964 elevate_sea(void)
965 {
966     int x, y;
967
968     for (y = 0; y < WORLD_Y; ++y) {
969         for (x = y % 2; x < WORLD_X; x += 2) {
970             if (elev[x][y] == -INFINITY)
971                 elev[x][y] = -rnd((distance_to_land() * 20 + 27)) - 1;
972         }
973     }
974 }
975
976 /****************************************************************************
977   ADD THE RESOURCES
978 ****************************************************************************/
979
980 static int
981 set_fert(int e)
982 {
983     int fert = 0;
984     if (e < LANDMIN)
985         fert = LANDMIN - e + 40;
986     else if (e < FERT_MAX)
987         fert = (140 * (FERT_MAX - e)) / (FERT_MAX - LANDMIN);
988     if (fert > 120)
989         fert = 120;
990     return fert;
991 }
992
993 static int
994 set_oil(int e)
995 {
996     int oil = 0;
997     if (e < LANDMIN)
998         oil = (LANDMIN - e) * 2 + rnd(2);
999     else if (e <= OIL_MAX)
1000         oil = (120 * (OIL_MAX - e + 1)) / (OIL_MAX - LANDMIN + 1);
1001     if (oil > 100)
1002         oil = 100;
1003     return oil;
1004 }
1005
1006 static int
1007 set_iron(int e)
1008 {
1009     int iron = 0;
1010     if (e >= IRON_MIN && e < HIGHMIN)
1011         iron = (120 * (e - IRON_MIN + 1)) / (HIGHMIN - IRON_MIN);
1012     if (iron > 100)
1013         iron = 100;
1014     return iron;
1015 }
1016
1017 static int
1018 set_gold(int e)
1019 {
1020     int gold = 0;
1021     if (e >= GOLD_MIN) {
1022         if (e < HIGHMIN)
1023             gold = (80 * (e - GOLD_MIN + 1)) / (HIGHMIN - GOLD_MIN);
1024         else
1025             gold = 100 - 20 * HIGHMIN / e;
1026     }
1027     if (gold > 100)
1028         gold = 100;
1029     return gold;
1030 }
1031
1032 static int
1033 set_uran(int e)
1034 {
1035     int uran = 0;
1036     if (e >= URAN_MIN && e < HIGHMIN)
1037         uran = (120 * (e - URAN_MIN + 1)) / (HIGHMIN - URAN_MIN);
1038     if (uran > 100)
1039         uran = 100;
1040     return uran;
1041 }
1042
1043 static void
1044 add_resources(struct sctstr *sct)
1045 {
1046     sct->sct_fertil = set_fert(sct->sct_elev);
1047     sct->sct_oil = set_oil(sct->sct_elev);
1048     sct->sct_min = set_iron(sct->sct_elev);
1049     sct->sct_gmin = set_gold(sct->sct_elev);
1050     sct->sct_uran = set_uran(sct->sct_elev);
1051 }
1052
1053 /****************************************************************************
1054   DESIGNATE THE SECTORS
1055 ****************************************************************************/
1056
1057 void
1058 write_sects(void)
1059 {
1060     register struct sctstr *sct;
1061     int c, x, y, total;
1062
1063     /*  sct = &sects[0][0]; */
1064     sct = sectsbuf;
1065     for (y = 0; y < YSIZE; y++) {
1066         for (x = 0; x < XSIZE; x++, sct++) {
1067             fl_sct_init(x * 2 + (y & 01), y, (s_char *)sct);
1068             total = elev[sct->sct_x][y];
1069             if (total < LANDMIN) {
1070                 sct->sct_type = SCT_WATER;
1071             } else if (total < HILLMIN)
1072                 sct->sct_type = SCT_RURAL;
1073             else if (total < PLATMIN)
1074                 sct->sct_type = SCT_MOUNT;
1075             else if (total < HIGHMIN)
1076                 sct->sct_type = SCT_RURAL;
1077             else
1078                 sct->sct_type = SCT_MOUNT;
1079             sct->sct_elev = total;
1080             sct->sct_newtype = sct->sct_type;
1081             if (ORE)
1082                 add_resources(sct);
1083         }
1084     }
1085     if (AIRPORT_MARKER)
1086         for (c = 0; c < nc; ++c) {
1087             sects[capy[c]][capx[c] / 2 + capy[c] % 2].sct_type = SCT_AIRPT;
1088             sects[capy[c]][capx[c] / 2 + capy[c] % 2].sct_newtype = SCT_AIRPT;
1089         }
1090 }
1091
1092 /****************************************************************************
1093   WRITE ALL THIS STUFF TO THE FILE
1094 ****************************************************************************/
1095 int
1096 write_file(void)
1097 {
1098     int n;
1099
1100     /*  if ((n = write(the_file, sects, sizeof(sects))) < 0) { */
1101     if ((n = write(the_file, sectsbuf, YSIZE * XSIZE * sizeof(struct sctstr))) < 0) {
1102         perror(empfile[EF_SECTOR].file);
1103         return -1;
1104     }
1105     if (n != (int)(YSIZE * XSIZE * sizeof(struct sctstr))) {
1106         printf("%s:partial write\n", empfile[EF_SECTOR].file);
1107         return -1;
1108     }
1109     close(the_file);
1110     return 0;
1111 }
1112
1113 /****************************************************************************
1114   PRINT A PICTURE OF THE MAP TO YOUR SCREEN
1115 ****************************************************************************/
1116 void
1117 output(void)
1118 {
1119     int i, j;
1120     if (opt_BLITZ)
1121         translate_continents();
1122     if (quiet == 0) {
1123         for (i = 0; i < WORLD_Y; ++i) {
1124             puts("");
1125             if (i % 2)
1126                 printf(" ");
1127             for (j = i % 2; j < WORLD_X; j += 2) {
1128                 if (own[j][i] == -1)
1129                     printf(". ");
1130                 else {
1131                     printf("%c ", map_symbol(j, i));
1132                 }
1133             }
1134         }
1135     }
1136     if (AIRPORT_MARKER)
1137         printf("\n\nEach continent is marked by a \"*\" on the map (to distinguish them from\nthe islands).  You can redesignate these airfields to wilderness sectors\none at a time, each time you add a new country to the game.\n");
1138 }
1139
1140 /* Reorder the continents from top left to bottom right */
1141 void
1142 translate_continents(void)
1143 {
1144     int i, j, n = 0, k, gotit, c;
1145     int *trans, *trans_cont, *oldcapx, *oldcapy;
1146
1147     trans = (int *)calloc(nc, sizeof(int));
1148     trans_cont = (int *)calloc(nc, sizeof(int));
1149     oldcapx = (int *)calloc(nc, sizeof(int));
1150     oldcapy = (int *)calloc(nc, sizeof(int));
1151
1152     for (i = 0; i < WORLD_Y; ++i) {
1153         for (j = i % 2; j < WORLD_X; j += 2) {
1154             if (own[j][i] > -1 && own[j][i] < nc) {
1155                 gotit = 0;
1156                 for (k = 0; k < n; ++k) {
1157                     if (trans[k] == own[j][i])
1158                         gotit = 1;
1159                 }
1160                 if (!gotit) {
1161                     if (n > nc) {
1162                         printf("fairland: BUG in translate continents!  mail stevens@math.utoronto.ca\n");
1163                         exit(2);
1164                     }
1165                     trans[n] = own[j][i];
1166                     trans_cont[own[j][i]] = n;
1167                     ++n;
1168                 }
1169             }
1170         }
1171     }
1172     for (i = 0; i < WORLD_Y; ++i) {
1173         for (j = i % 2; j < WORLD_X; j += 2) {
1174             if (own[j][i] > -1 && own[j][i] < nc) {
1175                 own[j][i] = trans_cont[own[j][i]];
1176             }
1177         }
1178     }
1179     for (c = 0; c < nc; ++c) {
1180         oldcapx[c] = capx[c];
1181         oldcapy[c] = capy[c];
1182     }
1183     for (c = 0; c < nc; ++c) {
1184         capx[c] = oldcapx[trans[c]];
1185         capy[c] = oldcapy[trans[c]];
1186     }
1187 }
1188
1189 int
1190 map_symbol(int x, int y)
1191 {
1192     int c, iscap = 0;
1193
1194     for (c = 0; c < nc; ++c)
1195         if ((x == capx[c] && y == capy[c])
1196             || (x == new_x(capx[c] + 2) && y == capy[c]))
1197             iscap = 1;
1198     if ((elev[x][y] >= HILLMIN && elev[x][y] < PLATMIN)
1199         || elev[x][y] >= HIGHMIN)
1200         return '^';
1201     return own[x][y] >= nc ? '%' : iscap ? '#' : numletter[own[x][y] % 62];
1202 }
1203
1204 /***************************************************************************
1205   WRITE A SCRIPT FOR PLACING CAPITALS
1206 ****************************************************************************/
1207 int
1208 write_newcap_script(void)
1209 {
1210     int c;
1211     FILE *script = fopen(outfile, "w");
1212
1213     if (!script) {
1214         printf("fairland: error, unable to write to %s.\n", outfile);
1215         return -1;
1216     }
1217
1218     for (c = 0; c < nc; ++c) {
1219         fprintf(script, "add %d %d %d n i\n", c + 1, c + 1, c + 1);
1220         if (AIRPORT_MARKER)
1221             fprintf(script, "des %d,%d -\n", capx[c], capy[c]);
1222         fprintf(script, "newcap %d %d,%d\n", c + 1, capx[c], capy[c]);
1223     }
1224     fprintf(script, "add %d visitor visitor v i\n", c + 1);
1225     ++c;
1226     fclose(script);
1227     if (quiet == 0)
1228         printf("\n\nA script for adding all the countries can be found in \"%s\".\n",
1229              outfile);
1230     if (ORE && quiet == 0)
1231         printf("\t***IMPORTANT: Resources have already been added***\n\tYou do NOT need to run the ore program.\n");
1232     return 0;
1233 }
1234
1235 static void
1236 qprint(const char *str)
1237 {
1238     if (quiet == 0)
1239         fputs(str, stdout);
1240 }
1241
1242 void
1243 fl_sct_init(coord x, coord y, s_char *ptr)
1244 {
1245     struct sctstr *sp = (struct sctstr *)ptr;
1246
1247     sp->ef_type = EF_SECTOR;
1248     sp->sct_x = x;
1249     sp->sct_y = y;
1250     sp->sct_dist_x = x;
1251     sp->sct_dist_y = y;
1252     sp->sct_road = 0;
1253     sp->sct_rail = 0;
1254     sp->sct_defense = 0;
1255 }