comparison src/pl_gen3.c @ 4:aa38447a4b21

First entry of Paradise Server 2.9 patch 10 Beta
author darius
date Sat, 06 Dec 1997 04:37:03 +0000
parents
children
comparison
equal deleted inserted replaced
3:cafa94d86546 4:aa38447a4b21
1 /*--------------------------------------------------------------------------
2 NETREK II -- Paradise
3
4 Permission to use, copy, modify, and distribute this software and its
5 documentation, or any derivative works thereof, for any NON-COMMERCIAL
6 purpose and without fee is hereby granted, provided that this copyright
7 notice appear in all copies. No representations are made about the
8 suitability of this software for any purpose. This software is provided
9 "as is" without express or implied warranty.
10
11 Xtrek Copyright 1986 Chris Guthrie
12 Netrek (Xtrek II) Copyright 1989 Kevin P. Smith
13 Scott Silvey
14 Paradise II (Netrek II) Copyright 1993 Larry Denys
15 Kurt Olsen
16 Brandon Gillespie
17 --------------------------------------------------------------------------*/
18
19 #include "config.h"
20 #include <math.h>
21
22 #include "defs.h"
23 #include "struct.h"
24 #include "data.h"
25 #include "shmem.h"
26 #include "planets.h"
27
28 #define SYSWIDTH (GWIDTH/5.9) /* width of a system */
29
30 #define SYSTEMS 9 /* number of planetary systems */
31
32 /* atmosphere chances form a cascade win rand()%100 */
33 #define PATMOS1 40 /* chance for normal atmosphere */
34 #define PATMOS2 70 /* chance for thin atmosphere */
35 #define PATMOS3 90 /* chance for slightly toxic stmos */
36 #define PPOISON 100 /* chance for poison atmos */
37
38 /* defines that deal with planets resources and types */
39 #define NMETAL 13 /* number of metal deposits */
40 #define NDILYTH 10 /* number of dilythium deposits */
41 #define NARABLE 15 /* number of arable land planets */
42 /* defines that deal with star placement */
43
44 #define GW ((float)GWIDTH) /* size of galaxy in floating point */
45 #define STARBORD (GW*0.27)
46 #define TEAMBORD (GW*0.32)
47 #define STARMIN (GW/5.6)/* min dist between stars */
48 #define STARMAX GW
49 #define TEAMMIN (GW/2.8)/* min dist between team stars */
50 #define TEAMMAX (GW/1.8)/* max dist between team stars */
51
52 /* defines that deal with systems and their planets */
53 #define SYSADD 2 /* number possible above min number */
54 #define SYSBORD (7000.0 + (float)GWIDTH/200) /* min distance from
55 * border wall */
56 #define INDBORD (GW*0.23)
57 #define SYSMIN (5500.0 + (float)GWIDTH/200) /* min distance between
58 * objects */
59 #define SYSMIN2 (SYSMIN*SYSMIN) /* square of sysmin distance */
60 #define SYSPLMIN 5 /* min number of planets for system */
61 #define SYSPLADD 0 /* number of possible extra planets */
62 #define MINARMY 8 /* min numer of armies on a planet */
63 #define MAXARMY 15 /* max number of armies on a planet */
64
65 /* other defines */
66 #define HOMEARMIES 30 /* number of armies on home planets */
67 #define COLONYARMIES 10 /* number of armies for colony planet */
68
69
70 /* defines dealing with growth timers */
71 #define PLGFUEL configvals->plgrow.fuel /* time for growth of fuel
72 * depot */
73 #define PLGAGRI configvals->plgrow.agri /* time for growth of agri */
74 #define PLGREPAIR configvals->plgrow.repair /* time for growth of
75 * repair */
76 #define PLGSHIP configvals->plgrow.shipyard /* time for growth of
77 * shipyard */
78
79
80 #if 0
81 /*-------------------------------GENRESOURCES----------------------------*/
82 /*
83 * This function goes through the planets structure and determines what kind
84 * of atmosphere and what kind of surface the planets have. It generates the
85 * stars that will be used as system centers ans then places atmospheres on
86 * the other planets. It then distributes the resources on the planet
87 * surfaces.
88 */
89
90 static void
91 genresources()
92 {
93 int i; /* looping vars */
94 int t; /* temp var */
95
96 for (i = 0; i < SYSTEMS; i++) /* first planets are stars */
97 planets[i].pl_flags |= PLSTAR; /* or in star flag */
98 for (i = SYSTEMS; i < NUMPLANETS; i++)
99 { /* generate atmospheres */
100 t = lrand48() % 100; /* random # 0-99 */
101 if (t < PATMOS1) /* is it atmosphere type 1 */
102 planets[i].pl_flags |= PLATYPE1;
103 else if (t < PATMOS2) /* is it atmosphere type 2 */
104 planets[i].pl_flags |= PLATYPE2;
105 else if (t < PATMOS3) /* is it atmosphere type 3 */
106 planets[i].pl_flags |= PLATYPE3;
107 else if (t < PPOISON) /* is it poison atmosphere */
108 planets[i].pl_flags |= PLPOISON;
109 }
110 for (i = 0; i < NMETAL; i++)
111 { /* place the metal deposits */
112 t = lrand48() % (NUMPLANETS - SYSTEMS) + SYSTEMS; /* random planet */
113 planets[t].pl_flags |= PLMETAL; /* OR in the metal flag */
114 if (!configvals->resource_bombing)
115 planets[t].pl_flags |= PLREPAIR;
116 }
117 for (i = 0; i < NDILYTH; i++)
118 { /* place the metal deposits */
119 t = lrand48() % (NUMPLANETS - SYSTEMS) + SYSTEMS; /* random planet */
120 planets[t].pl_flags |= PLDILYTH; /* OR in the dilyth flag */
121 planets[t].pl_flags &= ~(PLATMASK | PLARABLE); /* zero off previous
122 * atmos */
123 planets[t].pl_flags |= PLPOISON; /* dilyth poisons atmosphere */
124 if (!configvals->resource_bombing)
125 planets[t].pl_flags |= PLFUEL;
126 }
127 for (i = 0; i < NARABLE; i++)
128 { /* place the metal deposits */
129 t = lrand48() % (NUMPLANETS - SYSTEMS) + SYSTEMS; /* random planet */
130 planets[t].pl_flags |= PLARABLE | PLATYPE1; /* OR in the arable flag */
131 if (!configvals->resource_bombing)
132 planets[t].pl_flags |= PLAGRI;
133 }
134 }
135 #endif
136
137
138
139 #if 0
140 /*--------------------------------PLACESTARS------------------------------*/
141 /*
142 * This function places each system's star. The stars are expected to be in
143 * the first SYSTEMS number of planets. The coordinates of the stars are
144 * placed in the space grid.
145 */
146
147 static int
148 placestars()
149 {
150 int i, j; /* looping vars */
151 double x, y; /* to hold star coordinates */
152 int done; /* flag to indicate done */
153 double dx, dy; /* delta x and y's */
154 int attempts;
155 double min, max, dist, bord, nbwidth;
156 double xoff, yoff;
157
158 for (i = 0; i < SYSTEMS; i++)
159 { /* star for each system */
160 if (i < 2)
161 { /* choose optimal position for first two */
162 min = TEAMMIN2;
163 max = TEAMMAX2;
164 bord = TEAMBORD;
165 }
166 else if (i < 4)
167 {
168 min = TEAMMIN2;
169 max = STARMAX2;
170 bord = STARBORD * 0.8;
171 }
172 else
173 {
174 min = STARMIN2;
175 max = STARMAX2;
176 bord = STARBORD;
177 }
178 nbwidth = GW - 2 * bord;
179 x = drand48() * nbwidth + bord; /* pick intial coords */
180 y = drand48() * nbwidth + bord;
181 xoff = 3574.0 - bord;
182 yoff = 1034.0 - bord;
183 attempts = 0;
184 do
185 { /* do until location found */
186 attempts++;
187 done = 0; /* not done yet */
188 x = bord + fmod(x + xoff, nbwidth); /* offset coords a little */
189 y = bord + fmod(y + yoff, nbwidth); /* every loop */
190 #if 0
191 if ((x > GW - bord) || (x < bord)
192 || (y < bord) || (y > GW - bord))
193 continue; /* too close to border? */
194 #endif
195 done = 1; /* assume valid cord found */
196 for (j = 0; j < i; j++)
197 { /* go through previous stars */
198 dx = fabs(x - (double) planets[j].pl_x);
199 dy = fabs(y - (double) planets[j].pl_y);
200 dist = dx * dx + dy * dy;
201 if (dist < min || dist > max) /* if too close or too far then */
202 done = 0; /* we must get another coord */
203 }
204 } while (!done && attempts < 1000); /* do until location found */
205
206 if (!done)
207 return 0;
208
209 planets[i].pl_owner = NOBODY; /* no team owns a star */
210 planets[i].pl_flags |= PLSTAR; /* mark planet as a star */
211 move_planet(i, (int) x, (int) y, 0);
212 planets[i].pl_system = i + 1; /* mark the sytem number */
213 planets[i].pl_hinfo = ALLTEAM; /* all teams know its a star */
214 for (j = 0; j < MAXTEAM + 1; j++)
215 { /* go put in info for teams */
216 planets[i].pl_tinfo[j].owner = NOBODY; /* nobody owns it */
217 planets[i].pl_tinfo[j].armies = 0;
218 planets[i].pl_tinfo[j].flags = planets[i].pl_flags;
219 }
220 }
221 return 1;
222 }
223 #endif
224
225
226
227 /*-----------------------------PLACESYSTEMS------------------------------*/
228 /*
229 * This function places the planets in each star's system. The function will
230 * return the index of the first planet that was not placed in a system. The
231 * coordinates of the planets are placed in the space grid.
232 */
233
234 static int
235 placesystems()
236 {
237 int i, j, k; /* looping vars */
238 double x, y; /* to hold star coordinates */
239 int done; /* flag to indicate done */
240 double dx, dy; /* delta x and y's */
241 int n; /* number of planet to place */
242 int np; /* number of planets in system */
243 int attempts;
244
245 n = SYSTEMS; /* first planet to place */
246 for (i = 0; i < SYSTEMS; i++)
247 { /* planets for each system */
248 np = SYSPLMIN + lrand48() % (SYSPLADD + 1); /* how many planets */
249 for (k = 0; k < np; k++)
250 { /* go place the planets */
251 attempts = 0;
252 do
253 { /* do until location found */
254 attempts++;
255 done = 0; /* not done yet */
256 dx = (drand48() * SYSWIDTH - SYSWIDTH / 2.0);
257 dy = (drand48() * SYSWIDTH - SYSWIDTH / 2.0);
258 if (dx * dx + dy * dy > (SYSWIDTH / 2.0) * (SYSWIDTH / 2.0))
259 continue; /* might orbit its way out of the galaxy */
260 x = planets[i].pl_x + dx;
261 y = planets[i].pl_y + dy;
262 if ((x > GW - SYSBORD) || (x < SYSBORD)
263 || (y < SYSBORD) || (y > GW - SYSBORD))
264 continue; /* too close to border? */
265
266 done = 1; /* assume valid coord found */
267 for (j = 0; j < n; j++)
268 { /* go through previous planets */
269 dx = fabs(x - (double) planets[j].pl_x);
270 dy = fabs(y - (double) planets[j].pl_y);
271 if (dx * dx + dy * dy < SYSMIN2)
272 { /* if too close to another star */
273 done = 0; /* we must get another coord */
274 }
275 }
276 } while (!done && attempts < 200); /* do until location found */
277
278 if (!done)
279 return 0; /* universe too crowded, try again */
280
281 move_planet(n, (int) x, (int) y, 0);
282 planets[n].pl_system = i + 1; /* mark the sytem number */
283 planets[n].pl_armies = MINARMY + lrand48() % (MAXARMY - MINARMY);
284 n++; /* go to next planet */
285 }
286 }
287 return (n); /* return index of next planet */
288 }
289
290
291
292
293 /*-----------------------------PLACEINDEP------------------------------*/
294 /*
295 * This function places idependent planets that are not in a system. They can
296 * appear anywhere in the galaxy as long as they are not too close to another
297 * planet. The coords are put in the space grid.
298 */
299
300 static int
301 placeindep(n)
302 int n;
303 /* number of planet to start with */
304 {
305 int i, j; /* looping vars */
306 double x, y; /* to hold star coordinates */
307 int done; /* flag to indicate done */
308 double dx, dy; /* delta x and y's */
309 int attempts;
310
311 for (i = n; i < (NUMPLANETS - (WORMPAIRS * 2)); i++)
312 { /* go through rest of planets */
313 x = drand48() * (GW - 2 * INDBORD) + INDBORD; /* pick initial coords */
314 y = drand48() * (GW - 2 * INDBORD) + INDBORD;
315 attempts = 0;
316 do
317 { /* do until location found */
318 attempts++;
319 done = 0; /* not done yet */
320 x = INDBORD + fmod(x + (3574.0 - INDBORD), GW - 2 * INDBORD); /* offset coords a
321 * little */
322 y = INDBORD + fmod(y + (1034.0 - INDBORD), GW - 2 * INDBORD); /* every loop */
323 #if 0
324 if ((x > GW - INDBORD) || (x < INDBORD)
325 || (y < INDBORD) || (y > GW - INDBORD))
326 continue; /* too close to border? */
327 #endif
328 done = 1; /* assume valid coord */
329 for (j = 0; j < n; j++)
330 { /* go through previous planets */
331 dx = fabs(x - (double) planets[j].pl_x);
332 dy = fabs(y - (double) planets[j].pl_y);
333 if (dx * dx + dy * dy < SYSMIN2)
334 { /* if planet to close */
335 done = 0; /* we must get another coord */
336 }
337 }
338 } while (!done && attempts < 200); /* do until location found */
339
340 if (!done)
341 return 0;
342
343 move_planet(n, (int) x, (int) y, 0);
344 planets[n].pl_system = 0; /* mark the no sytem */
345 planets[n].pl_armies = MINARMY + lrand48() % (MAXARMY - MINARMY);
346 n++; /* go to next planet */
347 }
348 for (i = n; i < NUMPLANETS; i++) /* now place wormholes */
349 {
350 x = drand48() * GW; /* pick intial coords */
351 y = drand48() * GW;
352 attempts = 0;
353 do
354 { /* do until location found */
355 attempts++;
356 done = 0; /* not done yet */
357 x = fmod(x + 3574.0, GW); /* offset coords a little */
358 y = fmod(y + 1034.0, GW); /* every loop */
359 #if 0
360 if ((x > GW) || (y > GW))
361 continue; /* too close to border? */
362 #endif
363 done = 1; /* assume valid coord */
364 for (j = 0; j < n; j++)
365 { /* go through previous planets */
366 dx = fabs(x - (double) planets[j].pl_x);
367 dy = fabs(y - (double) planets[j].pl_y);
368 if (dx * dx + dy * dy < SYSMIN2)
369 { /* if planet to close */
370 done = 0; /* we must get another coord */
371 }
372 }
373 } while (!done && attempts < 200); /* do until location found */
374
375 if (!done)
376 return 0;
377
378 move_planet(n, (int) x, (int) y, 0);
379 planets[n].pl_system = 0; /* mark the no system */
380 planets[n].pl_flags |= PLWHOLE; /* mark the planet as a wormhole */
381 /* the armies in a wormhole is the other wormhole's x coord */
382 /* the radius is the other wormhole's y coord */
383 if (NUMPLANETS % 2)
384 {
385 if (!(n % 2))
386 {
387 planets[n].pl_armies = planets[n - 1].pl_x;
388 planets[n].pl_radius = planets[n - 1].pl_y;
389 planets[n - 1].pl_armies = planets[n].pl_x;
390 planets[n - 1].pl_radius = planets[n].pl_y;
391 }
392 }
393 else
394 {
395 if (n % 2)
396 {
397 planets[n].pl_armies = planets[n - 1].pl_x;
398 planets[n].pl_radius = planets[n - 1].pl_y;
399 planets[n - 1].pl_armies = planets[n].pl_x;
400 planets[n - 1].pl_radius = planets[n].pl_y;
401 }
402 }
403 planets[i].pl_owner = NOBODY; /* no team owns a star */
404 planets[i].pl_hinfo = ALLTEAM; /* all teams know its a star */
405 for (j = 0; j < MAXTEAM + 1; j++)
406 { /* go put in info for teams */
407 planets[i].pl_tinfo[j].owner = NOBODY; /* nobody owns it */
408 planets[i].pl_tinfo[j].armies = 0;
409 planets[i].pl_tinfo[j].flags = planets[i].pl_flags;
410 }
411 n++; /* go to next planet */
412 }
413 return 1;
414 }
415
416
417
418
419 /*---------------------------------PLACERACES------------------------------*/
420 /*
421 * This function places the races in the galaxy. Each race is placed in a
422 * different system. The race is given a home world with an Agri and Ship-
423 * yard on it and HOMEARMIES. They are also given a conoly planet with
424 * dilythium deposits and COLONYARMIES on it.
425 */
426
427 static void
428 placeraces()
429 {
430 int i, j, k; /* looping vars */
431 int p; /* to hold planet for race */
432 int r[4], t;
433
434 r[0] = r[1] = lrand48() % 4; /* pick two races at random. They will be */
435 while (r[0] == r[1]) /* the races whose systems are 'optimally' */
436 r[1] = lrand48() % 4; /* placed. */
437 i = 0;
438 while (i == r[0] || i == r[1])
439 i++;
440 r[2] = i++;
441 while (i == r[0] || i == r[1])
442 i++;
443 r[3] = i;
444 status2->nontteamlock = (1 << r[0]) | (1 << r[1]); /* only allow these
445 * teams */
446
447 for (i = 0; i < 4; i++)
448 { /* go through races */
449 t = r[i]; /* which team */
450 p = lrand48() % NUMPLANETS; /* pick random planet */
451 while ((planets[p].pl_system != i + 1)
452 || (PL_TYPE(planets[p]) == PLSTAR)
453 || (planets[p].pl_owner != NOBODY))
454 p = (p + 1) % NUMPLANETS; /* go on to next planet */
455
456 planets[p].pl_flags &= ~PLSURMASK; /* make sure no dilithium */
457 planets[p].pl_flags |= (PLMETAL | PLARABLE); /* metal and arable */
458 planets[p].pl_flags |= PLATYPE1; /* good atmosphere */
459 planets[p].pl_flags |= (PLAGRI | PLSHIPYARD | PLREPAIR);
460 planets[p].pl_tagri = PLGAGRI; /* set timers for resources */
461 planets[p].pl_tshiprepair = PLGSHIP;
462 planets[p].pl_owner = 1 << t; /* make race the owner */
463 planets[p].pl_armies = HOMEARMIES; /* set the armies */
464 planets[p].pl_hinfo = 1 << t; /* race has info on planet */
465 planets[p].pl_tinfo[1 << t].owner = 1 << t; /* know about owner */
466 planets[p].pl_tinfo[1 << t].armies = planets[p].pl_armies;
467 planets[p].pl_tinfo[1 << t].flags = planets[p].pl_flags;
468 /* find colony planet */
469 p = lrand48() % NUMPLANETS; /* pick random planet */
470 while ((planets[p].pl_system != i + 1)
471 || (PL_TYPE(planets[p]) == PLSTAR)
472 || (planets[p].pl_owner != NOBODY))
473 p = (p + 1) % NUMPLANETS; /* go on to next planet */
474 planets[p].pl_flags |= PLFUEL; /* make fuel depot */
475 planets[p].pl_tfuel = PLGFUEL; /* set timer for fuel depot */
476 planets[p].pl_flags &= ~PLATMASK; /* take off previous atmos */
477 planets[p].pl_flags |= PLPOISON; /* poison atmosphere */
478 planets[p].pl_flags |= PLDILYTH; /* dilythium deposits */
479 planets[p].pl_owner = 1 << t; /* make race the owner */
480 planets[p].pl_armies = COLONYARMIES; /* set the armies */
481 planets[p].pl_hinfo = 1 << t; /* race knows about */
482 planets[p].pl_tinfo[1 << t].owner = 1 << t; /* know about owner */
483 planets[p].pl_tinfo[1 << t].armies = planets[p].pl_armies;
484 planets[p].pl_tinfo[1 << t].flags = planets[p].pl_flags;
485 for (j = 0; j < NUMPLANETS; j++)
486 {
487 if ((planets[j].pl_system == i + 1) && (PL_TYPE(planets[j]) != PLSTAR))
488 {
489 #ifdef LEAGUE_SUPPORT
490 for (k = (status2->league ? 0 : t);
491 k < (status2->league ? 4 : t + 1);
492 k++)
493 #else
494 k = t;
495 #endif
496 {
497 planets[j].pl_owner = 1 << t;
498 planets[j].pl_hinfo =
499 #ifdef LEAGUE_SUPPORT
500 status2->league ? (1 << 4) - 1 :
501 #endif
502 (1 << t);
503 planets[j].pl_tinfo[1 << k].owner = 1 << t;
504 planets[j].pl_tinfo[1 << k].armies = planets[j].pl_armies;
505 planets[j].pl_tinfo[1 << k].flags = planets[j].pl_flags;
506 }
507 }
508 }
509 }
510 }
511
512 /*
513 * Generate a complete galaxy. This variation is similar to gen_galaxy_1;
514 * except that it tries to place the races at consistent distances from one
515 * another.
516 */
517
518 void
519 gen_galaxy_3()
520 {
521 int t;
522
523 NUMPLANETS = 60; /* planets + wormholes */
524 GWIDTH = 200000;
525
526 while (1)
527 {
528 initplanets(); /* initialize planet structures */
529
530 /* place the resources */
531 zero_plflags(planets, NUMPLANETS);
532 randomize_atmospheres(planets + SYSTEMS, NUMPLANETS - SYSTEMS,
533 PATMOS1, PATMOS2, PATMOS3, PPOISON);
534 randomize_resources(planets + SYSTEMS, NUMPLANETS - SYSTEMS,
535 NMETAL, NDILYTH, NARABLE);
536
537 /* place system centers */
538 t = place_stars(planets, 2,
539 (int) TEAMBORD, (int) TEAMMIN, (int) TEAMMAX,
540 (struct planet *) 0, 0)
541 && place_stars(planets + 2, 2,
542 (int) (STARBORD * 0.8), (int) TEAMMIN, (int) STARMAX,
543 planets, 2)
544 && place_stars(planets + 4, SYSTEMS - 4,
545 (int) STARBORD, (int) STARMIN, (int) STARMAX,
546 planets, 4);
547
548 if (!t)
549 continue;
550 t = placesystems(); /* place planets in systems */
551 if (!t)
552 continue;
553 t = placeindep(t); /* place independent planets */
554 if (t)
555 break; /* success */
556 }
557 if (configvals->justify_galaxy)
558 justify_galaxy(SYSTEMS);
559 placeraces(); /* place home planets for races */
560
561 }