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