comparison src/terrain.c @ 8:0836fb919dfa

First entry of Paradise Server 2.9 patch 10 Beta
author darius
date Sat, 06 Dec 1997 04:37:05 +0000
parents
children
comparison
equal deleted inserted replaced
7:814de70c9f67 8:0836fb919dfa
1 /*--------------------------------------------------------------------------
2 NETREK II -- Paradise
3
4 Permission to use, copy, modify, and distribute this software and its
5 documentation for any NON-COMMERCIAL purpose (following the terms of
6 the GNU General Public License (read the file 'COPYING')) and without
7 fee is hereby granted, provided that this copyright notice appear in all
8 copies. No representations are made about the suitability of this
9 software for any purpose. This software is provided "as is" without
10 express or implied warranty.
11
12 Xtrek Copyright 1986 Chris Guthrie
13 Netrek (Xtrek II) Copyright 1989 Kevin P. Smith
14 Scott Silvey
15 Paradise II (Netrek II) Copyright 1993 Larry Denys
16 Kurt Olsen
17 Brandon Gillespie
18
19 Comprehensive credits are available in the file "CREDITS"
20 --------------------------------------------------------------------------*/
21
22 #include "config.h"
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <math.h>
26 #include "struct.h"
27 #include "data.h"
28 #include "shmem.h"
29 #include "terrain.h"
30
31 #define MAXALTITUDE 255
32 #define MAXSTARS 20
33 #define X 0
34 #define Y 1
35
36 void
37 generate_terrain()
38 /*
39 * Generates terrain based on specs in the system configuration. Places a
40 * number of "seeds" into the terrain grid, and then generates an "altitude"
41 * map based on those seeds' positions (which correspond to star positions).
42 * Place_nebula generates another altitude map for nebulae -- the first map
43 * is used for asteroids and generating the second map.
44 *
45 * This function is called within the galaxy generation stuff.
46 *
47 * 10/26/94 MM
48 */
49 {
50 int i, j, k; /* counters */
51 int x, y; /* more counters, different purpose */
52 double dist, val; /* for distance calculations */
53 int num_seeds = 0;
54 int seed_xy[MAXSTARS][2];
55 int qx[4] = {-1, 1, -1, 1}, qy[4] = {1, 1, -1, -1}; /* quadrant multipliers */
56
57 /*
58 * place seeds -- this would be easy to change if you just had a number of
59 * seeds you wanted to place, instead of basing it on stars. I won't
60 * bother doing it, even though it might be cool to see it work in a bronco
61 * game... MM
62 */
63
64 for (i = 0; i < NUMPLANETS; i++)
65 if (PL_TYPE(planets[i]) == PLSTAR)
66 {
67 terrain_grid[(planets[i].pl_x / TGRID_GRANULARITY) * TGRID_SIZE +
68 planets[i].pl_y / TGRID_GRANULARITY].alt1 = MAXALTITUDE;
69
70 seed_xy[num_seeds][X] = planets[i].pl_x / TGRID_GRANULARITY;
71 seed_xy[num_seeds][Y] = planets[i].pl_y / TGRID_GRANULARITY;
72 num_seeds++;
73 }
74
75 /* generate terrain -- simple, stupid version. */
76
77
78 for (x = 0; x < TGRID_SIZE; x++)
79 for (y = 0; y < TGRID_SIZE; y++)
80 if (terrain_grid[x * TGRID_SIZE + y].alt1 != MAXALTITUDE)
81 {
82 val = 0.0;
83 for (i = 0; i < num_seeds; i++)
84 {
85 dist = (double) MAXALTITUDE -
86 sqrt((double) ((x - seed_xy[i][X]) * (x - seed_xy[i][X]) +
87 (y - seed_xy[i][Y]) * (y - seed_xy[i][Y])));
88 if (dist > val)
89 val = dist;
90 }
91 /* reset any previous terrain values */
92 terrain_grid[x * TGRID_SIZE + y].types = 0x00;
93
94 terrain_grid[x * TGRID_SIZE + y].alt1 = (int) val;
95 terrain_grid[x * TGRID_SIZE + y].alt2 = 0;
96 }
97
98 /* place nebula */
99 if (num_nebula)
100 place_nebula(*num_nebula, *nebula_subclouds, *nebula_density);
101 /* place asteroids */
102 if (num_asteroid)
103 place_asteroids(MAXALTITUDE - (*asteroid_radius));
104 }
105
106 void
107 place_nebula(int num_nebula, int num_seeds, int minalt)
108 /*
109 * Values inbetween MAXALTITUDE and minalt are considered nebulous terrain.
110 * Tries to cluster seeds in groups based on num_nebula and num_seeds. ...the
111 * number of seeds per nebula being num_seeds. 10/26/94 MM
112 */
113 {
114 int i = 0, j = 0, x, y, dx, dy, dist, lowdist = 2 * TGRID_SIZE;
115 int *seeds1, *seeds2;
116
117 seeds1 = (int *) malloc(num_nebula * sizeof(int));
118 if (num_seeds)
119 seeds2 = (int *) malloc(num_seeds * sizeof(int) * num_nebula);
120
121 /* find a local minimum, and place a "seed" */
122 while (i < num_nebula)
123 {
124 j = (int) lrand48() % (TGRID_SIZE * TGRID_SIZE);
125 if (j == 0)
126 j = 1;
127 while ((j < (TGRID_SIZE * TGRID_SIZE)) &&
128 ((terrain_grid[j - 1].alt1 < terrain_grid[j].alt1) ||
129 (terrain_grid[j + 1].alt1 < terrain_grid[j].alt1)))
130 j++;
131 seeds1[i] = j;
132 terrain_grid[seeds1[i]].alt2 = MAXALTITUDE;
133 i++;
134 }
135 /* group num_seeds more "sub seeds" around each seed */
136 /*
137 * (there are a couple bugs in this algorithm yet -- theres a wierd
138 * wraparound occasionally. MDM, 8/23/95)
139 */
140
141 for (i = 0; i < num_nebula; i++)
142 for (j = 0; j < num_seeds; j++)
143 {
144 dx = (int) (lrand48() % ((MAXALTITUDE - minalt) * 3)) -
145 (int) (lrand48() % (int) ((MAXALTITUDE - minalt) * (1.5)));
146 dy = (int) (lrand48() % ((MAXALTITUDE - minalt) * 3)) -
147 (int) (lrand48() % (int) ((MAXALTITUDE - minalt) * (1.5)));
148 if (seeds1[i] / TGRID_SIZE + dx < 0)
149 dx -= (seeds1[i] / TGRID_SIZE + dx);
150 if (seeds1[i] / TGRID_SIZE + dx >= TGRID_SIZE)
151 dx -= (seeds1[i] / TGRID_SIZE + dx) - (TGRID_SIZE - 1);
152 if (seeds1[i] / TGRID_SIZE + dy < 0)
153 dy -= (seeds1[i] / TGRID_SIZE + dy);
154 if (seeds1[i] / TGRID_SIZE + dy >= TGRID_SIZE)
155 dy -= (seeds1[i] / TGRID_SIZE + dy) - (TGRID_SIZE - 1);
156 seeds2[i * num_seeds + j] = (seeds1[i] / TGRID_SIZE + dx) * TGRID_SIZE +
157 (seeds1[i] % TGRID_SIZE + dy);
158 terrain_grid[seeds2[i * num_seeds + j]].alt2 = MAXALTITUDE;
159 }
160
161 /*
162 * assign random-ish values, from a distance-from-seed base value (density
163 * is the randomness -- low density values are smooth, high are rough)
164 */
165 /* randomness NYI */
166 /*
167 * these values could be used in combination with the alt1 values to do
168 * other funky terrain "shapes, but I'm putting in the ABS() speedup stuff
169 * in for now anyway. It'll result in alt2 values of 0 for any spot
170 * outside a nebulous radius -- MDM
171 */
172 for (x = 0; x < TGRID_SIZE; x++)
173 for (y = 0; y < TGRID_SIZE; y++)
174 {
175 for (i = 0; i < num_nebula; i++)
176 {
177 dx = (seeds1[i] / TGRID_SIZE) - x;
178 dy = (seeds1[i] % TGRID_SIZE) - y;
179 /* loop speedup */
180 if ((ABS(dx) <= MAXALTITUDE - minalt) &&
181 (ABS(dy) <= MAXALTITUDE - minalt))
182 {
183 dist = (int) sqrt(dx * dx + dy * dy);
184 if (dist < lowdist)
185 lowdist = dist;
186 }
187 if (num_seeds)
188 for (j = 0; j < num_seeds; j++)
189 {
190 dx = seeds2[i * num_seeds + j] / TGRID_SIZE - x;
191 dy = seeds2[i * num_seeds + j] % TGRID_SIZE - y;
192 /* loop speedup */
193 if ((ABS(dx) <= MAXALTITUDE - minalt) &&
194 (ABS(dy) <= MAXALTITUDE - minalt))
195 {
196 dist = (int) sqrt(dx * dx + dy * dy);
197 if (dist < lowdist)
198 lowdist = dist;
199 }
200 }
201 }
202 terrain_grid[x * TGRID_SIZE + y].alt2 = MAXALTITUDE - lowdist;
203 lowdist = 2 * TGRID_SIZE;
204 }
205
206 /* give each spot with a high enuf alt value the nebulous terrain flag. */
207 for (i = 0; i < TGRID_SIZE; i++)
208 for (j = 0; j < TGRID_SIZE; j++)
209 if (terrain_grid[i * TGRID_SIZE + j].alt2 >= minalt)
210 terrain_grid[i * TGRID_SIZE + j].types |= T_NEBULA;
211
212 free(seeds1);
213 free(seeds2);
214 }
215
216 void
217 place_asteroids(int altitude)
218 /*
219 * Marks terrain grid locations within density of altitude as asteroid
220 * fields. I may make the chance of such a grid location becoming a field
221 * random (like 90% or something), so that fields will appear less uniform,
222 * and holes may exist in them. Makes for interesting terrain, IMO. 10/26/94
223 * MM
224 */
225 {
226 int x, y, i, j, numstars = 0, attempts = 0;
227 int *systems_with_asteroids;
228 int *star_numbers;
229 int *varied_rad;
230 int *varied_dens;
231 float *varied_thick;
232
233 printf("placing asteroids\n");
234 star_numbers = (int *) malloc((NUMPLANETS) * sizeof(int));
235 for (i = 0; i < NUMPLANETS; i++)
236 if (PL_TYPE(planets[i]) == PLSTAR)
237 {
238 star_numbers[numstars] = i;
239 numstars++;
240 }
241 systems_with_asteroids = (int *) malloc(numstars * sizeof(int));
242 varied_rad = (int *) malloc(numstars * sizeof(int));
243 varied_dens = (int *) malloc(numstars * sizeof(int));
244 varied_thick = (float *) malloc(numstars * sizeof(float));
245 for (i = 0; i < numstars; i++)
246 systems_with_asteroids[i] = 0;
247
248 /*
249 * assign what stars have asteroid belts -- I could just start with system
250 * #1, since systems are placed randomly, but I might as well pick a random
251 * system to start with. The only prereq is that the system does NOT
252 * belong to a race. (prereq NYI)
253 */
254 if (*num_asteroid > (numstars - 4))
255 *num_asteroid = numstars - 4;
256
257 i = 0;
258 while (i < *num_asteroid)
259 {
260 j = lrand48() % numstars;
261
262 if (((planets[j].pl_system < 1) || (planets[j].pl_system > 4))
263 && (systems_with_asteroids[j] == 0))
264 systems_with_asteroids[j] = 1;
265 else
266 continue;
267
268 i++;
269
270 if ((*asteroid_rad_variance) == 0)
271 varied_rad[j] = altitude;
272 else
273 varied_rad[j] = altitude - ((*asteroid_rad_variance) / 2) +
274 lrand48() % (*asteroid_rad_variance);
275
276 if ((*asteroid_dens_variance) == 0)
277 varied_dens[j] = *asteroid_density;
278 else
279 varied_dens[j] = (*asteroid_density) - ((*asteroid_dens_variance) / 2) +
280 lrand48() % (*asteroid_dens_variance);
281
282 varied_thick[j] = (*asteroid_thickness) - ((*asteroid_thick_variance) / 2.0)
283 + drand48() * (*asteroid_thick_variance);
284
285 attempts++;
286
287 if (attempts > 1000)
288 {
289 printf("Too many attempts - giving up\n");
290 break;
291 }
292 }
293
294 for (i = 0; i < numstars; i++)
295 if (systems_with_asteroids[i])
296 printf("System %s has an asteroid belt\n", planets[star_numbers[i]].pl_name);
297
298 for (x = 0; x < TGRID_SIZE; x++)
299 {
300 for (y = 0; y < TGRID_SIZE; y++)
301 {
302 for (i = 0; i < numstars; i++)
303 {
304 /*
305 * if the tgrid locale is within a certain distance of a system that
306 * is supposed to have an asteroid belt, then, AST_CHANCE percent of
307 * the time, mark that locale as having asteroids
308 */
309 if (systems_with_asteroids[i] &&
310 terrain_grid[x * TGRID_SIZE + y].alt1 >= varied_rad[i] -
311 (varied_thick[i]) && terrain_grid[x * TGRID_SIZE + y].alt1
312 <= varied_rad[i] + (varied_thick[i]) && (ABS(x * TGRID_GRANULARITY -
313 planets[star_numbers[i]].pl_x) <
314 (MAXALTITUDE - (varied_rad[i] -
315 (varied_thick[i] + 1.0)))
316 * TGRID_GRANULARITY) &&
317 (ABS(y * TGRID_GRANULARITY - planets[star_numbers[i]].pl_y) <
318 (MAXALTITUDE - (varied_rad[i] - (varied_thick[i] + 1.0))) * TGRID_GRANULARITY) &&
319 lrand48() % 100 < varied_dens[i])
320 {
321 printf("terrain grid %d has asteroids\n", x * TGRID_SIZE + y);
322 terrain_grid[x * TGRID_SIZE + y].types |= T_ASTEROIDS;
323 }
324 }
325 }
326 }
327 }
328
329 void
330 doTerrainEffects()
331 /*
332 * apply terrain effects to players
333 *
334 * I REALLY wish I could add a "skill" element to many of the effects, but its
335 * tough. Asteroid damage is the most notable example where skill *should* be
336 * a factor, but isn't. MDM
337 */
338 {
339 struct player *p;
340 int i, j, dam;
341
342 for (i = 0; i < MAXPLAYER; i++)
343 {
344 p = &(players[i]);
345 if (p->p_status != PALIVE)
346 continue;
347 if (TERRAIN_TYPE((p->p_x) / TGRID_GRANULARITY, (p->p_y) / TGRID_GRANULARITY) &
348 T_ASTEROIDS)
349 {
350 j = lrand48() % 100;
351 /* the player is in an asteroid location */
352 if (p->p_speed != 0)
353 {
354 if (ast_effect[SS_IMPULSE] &&
355 (j < (100 - ((p->p_ship.s_turns / (p->p_speed * p->p_speed)) / 200)) ||
356 (j < MIN_AST_HIT)))
357 {
358 dam = lrand48() % (VAR_AST_DAMAGE * p->p_speed) + MIN_AST_DAMAGE;
359 if (inflict_damage(0, 0, p, dam, KASTEROID) == 1)
360 p->p_whydead = KASTEROID;
361 }
362 }
363 }
364 }
365 }