Mercurial > ~darius > hgwebdir.cgi > paradise_server
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 } |