]> git.pond.sub.org Git - empserver/blob - src/util/ore.c
Indented with src/scripts/indent-emp.
[empserver] / src / util / ore.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  *  ore.c: Create a world
29  * 
30  *  Known contributors to this file:
31  *     Thomas Ruschak
32  */
33
34 /*
35  * In the oceans, it puts oil = (2d6-4)*10+d10, fert = (2d6-2)*10+d10
36  *                        (max of 127 in both cases)
37  *
38  * For islands smaller than ISLANDSIZE, it puts in normal
39  *     resources. (These are assumed to be small non-start islands)
40  * For islands at least ISLANDSIZE big, it makes normal fert,
41  *     but it uses the MIN, OIL, GOLD, and URAN arrays to find out
42  *     what resources to put there. The intent is to find all start
43  *     islands, and give them all a pre-determined spread of stuff.
44  *     To change the stuff, just change the MIN, OIL, GOLD, and URAN arrays.
45  *
46  * For example, if the GOLD array is 90,80,70,60, it'll try to put 1
47  *     sector with 90 gold, 1 with 80 gold, 1 with 70, and 1 with 60 gold
48  *     on each island of at least ISLANDSIZE. It will not overrun start
49  *     sectors, and should be run AFTER you have placed capitals.
50  */
51
52 * /
53 #if defined(aix) || defined(linux) || defined(solaris)
54 #include <unistd.h>
55 #endif /* aix or linux */
56 #include <stdio.h>
57 #include <fcntl.h>
58 #include "misc.h"
59 #include "var.h"
60 #include "sect.h"
61 #include "gamesdef.h"
62 #include "file.h"
63 #include "path.h"
64 #include "xy.h"
65 #include "prototypes.h"
66 #define XPLATES         WORLD_X/2
67 #define YPLATES         WORLD_Y
68 #define YbyX            (YPLATES*XPLATES/8)
69 #define ISLANDSIZE      25
70 #define ISLANDMAX       1000
71 int MIN[] = { 90, 85, 85, 85, 70, 70, 70, 70, 70 };
72 int OIL[] = { 90, 80, 70, 60, 50 };
73 int GOLD[] = { 90, 80, 70, 60, 50 };
74 int URAN[] = { 90, 80, 70, 60, 50 };
75
76 #define MIN_TYPE        0
77 #define OIL_TYPE        1
78 #define GOLD_TYPE       2
79 #define URAN_TYPE       3
80
81 struct sctstr sects[YPLATES * XPLATES];
82 u_char s[WORLD_Y][WORLD_X];
83 short c[WORLD_Y][WORLD_X];
84 short e[WORLD_Y][WORLD_X];
85 int size[YbyX];
86 int goldchance[YbyX];
87 int ironchance[YbyX];
88 int oilchance[YbyX];
89 int fertchance[YbyX];
90 int urchance[YbyX];
91 int ix[ISLANDMAX], iy[ISLANDMAX], ic[ISLANDMAX], in = 0;
92 int cont = 0;
93
94 void makec();
95 void makeore();
96 int place();
97 int nearelev();
98
99 int
100 main(argc, argp)
101 int argc;
102 s_char **argp;
103 {
104     register struct sctstr *sp;
105     register int y;
106     register int x;
107     int sectf;
108     time_t now;
109     s_char *sectfil = NULL;
110     int xx, x1, y1;
111     extern char *optarg;
112     int opt;
113     char *config_file = NULL;
114
115
116     while ((opt = getopt(argc, argp, "e:s:")) != EOF) {
117         switch (opt) {
118         case 'e':
119             config_file = optarg;
120             break;
121         case 's':
122             sectfil = optarg;
123             break;
124         }
125     }
126
127     emp_config(config_file);
128
129     if (sectfil == NULL)
130         sectfil = empfile[EF_SECTOR].file;
131     time(&now);
132     srandom((unsigned int)now);
133     sectf = open(sectfil, O_RDWR, 0);
134     if (sectf < 0) {
135         perror(sectfil);
136         exit(1);
137     }
138     read(sectf, sects, sizeof(sects));
139     sp = sects;
140     for (y = 0; y < WORLD_Y; y++) {
141         for (x = 0; x < WORLD_X; x++) {
142             if (((x ^ y) & 1))
143                 continue;
144             c[sp->sct_y][sp->sct_x] = 0;
145             s[sp->sct_y][sp->sct_x] = sp->sct_type;
146             e[sp->sct_y][sp->sct_x] = sp->sct_elev;
147             sp++;
148         }
149     }
150     for (y = 0; y < WORLD_Y; y++) {
151         for (x = 0; x < WORLD_X; x++) {
152             if (((x ^ y) & 1))
153                 continue;
154             if (c[y][x] != 0)
155                 continue;
156             if (s[y][x] == SCT_WATER)
157                 continue;
158
159             makec(x, y, 0);
160
161             for (y1 = 0; y1 < WORLD_Y; y1++)
162                 for (x1 = 0; x1 < WORLD_X; x1++)
163                     if (c[y1][x1] < 0) {
164                         size[cont]++;
165                         c[y1][x1] = cont;
166                     }
167             if (size[cont] == 0)
168                 continue;
169             if (size[cont] >= ISLANDSIZE) {
170                 xx = ISLANDSIZE / 2;
171                 for (y1 = 0; y1 < WORLD_Y; y1++)
172                     for (x1 = 0; x1 < WORLD_X; x1++)
173                         if (c[y1][x1] == cont) {
174                             if (--xx == 0) {
175                                 ix[in] = x1;
176                                 iy[in] = y1;
177                                 ic[in] = cont;
178                                 in++;
179                             }
180                         }
181                 printf("Found island %d of size %d at %d,%d\n",
182                        in, size[cont], ix[in - 1], iy[in - 1]);
183             } else {
184                 printf("Found islet %d of size %d\n", cont, size[cont]);
185                 for (y1 = 0; y1 < WORLD_Y; y1++)
186                     for (x1 = 0; x1 < WORLD_X; x1++)
187                         if (c[y1][x1] == cont)
188                             c[y1][x1] = ISLANDMAX + 1;
189             }
190         }
191     }
192
193     sp = sects;
194     for (y = 0; y < WORLD_Y; y++) {
195         for (x = 0; x < WORLD_X; x++) {
196             if (((x ^ y) & 1))
197                 continue;
198             makeore(sp++);
199         }
200     }
201     for (x = 0; x < in; x++) {
202         printf("Making ore for island %d\n", x);
203         place(x, MIN, sizeof(MIN) / sizeof(int), OFFSET(sctstr, sct_min),
204               "MIN");
205         place(x, URAN, sizeof(URAN) / sizeof(int),
206               OFFSET(sctstr, sct_uran), "URAN");
207         place(x, OIL, sizeof(OIL) / sizeof(int), OFFSET(sctstr, sct_oil),
208               "OIL");
209         place(x, GOLD, sizeof(GOLD) / sizeof(int),
210               OFFSET(sctstr, sct_gmin), "GOLD");
211     }
212
213     lseek(sectf, 0L, 0);
214     write(sectf, sects, sizeof(sects));
215     close(sectf);
216     exit(0);
217 }
218
219 #define max(a,b) (a < b ? b : a)
220
221 void
222 makec(x, y, n)
223 int x;
224 int y;
225 int n;
226 {
227     register int dy;
228     register int dx;
229     register int dir;
230
231     if (s[y][x] == SCT_WATER)
232         return;
233
234     if (c[y][x] != 0)
235         return;
236
237     if (n == 0)
238         n = ++cont;
239
240     c[y][x] = -1;
241
242     for (dir = 1; dir <= 6; dir++) {
243         dx = (diroff[dir][0] + x + WORLD_X) % WORLD_X;
244         dy = (diroff[dir][1] + y + WORLD_Y) % WORLD_Y;
245         makec(dx, dy, n);
246     }
247 }
248
249 #define MINIMUM(x,y) (x > y ? y : x)
250 #define MAXIMUM(x,y) (x > y ? x : y)
251
252 void
253 makeore(sp)
254 register struct sctstr *sp;
255 {
256     int elev;
257     int oil, gmin, iron, fertil, ur;
258     int lev;
259     int i;
260     int x, y;
261
262     if (sp->sct_type == SCT_SANCT)
263         return;
264
265     y = sp->sct_y;
266     x = sp->sct_x;
267
268     elev = e[y][x];
269     lev = (elev * 12 + nearelev(x, y)) / 18;
270     i = c[y][x];
271     oil = 0;
272     iron = 0;
273     gmin = 0;
274     fertil = 0;
275     ur = 0;
276
277     if (sp->sct_type == SCT_WATER) {
278         oil = MAXIMUM(((roll(6) + roll(6) - 4) * 10 + roll(10)), 0);
279         sp->sct_oil = MINIMUM(oil, 127);
280         fertil = MAXIMUM(((roll(6) + roll(6) - 2) * 12 + roll(10)), 0);
281         sp->sct_fertil = MINIMUM(fertil, 127);
282         return;
283     }
284     iron = roll(100) + 100 - roll(100);
285     oil = roll(100) + 100 - roll(100);
286     ur = roll(100) + 100 - roll(100);
287     gmin = roll(100) + 100 - roll(100);
288     fertil = 85 + 100 - roll(100);
289
290     iron = MAXIMUM(iron, 0);
291     oil = MAXIMUM(oil, 0);
292     ur = MAXIMUM(ur, 0);
293     gmin = MAXIMUM(gmin, 0);
294     fertil = MAXIMUM(fertil, 0);
295     iron = MINIMUM(iron, 127);
296     oil = MINIMUM(oil, 127);
297     ur = MINIMUM(ur, 127);
298     gmin = MINIMUM(gmin, 127);
299     fertil = MINIMUM(fertil, 127);
300
301     sp->sct_fertil = fertil;
302     if (i > ISLANDMAX) {
303         sp->sct_oil = oil;
304         sp->sct_min = iron;
305         sp->sct_gmin = gmin;
306         sp->sct_uran = ur;
307     } else {
308         fertil -= 20;
309         fertil = MAXIMUM(fertil, 0);
310         fertil = MINIMUM(fertil, 127);
311         sp->sct_fertil = fertil;
312     }
313 }
314
315 int
316 nearelev(x, y)
317 int x;
318 int y;
319 {
320     int dir;
321     int dx;
322     int dy;
323     int level;
324
325     level = 0;
326     for (dir = 1; dir <= 6; dir++) {
327         dx = (diroff[dir][0] + x + WORLD_X) % WORLD_X;
328         dy = (diroff[dir][1] + y + WORLD_Y) % WORLD_Y;
329         level += e[dy][dx];
330     }
331     return level;
332 }
333
334 /*              Already in libgen.a
335 roll(n)
336         int     n;
337 {
338         return random() % n;
339 }
340 */
341
342 int
343 min(a, b)
344 int a;
345 int b;
346 {
347     if (a < b)
348         return a;
349     return b;
350 }
351
352 int
353 place(island, res, num, offset, restype)
354 int island, res[], num, offset;
355 s_char *restype;
356 {
357     int x1, y1, x2, y2, x3, y3, j, k;
358     int tried[WORLD_Y][WORLD_X];
359     int numtried, there;
360     struct sctstr *foo;
361
362     x1 = ix[island];
363     y1 = iy[island];
364
365     for (k = 0; k < num; k++) {
366
367         x2 = x1;
368         y2 = y1;
369         bzero((s_char *)tried, sizeof(tried));
370         numtried = 0;
371         while ((sects[y2 * XPLATES + x2 / 2].sct_type == SCT_WATER) ||
372                (*
373                 ((u_char *)(((s_char *)&sects[y2 * XPLATES + x2 / 2]) +
374                             offset)) > 0)
375                || (sects[y2 * XPLATES + x2 / 2].sct_type == SCT_MOUNT)) {
376
377             there =
378                 *((u_char *)(((s_char *)&sects[y2 * XPLATES + x2 / 2]) +
379                              offset));
380
381             foo = &sects[y2 * XPLATES + x2 / 2];
382
383             if (sects[y2 * XPLATES + x2 / 2].sct_type == SCT_RURAL) {
384                 if (!tried[y2][x2]) {
385                     tried[y2][x2] = 1;
386                     numtried++;
387                     if (numtried == ISLANDSIZE) {
388                         int a, b;
389                         printf("*** %d) couldn't place %s %d (%d)\n",
390                                island, restype, k, res[k]);
391                         for (a = 0; a < WORLD_Y; a++)
392                             for (b = 0; b < WORLD_X; b++)
393                                 if (tried[a][b])
394                                     printf("\tTried %d,%d\n", b, a);
395                         return (0);
396                     }
397                 }
398             }
399             do {
400                 j = roll(6);
401                 x3 = (diroff[j][0] + x2 + WORLD_X) % WORLD_X;
402                 y3 = (diroff[j][1] + y2 + WORLD_Y) % WORLD_Y;
403             } while (sects[y3 * XPLATES + x3 / 2].sct_type == SCT_WATER);
404             x2 = x3;
405             y2 = y3;
406         }
407
408 /*              sects[y2*XPLATES+x2/2].sct_min = MIN[k]; */
409         *((u_char *)(((s_char *)&sects[y2 * XPLATES + x2 / 2]) + offset)) =
410             res[k];
411     }
412     return (1);
413 }