Mercurial > ~darius > hgwebdir.cgi > paradise_server
comparison src/planets.c @ 6:8c6d5731234d
First entry of Paradise Server 2.9 patch 10 Beta
author | darius |
---|---|
date | Sat, 06 Dec 1997 04:37:04 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
5:054275999194 | 6:8c6d5731234d |
---|---|
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 | |
20 #define PLANETS 1 | |
21 #define GRID 0 /* for space grid */ | |
22 | |
23 #include "config.h" | |
24 #include <stdio.h> | |
25 #include <stdlib.h> | |
26 #include <string.h> | |
27 #include <math.h> | |
28 #include <setjmp.h> | |
29 #include <sys/types.h> | |
30 #include <sys/time.h> | |
31 #include <unistd.h> | |
32 | |
33 #include "struct.h" | |
34 #include "data.h" | |
35 #include "daemonII.h" | |
36 #include "planets.h" | |
37 #include "misc.h" | |
38 #include "conquer.h" | |
39 #include "player.h" | |
40 #include "grid.h" | |
41 #include "shmem.h" | |
42 #include "terrain.h" | |
43 | |
44 | |
45 /* define this if you want the experimental dragging-into-star-counts mod */ | |
46 #define GIVESTARKILLS | |
47 | |
48 #define friendly(fred, bart) \ | |
49 (!(fred->p_team & (bart->p_swar|bart->p_hostile)) && \ | |
50 !(bart->p_team & (fred->p_swar|fred->p_hostile))) | |
51 | |
52 | |
53 /* defines dealing with growth timers */ | |
54 #define PLGFUEL configvals->plgrow.fuel /* time for growth of fuel | |
55 * depot */ | |
56 #define PLGAGRI configvals->plgrow.agri /* time for growth of agri */ | |
57 #define PLGREPAIR configvals->plgrow.repair /* time for growth of | |
58 * repair */ | |
59 #define PLGSHIP configvals->plgrow.shipyard /* time for growth of | |
60 * shipyard */ | |
61 | |
62 /* other defines */ | |
63 #define UCVISIBLE 40000 /* dist for uncloaked visibility */ | |
64 #define CVISMIN 12000 /* cloakers always visible distance */ | |
65 #define CVISSPEED 2000 /* cloak dist added per warp point */ | |
66 #define CVISIBLE 25000 /* dist for cloaked visibility */ | |
67 #define PLFIREDIST 1500 /* distance planets fire at players */ | |
68 #define PLVISDIST 5000 /* dist planets sense enemy players */ | |
69 #define REVOLT 200 /* chance out of 1000 of revolt start */ | |
70 #define STARTREV 8 /* for revolt timer */ | |
71 /*-------------------------------------------------------------------------*/ | |
72 | |
73 | |
74 | |
75 | |
76 | |
77 | |
78 /*-----------------------------MODULE VARIABLES----------------------------*/ | |
79 | |
80 /* the list of all possible planet names */ | |
81 char *pnames[] = | |
82 { | |
83 /* Federation planets */ | |
84 "Rigel", "Canopus", "Beta Crucis", "Organia", "Deneb", | |
85 "Ceti Alpha V", "Altair", "Vega", "Alpha Centauri", | |
86 /* Romulan worlds */ | |
87 "Eridani", "Aldeberan", "Regulus", "Capella", "Tauri", | |
88 "Draconis", "Sirius", "Indi", "Hydrae", | |
89 /* Klingon worlds */ | |
90 "Pleiades V", "Andromeda", "Lalande", "Pollux", "Lyrae", | |
91 "Scorpii", "Mira", "Cygni", "Castor", | |
92 /* Orion worlds */ | |
93 "Cassiopia", "El Nath", "Spica", "Procyon", "Polaris", | |
94 "Arcturus", "Ursae Majoris", "Herculis", "Antares", | |
95 | |
96 /* new worlds */ | |
97 "Planet 10", "Bezier", "Sequent", "Ophiuchi", "Lacaille", | |
98 "Luyten", "Pavonis", "Wolf 424", "Ross 882", "Cephei", | |
99 "Kruger", "Groombridge", "Maanen's Star", "Heinlein", | |
100 "Pixel", "Lazarus", "Mycroft", "Asimov", "Varley", | |
101 "Clarke's Star", "Ren", "Stimpy", "Foo", "Jolt Cola", | |
102 "Kelly Bundy", "Tyrell", "Roy", "Deckard", "Vangelis", | |
103 "Orpheus", "Xanth", "Tatooine", "Ludicrous", "Ogg", | |
104 "Scum", "Twink", "Chiapucci", "Bugno", "Hampsten", "Fignon", | |
105 "Paradise", "Azriel", "Gargamel", "Smurf Village", | |
106 "Praxis", "Acherner", "Arrakis", "Caladan", "Giedi Prime", | |
107 "Clue", "Paulina", "Sith", "Salusa", "Ahrain", "Cerranos", | |
108 "Darkurthe", "Dagobah", "Phaze", "Chatsubu", "Lemond", | |
109 "Bronco", "Vulcan", "Eden", "Klein", "Merckx", "Tarot", | |
110 "Mottet", "Roche", "Doorstop", "Shaedron", "Fondriest", | |
111 | |
112 /* Bob's fave worlds */ | |
113 "Wayne's World", "DanjerHaus", "Anvil", /* B-52s */ "Claire", | |
114 "Planet Reebok", "Sony Corp.", "SEGA!", "McWorld", | |
115 "Tokyo", "New York", "D.C.", "Atlanta", /* places I've never been */ | |
116 /* Tony */ "Levin", | |
117 "Planet Woogie", "Nancy", "Wilson", /* real people */ | |
118 "Beavis", "Butthead", | |
119 "Memolo", /* Matt Memolo was murdered in Miami in July | |
120 * of '93. He was a really swell guy. "...he | |
121 * would go far out of his way to give you | |
122 * the shirt off his back." - ajc */ | |
123 /* names from the T.V. shows */ | |
124 "New Berlin", | |
125 /* | |
126 * "Bejor", "Cardassia" I'm not including these till I can spell them - RF | |
127 */ | |
128 | |
129 /* Mike's fave worlds */ | |
130 "Melmac", "Order", "Yosemite", "New Chicago", "Ceptus", "Ork", | |
131 "Levi 501", "Toughskin", "Wonka", | |
132 | |
133 /* book names */ | |
134 "Terminus", "Magrathea", "Trantor", "Synnax", "Coruscant", | |
135 | |
136 /* Moons, names, etc. */ | |
137 "Io ", "Titan", "Europa", "Ganymede", "Charon", | |
138 "Tholia", "Gor", "Kzin", "Aerth", | |
139 "Proxima", "Cellust", "Calamar", "Icarus", | |
140 "New Prague", | |
141 | |
142 /* How about the solar system? */ | |
143 "Mercury", "Venus", "Mars", "Jupiter", "Saturn", "Neptune", | |
144 "Uranus", "Pluto", /* are Neptune and Uranus in order? */ | |
145 | |
146 #if 0 | |
147 /* Player's names */ | |
148 "Claypigeon", "Maxout", "Fungus", "Lynx", | |
149 "Bubbles", "KnightRaven", "Bolo", "Vladimir", | |
150 "Gajah Mada", "Trippix", "Shrew", "Bob Dobbs", "Wibble", | |
151 "Rogue" | |
152 #endif | |
153 }; | |
154 | |
155 #define MAXNAMES (sizeof(pnames)/sizeof(char *)) /* # of planet names */ | |
156 | |
157 char *homenames[] = /* names of the race's home worlds */ | |
158 { | |
159 " ", "Earth", "Romulus", " ", "Klingus", " ", " ", " ", | |
160 "Orion" | |
161 }; | |
162 | |
163 | |
164 /* | |
165 * This table is used to turn the four bits of resources flags into a three | |
166 * bit number. The shipyard and the repair are ORed together. All the non | |
167 * resource bits need to be masked off with PLRESMASK before this table is | |
168 * used | |
169 */ | |
170 int restores[16] = {0, 1, 2, 3, 4, 5, 6, 7, 1, 1, 3, 3, 5, 5, 7, 7}; | |
171 | |
172 | |
173 /* | |
174 * This is a matrix that determines the chance a planet has of popping. The | |
175 * chance is expressed as a chance out of 100. The matrix is accessed with | |
176 * the planet's atmosphere type and the resource bits after they have been | |
177 * converted to 3 bits with the table above. | |
178 */ | |
179 int popchance[4][8] = { | |
180 /* | |
181 * 000 00Z 0f0 0fZ a00 a0Z af0 afZ--the resources flags, | |
182 * Z=r|s | |
183 */ | |
184 {2, 3, 2, 2, 5, 7, 4, 8}, /* poison */ | |
185 {3, 5, 2, 4, 9, 11, 7, 12}, /* atmos #3 */ | |
186 {5, 7, 4, 6, 12, 14, 10, 15}, /* atmos #2 */ | |
187 {8, 12, 7, 10, 20, 24, 18, 23}/* atmos #1 */ | |
188 }; | |
189 | |
190 | |
191 /* | |
192 * This is a matrix that determines the multiplier for popping. When popping | |
193 * the armies on a planet will be multiplied by this multiplier to get the | |
194 * number of extra armies that grow. A negative number indicates negative | |
195 * growth. | |
196 */ | |
197 float popmult[4][8] = { | |
198 /* 000 00Z 0f0 0fZ a00 a0Z af0 afZ */ | |
199 {-0.08, 0.00, -0.10, -0.03, 0.00, 0.05, -0.05, 0.05}, /* poison */ | |
200 {0.03, 0.05, 0.02, 0.04, 0.06, 0.07, 0.06, 0.07}, /* atmos #3 */ | |
201 {0.05, 0.07, 0.05, 0.06, 0.10, 0.11, 0.08, 0.10}, /* atmos #2 */ | |
202 {0.09, 0.12, 0.08, 0.10, 0.17, 0.19, 0.15, 0.18} /* atmos #1 */ | |
203 }; | |
204 | |
205 | |
206 /* | |
207 * This is a matrix that determines the maximum army capacity of a planet. | |
208 * Once this capacity is reached, no other armies can grow there. | |
209 */ | |
210 float popcap[4][8] = { | |
211 /* | |
212 * 000 00Z 0f0 0fZ a00 a0Z af0 afZ--the resources flags, | |
213 * Z=r|s | |
214 */ | |
215 {5, 10, 7, 10, 15, 15, 10, 18}, /* poison */ | |
216 {9, 14, 11, 14, 20, 20, 14, 22}, /* atmos #3 */ | |
217 {12, 18, 15, 18, 25, 25, 19, 27}, /* atmos #2 */ | |
218 {15, 22, 18, 25, 40, 35, 27, 40} /* atmos #1 */ | |
219 }; | |
220 | |
221 /*-------------------------------------------------------------------------*/ | |
222 | |
223 | |
224 | |
225 | |
226 | |
227 | |
228 | |
229 | |
230 #ifdef LEAGUE_SUPPORT | |
231 extern void tlog_res(); | |
232 extern void tlog_bomb(); | |
233 extern void tlog_bres(); | |
234 extern void tlog_plankill(); | |
235 extern void tlog_revolt(); | |
236 extern void tlog_pop(); | |
237 #else | |
238 #define tlog_res(a,b) | |
239 #define tlog_bomb(a,b,c) | |
240 #define tlog_bres(a,b,c) | |
241 #define tlog_plankill(a,b,c) | |
242 #define tlog_revolt(a) | |
243 #define tlog_pop(a,b) | |
244 #endif | |
245 extern void scout_planet(); | |
246 extern int inflict_damage(); | |
247 extern void killmess(); | |
248 extern int enemy_admiral(); | |
249 extern off_t lseek(); | |
250 extern int write(); | |
251 | |
252 /*------------------------------INTERNAL FUNCTIONS-------------------------*/ | |
253 | |
254 void fill_planets(); | |
255 | |
256 | |
257 #ifndef NO_QSORT | |
258 /* used by the qsort() in sortnames() below */ | |
259 static int | |
260 comp_pl_name(a, b) | |
261 void *a, *b; | |
262 { | |
263 return strcasecmp(((struct planet *) a)->pl_name, | |
264 ((struct planet *) b)->pl_name); | |
265 } | |
266 #endif | |
267 | |
268 /*--------------------------------SORTNAMES---------------------------------*/ | |
269 /* | |
270 * This function sorts the planet into a alphabeticly increasing list. It | |
271 * operates on the global planets structure. This uses a simple bubble sort | |
272 * because I was too lazy to write anything more sophisticated. | |
273 */ | |
274 | |
275 /* | |
276 * Bubble sorts suck. Let's use the qsort library function instead, if | |
277 * available (HK) | |
278 */ | |
279 | |
280 void | |
281 sortnames() | |
282 { | |
283 #ifdef NO_QSORT | |
284 struct planet ptemp; /* temporary space to hold planet */ | |
285 int exchange; /* flag for exchange made in pass */ | |
286 int i; /* looping var */ | |
287 int t; /* temp var */ | |
288 | |
289 exchange = 1; /* no exchanges done yet */ | |
290 while (exchange) | |
291 { /* do until no exchanges */ | |
292 exchange = 0; /* no exchanges for this pass yet */ | |
293 for (i = 0; i < NUMPLANETS - 1; i++) | |
294 { /* go through list */ | |
295 if (strcmp(planets[i].pl_name, planets[i + 1].pl_name) > 0) | |
296 { | |
297 t = planets[i].pl_no; /* exchange planet numbers */ | |
298 planets[i].pl_no = planets[i + 1].pl_no; | |
299 planets[i + 1].pl_no = t; | |
300 memcpy(&ptemp, &(planets[i]), sizeof(struct planet)); | |
301 memcpy(&(planets[i]), &(planets[i + 1]), sizeof(struct planet)); | |
302 memcpy(&(planets[i + 1]), &ptemp, sizeof(struct planet)); | |
303 exchange++; /* we made an exchange this pass */ | |
304 } | |
305 } | |
306 } | |
307 #else | |
308 int i; | |
309 | |
310 qsort(planets, NUMPLANETS, sizeof(struct planet), comp_pl_name); | |
311 for (i = 0; i < NUMPLANETS; i++) /* go through the planets */ | |
312 planets[i].pl_no = i; /* and fix their pl_no value */ | |
313 #endif | |
314 } | |
315 | |
316 | |
317 /*--------------------------------INITPLANETS-------------------------------*/ | |
318 /* | |
319 * This function generates the names and initializes the fields in the | |
320 * planets structure. The planet names need to be sorted afterthe planets | |
321 * have been placed. | |
322 */ | |
323 | |
324 void | |
325 initplanets() | |
326 { | |
327 int i, j; /* looping vars */ | |
328 int nused[MAXNAMES]; /* to mark which names are used */ | |
329 | |
330 for (i = 0; i < MAXNAMES; i++)/* go through all possible names */ | |
331 nused[i] = 0; /* mark name is not used yet */ | |
332 for (i = 0; i < NUMPLANETS; i++) | |
333 { | |
334 planets[i].pl_no = i; /* set planet number */ | |
335 planets[i].pl_flags = PLPARADISE; /* Paradise planet */ | |
336 planets[i].pl_owner = NOBODY; /* no owner yet */ | |
337 planets[i].pl_x = 0; /* just to intialize x and y */ | |
338 planets[i].pl_y = 0; | |
339 j = lrand48() % MAXNAMES; /* get a random name */ | |
340 do | |
341 { /* do until unused name found */ | |
342 j = (j + 1) % MAXNAMES; /* go on to next name in list */ | |
343 } while (nused[j]); /* until unused name found */ | |
344 nused[j] = 1; /* mark name as used */ | |
345 strcpy(planets[i].pl_name, pnames[j]); /* copy into planet struct */ | |
346 planets[i].pl_namelen = strlen(pnames[j]); /* set name's length */ | |
347 #if 1 | |
348 planets[i].pl_hostile = 0; /* planet doesn't hate anyone yet */ | |
349 #else | |
350 planets[i].pl_torbit = 0; /* no teams orbiting */ | |
351 #endif | |
352 planets[i].pl_tshiprepair = 0; /* zero the repair growth timer */ | |
353 planets[i].pl_tagri = 0; /* zero the agri growth timer */ | |
354 planets[i].pl_tfuel = 0; /* zero the fuel growth timer */ | |
355 planets[i].pl_armies = 0; /* no armies yet */ | |
356 planets[i].pl_warning = 0; /* no warning being counted down for */ | |
357 planets[i].pl_system = 0; /* not in a system yet */ | |
358 planets[i].pl_hinfo = NOBODY; /* no race has info on planet */ | |
359 for (j = 0; j < MAXTEAM + 1; j++) | |
360 { /* go through four races */ | |
361 planets[i].pl_tinfo[j].owner = NOBODY; /* do not know who owns it */ | |
362 planets[i].pl_tinfo[j].armies = 0; /* no armies on planet */ | |
363 planets[i].pl_tinfo[j].flags = PLPARADISE; /* know nothing about | |
364 * flags */ | |
365 planets[i].pl_tinfo[j].timestamp = 0; /* set the timestamp */ | |
366 } | |
367 planets[i].pl_trevolt = 0; /* revolt timer not counting down */ | |
368 #if GRID | |
369 planets[i].pl_next = NULL; /* set fields related to space grid */ | |
370 planets[i].pl_previous = NULL; | |
371 planets[i].pl_gridnum = 0; | |
372 #endif | |
373 } | |
374 } | |
375 | |
376 | |
377 | |
378 | |
379 /*-------------------------------GROWPLANETS------------------------------*/ | |
380 /* | |
381 * This function grows resources on planets. It goes through all planets and | |
382 * updates the growth timers and checks for growth. Independent planets do | |
383 * not grow. This function also checks to see if any player in a starbase is | |
384 * orbiting a planet and adjusts the planet's growth rate if so. | |
385 */ | |
386 | |
387 void | |
388 growplanets() | |
389 { | |
390 int i; /* looping var */ | |
391 struct planet *p; /* to point within planets */ | |
392 int add; /* number to add to timers */ | |
393 | |
394 if (!status->tourn) | |
395 return; | |
396 | |
397 if (!configvals->resource_bombing) | |
398 return; | |
399 | |
400 for (i = 0; i < MAXPLAYER; i++) | |
401 { /* go through all players */ | |
402 struct player *py = &players[i]; /* and look for orbiting */ | |
403 if ((py->p_status != PALIVE) || /* starbases */ | |
404 (py->p_ship.s_type != STARBASE) || | |
405 !(py->p_flags & PFORBIT)) | |
406 continue; | |
407 p = &planets[py->p_planet]; /* found one, get planet */ | |
408 p->pl_tfuel += 20; /* give growth rate a boost */ | |
409 p->pl_tagri += 30; /* NOTE: change these if PLG consts */ | |
410 p->pl_tshiprepair += 50; /* change */ | |
411 } | |
412 p = &planets[0]; /* start with first planet */ | |
413 for (i = 0; i < NUMPLANETS; i++, p++) | |
414 { /* through all planets */ | |
415 if (p->pl_owner == NOBODY) /* if independent then */ | |
416 continue; /* no growth */ | |
417 add = p->pl_armies / 2; /* rate based on armies */ | |
418 p->pl_tfuel += add; /* add to fuel timer */ | |
419 p->pl_tfuel = (p->pl_tfuel > PLGFUEL) ? PLGFUEL : p->pl_tfuel; | |
420 if ((!(p->pl_flags & PLFUEL)) /* if no fuel */ | |
421 && (p->pl_flags & PLDILYTH) /* and dilythium deposits */ | |
422 && (p->pl_tfuel >= PLGFUEL)) | |
423 { /* and timer high enough */ | |
424 p->pl_flags |= (PLFUEL | PLREDRAW); /* create fuel depot */ | |
425 p->pl_tinfo[p->pl_owner].flags = p->pl_flags; | |
426 p->pl_tinfo[p->pl_owner].timestamp = status->clock; | |
427 tlog_res(p, "FUEL"); | |
428 } | |
429 p->pl_tagri += add; /* add to agri timer */ | |
430 p->pl_tagri = (p->pl_tagri > PLGAGRI) ? PLGAGRI : p->pl_tagri; | |
431 if ((!(p->pl_flags & PLAGRI)) /* if no agri on planet */ | |
432 && (p->pl_flags & PLARABLE) /* and arable */ | |
433 && (p->pl_tagri >= PLGAGRI)) | |
434 { /* and timer high enough */ | |
435 p->pl_flags |= (PLAGRI | PLREDRAW); /* create agri planet */ | |
436 p->pl_tinfo[p->pl_owner].flags = p->pl_flags; | |
437 p->pl_tinfo[p->pl_owner].timestamp = status->clock; | |
438 tlog_res(p, "AGRI"); | |
439 } | |
440 p->pl_tshiprepair += add; /* add to ship/repair timer */ | |
441 if ((!(p->pl_flags & PLREPAIR)) /* if not repair */ | |
442 && (p->pl_flags & PLMETAL) /* and metal deposits */ | |
443 && (p->pl_tshiprepair >= PLGREPAIR)) | |
444 { /* and timer high enough */ | |
445 p->pl_flags |= (PLREPAIR | PLREDRAW); /* create repair station */ | |
446 p->pl_tinfo[p->pl_owner].flags = p->pl_flags; | |
447 p->pl_tinfo[p->pl_owner].timestamp = status->clock; | |
448 tlog_res(p, "REPAIR"); | |
449 } | |
450 p->pl_tshiprepair = (p->pl_tshiprepair > PLGSHIP) ? PLGSHIP : | |
451 p->pl_tshiprepair; /* clamp value to max */ | |
452 if ((!(p->pl_flags & PLSHIPYARD)) /* if not repair */ | |
453 && (p->pl_flags & PLMETAL) /* and metal deposits */ | |
454 && (p->pl_tshiprepair >= PLGSHIP)) | |
455 { /* and timer high enough */ | |
456 p->pl_flags |= (PLSHIPYARD | PLREDRAW); /* create repair station */ | |
457 p->pl_tinfo[p->pl_owner].flags = p->pl_flags; | |
458 p->pl_tinfo[p->pl_owner].timestamp = status->clock; | |
459 tlog_res(p, "SHIPYARD"); | |
460 } | |
461 } | |
462 } | |
463 | |
464 | |
465 | |
466 | |
467 /*----------------------------------PVISIBLE------------------------------*/ | |
468 /* | |
469 * This function goes through the players and checks the other playes to see | |
470 * if an enemy is close enough to see him. THIS FUNCTION SHOULD EVENTUALLY | |
471 * USE THE SPACE GRID. | |
472 */ | |
473 | |
474 void | |
475 pvisible() | |
476 { | |
477 struct player *p; /* to point to a player */ | |
478 int i; /* looping var */ | |
479 int h; /* looping var */ | |
480 struct player *pl2; /* to point to other players */ | |
481 int dx, dy; /* delta coords */ | |
482 int dist; /* to hold distance */ | |
483 | |
484 for (i = 0, p = &players[0]; i < MAXPLAYER; i++, p++) | |
485 p->p_flags &= ~PFSEEN; /* clear all players' the seen flags */ | |
486 for (i = 0, p = &players[i]; i < MAXPLAYER - 1; i++, p++) | |
487 { | |
488 if (p->p_status != PFREE && /* only do if player alive */ | |
489 p->p_status != POBSERVE) | |
490 { /* observers can't augment team scanning */ | |
491 for (h = i + 1, pl2 = &players[h]; h < MAXPLAYER; h++, pl2++) | |
492 { | |
493 if ((pl2->p_status == PFREE) || (pl2->p_status == POBSERVE) | |
494 || (pl2->p_flags & PFROBOT) /* if not alive or robot or */ | |
495 || (pl2->p_team == p->p_team)) /* same team then continue */ | |
496 continue; | |
497 dx = ABS(pl2->p_x - p->p_x); /* calc delta coords */ | |
498 dy = ABS(pl2->p_y - p->p_y); | |
499 if ((dx > UCVISIBLE) || (dy > UCVISIBLE)) /* if obviously too far | |
500 * away */ | |
501 continue; /* then don't bother further */ | |
502 dist = ihypot(dx, dy); | |
503 if (dist > UCVISIBLE) /* out of range */ | |
504 continue; /* on to next ship */ | |
505 if ((dist < CVISMIN + CVISSPEED * pl2->p_speed) || | |
506 (!(pl2->p_flags & PFCLOAK))) | |
507 pl2->p_flags |= PFSEEN; /* if close then visible */ | |
508 if ((dist < CVISMIN + CVISSPEED * p->p_speed) || | |
509 (!(p->p_flags & PFCLOAK))) | |
510 p->p_flags |= PFSEEN; /* second player */ | |
511 } | |
512 } | |
513 } | |
514 } | |
515 | |
516 | |
517 | |
518 void | |
519 blast_resource(p, l, res, dival) | |
520 struct player *p; | |
521 struct planet *l; | |
522 int res; | |
523 double dival; | |
524 { | |
525 if (status->tourn) | |
526 { | |
527 p->p_stats.st_di += dival; | |
528 p->p_stats.st_tresbomb++; | |
529 p->p_resbomb++; | |
530 status->resbomb++; | |
531 } | |
532 l->pl_flags &= ~res; | |
533 l->pl_tinfo[l->pl_owner].flags = l->pl_flags; | |
534 l->pl_tinfo[l->pl_owner].timestamp = status->clock; | |
535 l->pl_tinfo[p->p_team].flags = l->pl_flags; | |
536 l->pl_tinfo[p->p_team].timestamp = status->clock; | |
537 l->pl_flags |= PLREDRAW; /* slate for redraw */ | |
538 } | |
539 | |
540 /*-----------------------------------PBOMB---------------------------------*/ | |
541 /* | |
542 * This function goes through the players and does the bombing if any player | |
543 * is bombing. This will knock resources off of planets. If a player is | |
544 * bombing a planet that another team owns, then that team will see the | |
545 * player by having the PFSEEN flag set. | |
546 */ | |
547 | |
548 void | |
549 pbomb() | |
550 { | |
551 struct player *p; /* to point to a player */ | |
552 int i; /* looping var */ | |
553 struct planet *l; /* to point to planet being bombed */ | |
554 char buf[90]; /* to sprintf messages into */ | |
555 char buf1[80]; | |
556 int rnd; /* to hold armies to knock off */ | |
557 | |
558 for (i = 0, p = &players[0]; i < MAXPLAYER; i++, p++) | |
559 { /* go through playrs */ | |
560 if ((p->p_status == PALIVE) /* only do if player is alive */ | |
561 && (p->p_flags & PFORBIT) /* and he is orbiting */ | |
562 && (p->p_flags & PFBOMB)) | |
563 { /* and he is bombing */ | |
564 | |
565 l = &planets[p->p_planet];/* get planet being bombed */ | |
566 | |
567 if ((!((p->p_swar | p->p_hostile) & l->pl_owner)) | |
568 && (l->pl_owner != NOBODY)) | |
569 { | |
570 /* if he's non-hostile, quit bombing */ | |
571 p->p_flags &= ~PFBOMB; | |
572 continue; | |
573 } | |
574 if ((l->pl_warning <= 0) && (l->pl_owner != NOBODY)) | |
575 { /* warning? */ | |
576 l->pl_warning = 50 / PLFIGHTFUSE; /* reset warning timer */ | |
577 sprintf(buf, "We are being attacked by %s %s who is %d%% damaged.", | |
578 p->p_name, twoletters(p), | |
579 (100 * p->p_damage) / (p->p_ship.s_maxdamage)); | |
580 sprintf(buf1, "%-3s->%-3s", l->pl_name, teams[l->pl_owner].shortname); | |
581 pmessage(buf, l->pl_owner, MTEAM | MBOMB, buf1); /* send message */ | |
582 | |
583 /* CRD feature: shipyard guardians - MAK, 2-Jun-93 */ | |
584 if ((l->pl_flags & PLSHIPYARD) && (!status->tourn)) | |
585 { | |
586 rescue(l->pl_owner, 0, l->pl_no); | |
587 } | |
588 } | |
589 p->p_swar |= l->pl_owner; /* set player at war w/ owner */ | |
590 rnd = (lrand48() % 50) + p->p_ship.s_bomb; /* pick random number */ | |
591 rnd = (int) ((float) rnd / 33.0 + 0.5); /* calc armies bombed */ | |
592 if (rnd <= 0) | |
593 continue; /* can't bomb negative armies */ | |
594 if (l->pl_armies > 4) | |
595 { /* if armies to bomb then */ | |
596 l->pl_armies -= rnd; /* kill off armies */ | |
597 tlog_bomb(l, p, rnd); | |
598 l->pl_armies = (l->pl_armies < 1) ? 1 : l->pl_armies; | |
599 l->pl_tinfo[l->pl_owner].armies = l->pl_armies; | |
600 l->pl_tinfo[l->pl_owner].timestamp = status->clock; | |
601 l->pl_tinfo[p->p_team].armies = l->pl_armies; | |
602 l->pl_tinfo[p->p_team].timestamp = status->clock; | |
603 if (l->pl_armies < 5) /* if planet needs to be redrawn */ | |
604 l->pl_flags |= PLREDRAW; /* schedule planet for redraw */ | |
605 if (l->pl_owner != NOBODY) | |
606 { | |
607 credit_armiesbombed(p, rnd, l); | |
608 } | |
609 } /* now do the resource bombing */ | |
610 if ((l->pl_armies > 4) || | |
611 (!configvals->resource_bombing)) /* no bombing resources if | |
612 * armies */ | |
613 continue; /* on planet or in bronco-mode */ | |
614 #if defined(AEDILE) || defined(SLOW_BOMB) | |
615 l->pl_tfuel -= rnd * 5; /* knock fuel timer down */ | |
616 #else | |
617 l->pl_tfuel -= rnd * 8; /* knock fuel timer down */ | |
618 #endif | |
619 l->pl_tfuel = (l->pl_tfuel < 0) ? 0 : l->pl_tfuel; | |
620 if ((l->pl_tfuel == 0) && (l->pl_flags & PLFUEL)) | |
621 { | |
622 blast_resource(p, l, PLFUEL, 0.10); | |
623 tlog_bres(l, p, "FUEL"); | |
624 } | |
625 #if defined(AEDILE) || defined(SLOW_BOMB) | |
626 l->pl_tagri -= rnd * 4; /* attack the agri timer */ | |
627 #else | |
628 l->pl_tagri -= rnd * 6; /* attack the agri timer */ | |
629 #endif | |
630 l->pl_tagri = (l->pl_tagri < 0) ? 0 : l->pl_tagri; | |
631 if ((l->pl_tagri == 0) && (l->pl_flags & PLAGRI)) | |
632 { | |
633 blast_resource(p, l, PLAGRI, 0.25); | |
634 tlog_bres(l, p, "AGRI"); | |
635 } | |
636 #if defined(AEDILE) || defined(SLOW_BOMB) | |
637 l->pl_tshiprepair -= rnd * 5; /* knock ship/repr down */ | |
638 #else | |
639 l->pl_tshiprepair -= rnd * 8; /* knock ship/repr down */ | |
640 #endif | |
641 l->pl_tshiprepair = (l->pl_tshiprepair < 0) ? 0 : | |
642 l->pl_tshiprepair; | |
643 if ((l->pl_tshiprepair < PLGREPAIR) && (l->pl_flags & PLSHIPYARD)) | |
644 { | |
645 blast_resource(p, l, PLSHIPYARD, 0.10); | |
646 tlog_bres(l, p, "SHIPYARD"); | |
647 } | |
648 if ((l->pl_tshiprepair == 0) && (l->pl_flags & PLREPAIR)) | |
649 { | |
650 blast_resource(p, l, PLREPAIR, 0.20); | |
651 tlog_bres(l, p, "REPAIR"); | |
652 } | |
653 } | |
654 } | |
655 } | |
656 | |
657 | |
658 | |
659 | |
660 /*---------------------------------PFIRE-----------------------------------*/ | |
661 /* | |
662 * This function goes through the planets and sees if any enemy players are | |
663 * close enough to be fired upon by the planet. It also checks to see if | |
664 * players are close enough to the planet so that the planet should be | |
665 * redrawn. Enemy planets will 'see' players that are very close to them. | |
666 * THIS FUNCTION SHOULD EVENTUALLY USE THE SPACE GRID. | |
667 */ | |
668 | |
669 void | |
670 pfire() | |
671 { | |
672 struct player *p; /* to point to a player */ | |
673 int i, j; /* looping vars */ | |
674 struct planet *l; /* to point to the planets */ | |
675 int dx, dy; /* to hold delta coords */ | |
676 int dist; /* to hold distance */ | |
677 int dam; /* to hold damage */ | |
678 int boost; /* for warp zones, total boost [BDyess] */ | |
679 | |
680 for (j = 0, p = &players[0]; j < MAXPLAYER; j++, p++) | |
681 { | |
682 if (p->p_status != PALIVE) | |
683 continue; | |
684 boost = 0; /* default no bonus or penalty [BDyess] */ | |
685 for (i = 0, l = &planets[0]; i < NUMPLANETS; i++, l++) | |
686 { | |
687 if ((p->p_team == l->pl_owner) && (PL_TYPE(*l) != PLSTAR) | |
688 && !configvals->warpzone) | |
689 continue; /* no, then continue */ | |
690 dx = ABS(l->pl_x - p->p_x); /* calc delta coorda between */ | |
691 dy = ABS(l->pl_y - p->p_y); /* planet and player */ | |
692 dist = ihypot(dx, dy); | |
693 | |
694 if (dist < configvals->warpzone) | |
695 { | |
696 /* within warp boost/block range [BDyess] */ | |
697 if (p->p_team == l->pl_owner) | |
698 boost += configvals->warpzone - dist; | |
699 else if (l->pl_owner != NOBODY && | |
700 ((p->p_swar | p->p_hostile) & l->pl_owner)) | |
701 boost -= configvals->warpzone - dist; | |
702 } | |
703 | |
704 if (dx < 6 * PLFIREDIST && dy < 6 * PLFIREDIST) /* redraw planet */ | |
705 l->pl_flags |= PLREDRAW;/* if player is very close */ | |
706 | |
707 if (dist <= p->p_ship.s_scanrange) | |
708 { /* check for scanners */ | |
709 scout_planet(p->p_no, l->pl_no); | |
710 #if 0 | |
711 handled in scout_planet now. | |
712 l->pl_hinfo |= p->p_team; | |
713 l->pl_tinfo[p->p_team].armies = l->pl_armies; | |
714 l->pl_tinfo[p->p_team].flags = l->pl_flags; | |
715 l->pl_tinfo[p->p_team].owner = l->pl_owner; | |
716 l->pl_tinfo[p->p_team].timestamp = status->clock; | |
717 #endif | |
718 } | |
719 | |
720 if (dist > PLVISDIST) | |
721 continue; | |
722 if ((dist < PLVISDIST) && (l->pl_owner != NOBODY) /* enemy planet */ | |
723 && ((p->p_swar | p->p_hostile) & l->pl_owner)) /* see players */ | |
724 p->p_flags |= PFSEEN; /* let team see enemy */ | |
725 if ((dist > PFIREDIST) || | |
726 ((dist > PFIREDIST / 2) && | |
727 (PL_TYPE(*l) == PLWHOLE))) /* if not within range */ | |
728 continue; /* go on to next playert */ | |
729 if (((p->p_swar | p->p_hostile) & l->pl_owner) | |
730 || ((l->pl_owner == NOBODY) | |
731 #if 1 | |
732 && (l->pl_hostile & p->p_team) | |
733 #else | |
734 && (l->pl_torbit & (p->p_team << 4)) | |
735 #endif | |
736 && (l->pl_armies != 0)) | |
737 || (PL_TYPE(*l) == PLWHOLE) || (PL_TYPE(*l) == PLSTAR)) | |
738 { | |
739 dam = l->pl_armies / 7 + 2; /* calc the damage */ | |
740 if (PL_TYPE(*l) == PLWHOLE) | |
741 { /* if a wormhole... */ | |
742 /* ...place outside the new wormhole's radius. */ | |
743 if ((wh_effect[SS_WARP] && !(p->p_flags & PFWARP)) | |
744 || (!wh_effect[SS_WARP])) | |
745 { | |
746 p->p_x = l->pl_armies + | |
747 (((PLFIREDIST / 2) + 50) * Cos[p->p_dir]); | |
748 p->p_y = l->pl_radius + | |
749 (((PLFIREDIST / 2) + 50) * Sin[p->p_dir]); | |
750 } | |
751 if ((p->p_speed > (p->p_ship.s_imp.maxspeed / 2)) && | |
752 (wh_effect[SS_IMPULSE])) | |
753 { | |
754 dam = ((p->p_ship.s_mass / 100) * (p->p_speed - | |
755 p->p_ship.s_imp.maxspeed / 2)); | |
756 } | |
757 else | |
758 dam = 0; | |
759 | |
760 } | |
761 else if (PL_TYPE(*l) == PLSTAR) /* if planet is a star */ | |
762 dam = 150; /* do massive damage */ | |
763 /* | |
764 * this needs to be reworked and most of it jammed into | |
765 * inflict_damage | |
766 */ | |
767 p->p_whodead = i; /* which planet is shooting */ | |
768 if (dam > 0 && inflict_damage(0, 0, p, dam, KPLANET)) | |
769 { | |
770 struct player *killer = 0; | |
771 p->p_whydead = KPLANET; /* set killed by a planet */ | |
772 if (PL_TYPE(*l) == PLSTAR) | |
773 { /* killed by star? */ | |
774 #ifdef GIVESTARKILLS | |
775 int pln; | |
776 for (pln = 0, killer = &players[0]; | |
777 pln < MAXPLAYER; | |
778 pln++, killer++) | |
779 { | |
780 if (killer->p_status != PALIVE) | |
781 continue; | |
782 if (!friendly(killer, p) && killer->p_tractor == p->p_no | |
783 && killer->p_flags & (PFTRACT | PFPRESS)) | |
784 { | |
785 | |
786 killer->p_kills += 1 + (p->p_armies + p->p_kills) / 10; | |
787 killerstats(killer->p_no, p); | |
788 checkmaxkills(killer->p_no); | |
789 break; | |
790 } | |
791 } | |
792 if (pln >= MAXPLAYER) | |
793 killer = 0; | |
794 #endif | |
795 } | |
796 killmess(p, killer); | |
797 tlog_plankill(p, l, killer); | |
798 } | |
799 } | |
800 } | |
801 /* found the boost for this player, make adjustments if in warp [BDyess] */ | |
802 if (configvals->warpzone && p->p_flags & PFWARP) | |
803 { | |
804 if (boost == 0 && p->p_zone > 0) | |
805 { /* did get warp bonus, lost it */ | |
806 if (p->p_desspeed > p->p_ship.s_warp.maxspeed) | |
807 p->p_desspeed = p->p_ship.s_warp.maxspeed; | |
808 } | |
809 else if (boost < 0 && p->p_zone >= 0) | |
810 { /* warp no longer allowed */ | |
811 p->p_desspeed = p->p_ship.s_imp.maxspeed; | |
812 if (!configvals->warpdecel) | |
813 p->p_flags &= ~PFWARP; | |
814 } | |
815 } | |
816 p->p_zone = boost; | |
817 } | |
818 } | |
819 | |
820 | |
821 | |
822 | |
823 /*---------------------------------REVOLT---------------------------------*/ | |
824 /* | |
825 * This function does the revolt of a planet. It updates the revolt timer | |
826 * and prints the messages that warn the team. | |
827 */ | |
828 | |
829 void | |
830 revolt(l) | |
831 struct planet *l; /* the planet to check */ | |
832 { | |
833 if (!configvals->revolts) | |
834 return; | |
835 | |
836 if (l->pl_trevolt > 0) | |
837 { /* revolt timer running? */ | |
838 char buf[80]; /* to sprintf into */ | |
839 | |
840 { | |
841 int i; | |
842 for (i = 0; i < MAXPLAYER; i++) | |
843 { | |
844 if (players[i].p_status == PALIVE | |
845 && (players[i].p_flags & (PFORBIT | PFDOCK)) == PFORBIT | |
846 && players[i].p_planet == l->pl_no | |
847 && players[i].p_team == l->pl_owner) | |
848 return; /* orbiting ship delays revolt */ | |
849 } | |
850 } | |
851 | |
852 l->pl_trevolt--; /* dec the timer */ | |
853 if ((l->pl_trevolt == 0) && (l->pl_armies > 2)) | |
854 { | |
855 l->pl_trevolt = 0; /* turn off revolt timer */ | |
856 sprintf(buf, "The revolution on %s has been put down.", | |
857 l->pl_name); /* get message to display */ | |
858 pmessage(buf, l->pl_owner, MTEAM | MCONQ, "PREFECT->"); | |
859 } | |
860 else if ((l->pl_trevolt == 0) && (l->pl_armies == 2)) | |
861 { | |
862 l->pl_trevolt = STARTREV; /* more time til last army */ | |
863 l->pl_armies--; /* kill one army */ | |
864 l->pl_tinfo[l->pl_owner].armies = l->pl_armies; | |
865 l->pl_tinfo[l->pl_owner].timestamp = status->clock; | |
866 sprintf(buf, "We cannot hold out much longer on %s", | |
867 l->pl_name); /* get message to display */ | |
868 pmessage(buf, l->pl_owner, MTEAM | MCONQ, "PREFECT->"); | |
869 } | |
870 else if (l->pl_trevolt == 0) | |
871 { | |
872 l->pl_trevolt = 0; /* revolution succeeded */ | |
873 sprintf(buf, "The planet %s has been lost to revolutionaries", | |
874 l->pl_name); /* get message to display */ | |
875 pmessage(buf, l->pl_owner, MTEAM | MCONQ, "PREFECT->"); | |
876 | |
877 tlog_revolt(l); | |
878 | |
879 l->pl_tinfo[l->pl_owner].timestamp = status->clock; | |
880 l->pl_tinfo[l->pl_owner].owner = NOBODY; | |
881 l->pl_owner = NOBODY; | |
882 l->pl_flags |= PLREDRAW; /* slate for redraw */ | |
883 checkwin(enemy_admiral(-1)); /* check for game end */ | |
884 | |
885 } | |
886 } | |
887 else | |
888 { /* no revolt timer--check for start */ | |
889 if ((l->pl_armies <= 2) && (!(l->pl_armies == 0)) | |
890 && ((lrand48() % 1000) <= REVOLT)) | |
891 { | |
892 char buf[80]; /* to sprintf message into */ | |
893 | |
894 sprintf(buf, "There is civil unrest on %s", l->pl_name); | |
895 pmessage(buf, l->pl_owner, MTEAM | MCONQ, "PREFECT>>"); | |
896 l->pl_trevolt = STARTREV; /* time before revolution */ | |
897 } | |
898 } | |
899 } | |
900 | |
901 void | |
902 check_revolt() | |
903 { | |
904 static int planetlist[MAXPLANETS]; | |
905 static int count = 0; | |
906 int idx; | |
907 struct planet *l; | |
908 | |
909 if (!status->tourn) | |
910 return; | |
911 | |
912 if (count < 1) | |
913 fill_planets(planetlist, &count, -1); | |
914 | |
915 idx = planetlist[--count]; | |
916 l = &planets[idx]; | |
917 | |
918 if (l->pl_armies > 0 && l->pl_owner != NOBODY) | |
919 revolt(l); | |
920 } | |
921 | |
922 /*-------------------------------------------------------------------------*/ | |
923 | |
924 | |
925 | |
926 | |
927 | |
928 | |
929 /* struct planet *stars[NUMPLANETS + 1]; */ | |
930 | |
931 static void | |
932 build_stars_array() | |
933 { | |
934 int i; | |
935 struct planet *pl; | |
936 | |
937 for (i = 0; i < NUMPLANETS; i++) | |
938 { | |
939 pl = &planets[i]; | |
940 if (PL_TYPE(*pl) == PLSTAR) | |
941 stars[pl->pl_system] = i; | |
942 } | |
943 } | |
944 | |
945 /*------------------------------VISIBLE FUNCTIONS-------------------------*/ | |
946 | |
947 /*-------------------------------GEN_PLANETS-------------------------------*/ | |
948 /* | |
949 * This function generates a number of random planets. The planets are | |
950 * arranged in systems and are also placed so that they are not too close to | |
951 * any other planets. The races are then given home planets. | |
952 */ | |
953 | |
954 void | |
955 gen_planets() | |
956 { | |
957 int i; | |
958 struct planet *pl; | |
959 | |
960 status->clock = 0; /* reset the timestamp clock */ | |
961 | |
962 switch (configvals->galaxygenerator) | |
963 { | |
964 case 2: | |
965 gen_galaxy_2(); /* Bob Forsman's compact galaxy generator */ | |
966 break; | |
967 case 3: | |
968 gen_galaxy_3(); /* Heath's better race placement galaxy | |
969 * generator */ | |
970 break; | |
971 case 4: | |
972 gen_galaxy_4(); /* Mike's Bronco emulator */ | |
973 break; | |
974 case 5: | |
975 gen_galaxy_5(); /* Mike's small-galaxy generator */ | |
976 break; | |
977 case 6: | |
978 gen_galaxy_6(); /* Brandon's hack on Heath's to give 2 */ | |
979 break; /* systems to each race */ | |
980 case 7: | |
981 gen_galaxy_7(); /* Eric Dormans deepspace galaxy gen, rooted | |
982 * in galaxy gen 6. */ | |
983 break; | |
984 case 1: | |
985 default: | |
986 gen_galaxy_1(); /* original paradiseII galaxy generator */ | |
987 break; | |
988 } | |
989 | |
990 if (configvals->galaxygenerator != 4) | |
991 { | |
992 /* gotta do this before they are sorted */ | |
993 for (i = 0; i < NUMPLANETS; i++) | |
994 { | |
995 pl = &planets[i]; | |
996 if (PL_TYPE(*pl) == PLSTAR || | |
997 ((pl->pl_system == 0) && (PL_TYPE(*pl) != PLWHOLE))) | |
998 { | |
999 pl->pl_radius = 0; | |
1000 pl->pl_angle = 0; | |
1001 } | |
1002 else if (PL_TYPE(*pl) != PLWHOLE) | |
1003 { | |
1004 int dx, dy; | |
1005 dx = pl->pl_x - planets[pl->pl_system - 1].pl_x; | |
1006 dy = pl->pl_y - planets[pl->pl_system - 1].pl_y; | |
1007 pl->pl_radius = ihypot(dx, dy); | |
1008 pl->pl_angle = atan2((double) dy, (double) dx); | |
1009 } | |
1010 } | |
1011 sortnames(); /* sort the names of planets */ | |
1012 build_stars_array(); | |
1013 if (configvals->neworbits) | |
1014 pl_neworbit(); | |
1015 generate_terrain(); | |
1016 } | |
1017 } | |
1018 | |
1019 void | |
1020 pl_neworbit() | |
1021 /* | |
1022 * rearranges a pre-existing galaxy setup such that planets orbit at more | |
1023 * "unique" distances from their star. Asteroids look and probably play bad | |
1024 * when all the planets are approx. the same dist from the star, so I'd | |
1025 * suggest turning this on if you plan to have asteroids or orbiting planets | |
1026 * on your server. I'd suggest turning it on even if you don't. :) -MDM | |
1027 */ | |
1028 { | |
1029 register int i, j; | |
1030 register struct planet *p; | |
1031 register int numStars = 0, planetsThisStar = 0; | |
1032 #ifndef IRIX | |
1033 int planetList[NUMPLANETS]; | |
1034 #else | |
1035 int planetList[70]; | |
1036 #endif | |
1037 | |
1038 /* find the number of stars */ | |
1039 for (i = 0; i < MAXPLANETS; i++) | |
1040 if (PL_TYPE(planets[i]) == PLSTAR) | |
1041 numStars++; | |
1042 | |
1043 /* for each star, find the number of planets, and the average distance */ | |
1044 | |
1045 for (i = 1; i <= numStars; i++) | |
1046 { | |
1047 planetsThisStar = 0; | |
1048 for (j = 0; j < MAXPLANETS; j++) | |
1049 if (planets[j].pl_system == i) | |
1050 planetList[planetsThisStar++] = j; | |
1051 | |
1052 /* | |
1053 * now move the planets such that each planet we came across gets its | |
1054 * previous distance from it's star, times (it's position in the | |
1055 * planetList array)/(planetsThisStar/1.6). also make sure that new | |
1056 * radius isin't so close to star ship can't orbit it. Heh. Separate | |
1057 * the men from the boyz, eh? | |
1058 */ | |
1059 | |
1060 for (j = 0; j < planetsThisStar; j++) | |
1061 { | |
1062 planets[planetList[j]].pl_radius = | |
1063 (int) ((float) planets[planetList[j]].pl_radius * | |
1064 ((float) (j + 1) / (float) (planetsThisStar / 1.6))) + 1500; | |
1065 planets[planetList[j]].pl_x = | |
1066 planets[stars[i]].pl_x + | |
1067 (int) ((float) cos(planets[planetList[j]].pl_angle) * | |
1068 (float) planets[planetList[j]].pl_radius); | |
1069 planets[planetList[j]].pl_y = | |
1070 planets[stars[i]].pl_y + | |
1071 (int) ((float) sin(planets[planetList[j]].pl_angle) * | |
1072 (float) planets[planetList[j]].pl_radius); | |
1073 } | |
1074 } | |
1075 } | |
1076 | |
1077 void | |
1078 moveplanets() | |
1079 { | |
1080 register int i; /* for looping */ | |
1081 register struct planet *l; /* to point to individual plaent */ | |
1082 | |
1083 if (stars[1] < 0) | |
1084 build_stars_array(); | |
1085 | |
1086 /* totally experimental planet moving stuff */ | |
1087 for (i = 0; i < NUMPLANETS; i++) | |
1088 { | |
1089 int x, y; | |
1090 double r; | |
1091 l = &planets[i]; | |
1092 if (PL_TYPE(*l) == PLSTAR || l->pl_system == 0) | |
1093 continue; /* write code for them another time */ | |
1094 | |
1095 r = l->pl_radius; | |
1096 l->pl_angle += configvals->planupdspd * 1e2 / sqrt(r * r * r); | |
1097 if (l->pl_angle > 2 * M_PI) | |
1098 l->pl_angle -= 2 * M_PI; | |
1099 x = planets[stars[l->pl_system]].pl_x + cos(l->pl_angle) * l->pl_radius; | |
1100 y = planets[stars[l->pl_system]].pl_y + sin(l->pl_angle) * l->pl_radius; | |
1101 move_planet(i, x, y, 1); | |
1102 } | |
1103 } | |
1104 | |
1105 | |
1106 /* | |
1107 * This function pops the armies on planets. It now uses the tables that are | |
1108 * in this module. Negative growth is supported. | |
1109 */ | |
1110 | |
1111 static void | |
1112 pop_one_planet1(l) | |
1113 struct planet *l; | |
1114 { | |
1115 int r; /* to hold resource index */ | |
1116 int a; /* to hold atmosphere index */ | |
1117 int t; /* temp var */ | |
1118 float ft; /* another temp */ | |
1119 | |
1120 r = (l->pl_flags & PLRESMASK) >> PLRESSHIFT; /* get resource bits */ | |
1121 r = restores[r]; /* convert to 3 bits */ | |
1122 a = l->pl_flags & PLATMASK; /* get atmosphere bits */ | |
1123 a = a >> PLATSHIFT; /* shift to lower two bits of int */ | |
1124 | |
1125 #ifdef UFL | |
1126 t = status2->league ? popchance[a][r] : 8; | |
1127 #else | |
1128 t = popchance[a][r]; /* get pop chance */ | |
1129 #endif | |
1130 if (t < lrand48() % 100) /* if planet misses chance */ | |
1131 return; /* then on to next planet */ | |
1132 ft = popmult[a][r]; /* get pop multiplier */ | |
1133 if (ft >= 0) | |
1134 { /* positive multiplier */ | |
1135 int incr; | |
1136 | |
1137 if (l->pl_armies >= popcap[a][r]) | |
1138 return; | |
1139 | |
1140 if (l->pl_armies < 4) /* chance of going over four */ | |
1141 l->pl_flags |= PLREDRAW; /* slate planet for redraw */ | |
1142 if (configvals->new_army_growth) | |
1143 #ifdef AEDILE | |
1144 incr = 0.5 + ft * 2.0 * (float) (lrand48() % 6 + 3); | |
1145 #else | |
1146 incr = 1 + 0.5 + ft * (float) (l->pl_armies); | |
1147 #endif | |
1148 else | |
1149 /* what about agri? */ | |
1150 incr = 1 + lrand48() % 3; /* bronco is always 1-3 armies/pop */ | |
1151 tlog_pop(l, incr); | |
1152 l->pl_armies += incr; /* add on multiplier armies */ | |
1153 l->pl_tinfo[l->pl_owner].armies = l->pl_armies; | |
1154 l->pl_tinfo[l->pl_owner].timestamp = status->clock; | |
1155 } | |
1156 else | |
1157 { /* negative multiplier */ | |
1158 int decr; | |
1159 if (l->pl_armies < 4) /* no killing all the armies on */ | |
1160 return; /* a planet */ | |
1161 l->pl_flags |= PLREDRAW; /* slate planet for redraw */ | |
1162 decr = 1 + 0.5 - ft * (float) (l->pl_armies); | |
1163 tlog_pop(l, -decr); | |
1164 l->pl_armies -= decr; /* subtract armies */ | |
1165 l->pl_armies = (l->pl_armies < 0) ? 0 : l->pl_armies; | |
1166 if (l->pl_armies <= 0) | |
1167 { /* if all died then */ | |
1168 l->pl_armies = 0; /* no negative armies */ | |
1169 l->pl_tinfo[l->pl_owner].armies = 0; /* old owner knows */ | |
1170 l->pl_tinfo[l->pl_owner].timestamp = status->clock; | |
1171 l->pl_tinfo[l->pl_owner].owner = NOBODY; | |
1172 l->pl_owner = NOBODY; /* planet is neutral */ | |
1173 } | |
1174 l->pl_tinfo[l->pl_owner].armies = l->pl_armies; | |
1175 l->pl_tinfo[l->pl_owner].timestamp = status->clock; | |
1176 if (l->pl_armies == 0) /* if all armies died */ | |
1177 checkwin(enemy_admiral(-1)); /* check if game over */ | |
1178 } | |
1179 } | |
1180 /* | |
1181 * */ | |
1182 | |
1183 static void | |
1184 pop_one_planet2(l) | |
1185 struct planet *l; | |
1186 { | |
1187 int delta = 0; | |
1188 int atmosphere = (l->pl_flags & PLATMASK) >> PLATSHIFT; | |
1189 int surface = (l->pl_flags & PLSURMASK) >> PLSURSHIFT; | |
1190 | |
1191 if (l->pl_armies < 4 && (l->pl_flags & PLAGRI)) | |
1192 delta++; | |
1193 | |
1194 if (atmosphere == 0) | |
1195 { | |
1196 if (l->pl_armies >= 4 && drand48() < 0.5) | |
1197 { | |
1198 delta--; | |
1199 } | |
1200 } | |
1201 else if (atmosphere < 3) | |
1202 { | |
1203 if (drand48() < | |
1204 ((atmosphere == 1) | |
1205 ? (l->pl_armies < 4 ? 0.2 : 0.1) | |
1206 : (l->pl_armies < 4 ? 0.5 : 0.2))) | |
1207 { | |
1208 delta++; | |
1209 } | |
1210 } | |
1211 else | |
1212 { | |
1213 if (drand48() < (l->pl_armies < 4 ? 0.3 : 0.2)) | |
1214 { | |
1215 static int table[] = {2, 2, 2, 3, 3, 3, 4, 4}; | |
1216 int max = table[surface]; | |
1217 delta++; | |
1218 if (l->pl_flags & PLAGRI && l->pl_armies >= 4) | |
1219 max++; /* armies<4 handled at top */ | |
1220 delta += lrand48() % max; | |
1221 } | |
1222 } | |
1223 | |
1224 if (l->pl_armies == 0 && delta > 1) | |
1225 delta = 1; /* training that first army is tough */ | |
1226 | |
1227 tlog_pop(l, delta); | |
1228 | |
1229 if (delta > 0 && | |
1230 l->pl_armies > popcap[atmosphere] | |
1231 [restores[(l->pl_flags & PLRESMASK) >> PLRESSHIFT]]) | |
1232 delta = 0; | |
1233 l->pl_armies += delta; | |
1234 | |
1235 /* | |
1236 * I doubt this if statement will ever get executed unless someone's | |
1237 * frobbing shmem | |
1238 */ | |
1239 if (l->pl_armies <= 0) | |
1240 { /* if all died then */ | |
1241 l->pl_armies = 0; /* no negative armies */ | |
1242 | |
1243 tlog_revolt(l); /* well, not exactly. */ | |
1244 | |
1245 l->pl_tinfo[l->pl_owner].armies = 0; /* old owner knows */ | |
1246 l->pl_tinfo[l->pl_owner].timestamp = status->clock; | |
1247 l->pl_tinfo[l->pl_owner].owner = NOBODY; | |
1248 l->pl_owner = NOBODY; /* planet is neutral */ | |
1249 checkwin(enemy_admiral(-1));/* check if game over */ | |
1250 } | |
1251 | |
1252 l->pl_tinfo[l->pl_owner].armies = l->pl_armies; | |
1253 l->pl_tinfo[l->pl_owner].timestamp = status->clock; | |
1254 } | |
1255 | |
1256 void | |
1257 pop_one_planet(l) | |
1258 struct planet *l; | |
1259 { | |
1260 #if 0 | |
1261 printf("popping planet #%d %x\n", l->pl_no, l->pl_owner); | |
1262 fflush(stdout); | |
1263 #endif | |
1264 | |
1265 switch (configvals->popscheme) | |
1266 { | |
1267 case 1: | |
1268 pop_one_planet2(l); | |
1269 break; | |
1270 default: | |
1271 case 0: | |
1272 pop_one_planet1(l); | |
1273 break; | |
1274 } | |
1275 } | |
1276 | |
1277 | |
1278 /*-------------------------------UDPLANETS----------------------------------*/ | |
1279 | |
1280 void | |
1281 fill_planets(plist, count, owner) | |
1282 int *plist; /* array */ | |
1283 int *count; /* scalar */ | |
1284 int owner; | |
1285 { | |
1286 int i; | |
1287 *count = 0; | |
1288 for (i = 0; i < configvals->numplanets; i++) | |
1289 { | |
1290 if (owner < 0 || planets[i].pl_owner == owner) | |
1291 plist[(*count)++] = i; | |
1292 } | |
1293 | |
1294 for (i = *count - 1; i > 0; i--) | |
1295 { | |
1296 int idx = lrand48() % (i + 1); | |
1297 int temp = plist[idx]; | |
1298 plist[idx] = plist[i]; | |
1299 plist[i] = temp; | |
1300 } | |
1301 } | |
1302 | |
1303 int | |
1304 find_other_team(teammask) | |
1305 int teammask; | |
1306 { | |
1307 int counts[NUMTEAM]; | |
1308 int i; | |
1309 for (i = 0; i < NUMTEAM; i++) | |
1310 counts[i] = 0; | |
1311 for (i = 0; i < MAXPLAYER; i++) | |
1312 { | |
1313 int teamidx = mask_to_idx(players[i].p_team); | |
1314 if (teamidx >= 0 && teamidx < NUMTEAM && !(teammask & (1 << teamidx))) | |
1315 counts[teamidx]++; | |
1316 } | |
1317 | |
1318 { | |
1319 int max = -1; | |
1320 int rval = 0; | |
1321 for (i = 0; i < NUMTEAM; i++) | |
1322 { | |
1323 if (counts[i] > max && !(teammask & (1 << i))) | |
1324 { | |
1325 max = counts[i]; | |
1326 rval = 1 << i; | |
1327 } | |
1328 } | |
1329 return rval; | |
1330 } | |
1331 } | |
1332 | |
1333 void | |
1334 popplanets() | |
1335 { | |
1336 register int i; /* for looping */ | |
1337 register struct planet *l; /* to point to individual plaent */ | |
1338 | |
1339 if (!status->tourn) /* check t-mode */ | |
1340 return; /* do not pop planets */ | |
1341 | |
1342 switch (configvals->popchoice) | |
1343 { | |
1344 case 0: | |
1345 { | |
1346 static int fuse = 0; | |
1347 if (++fuse < PLANETFUSE) | |
1348 return; /* nothing to do */ | |
1349 fuse = 0; | |
1350 for (i = 0, l = &planets[i]; i < NUMPLANETS; i++, l++) | |
1351 { | |
1352 if ((l->pl_armies == 0) || | |
1353 (PL_TYPE(*l) == PLSTAR) || | |
1354 (PL_TYPE(*l) == PLWHOLE)) /* if no armies to pop */ | |
1355 continue; /* go to next planet */ | |
1356 #if 0 | |
1357 if (l->pl_owner != NOBODY) /* only team planets can revolt */ | |
1358 revolt(l); /* check for revolt */ | |
1359 #endif | |
1360 pop_one_planet(l); | |
1361 } | |
1362 } break; | |
1363 case 1: | |
1364 { | |
1365 #if 0 | |
1366 static int indplanets[MAXPLANETS]; | |
1367 static int indcount = 0; | |
1368 #endif | |
1369 static int Aplanets[MAXPLANETS]; | |
1370 static int Acount = 0, Amask = 0; | |
1371 static int Bplanets[MAXPLANETS]; | |
1372 static int Bcount = 0, Bmask = 0; | |
1373 | |
1374 int INDchance; | |
1375 float Achance, Bchance; | |
1376 float f; | |
1377 | |
1378 /* make sure there's planets in the lists */ | |
1379 #if 0 | |
1380 if (indcount < 1) | |
1381 fill_planets(indplanets, &indcount, NOBODY); | |
1382 #endif | |
1383 if (Acount < 1) | |
1384 { | |
1385 Amask = find_other_team(Bmask); | |
1386 fill_planets(Aplanets, &Acount, Amask); | |
1387 } | |
1388 if (Bcount < 1) | |
1389 { | |
1390 Bmask = find_other_team(Amask); | |
1391 fill_planets(Bplanets, &Bcount, Bmask); | |
1392 } | |
1393 | |
1394 /* figure out the probabilities */ | |
1395 INDchance = Achance = Bchance = 0; | |
1396 for (i = 0; i < configvals->numplanets; i++) | |
1397 { | |
1398 if (planets[i].pl_owner == Amask) | |
1399 Achance += 1.0; | |
1400 else if (planets[i].pl_owner == Bmask) | |
1401 Bchance += 1.0; | |
1402 else if (!((PL_TYPE(planets[i]) == PLSTAR) || | |
1403 (PL_TYPE(planets[i]) == PLWHOLE))) | |
1404 /* if (planets[i].pl_owner == NOBODY) */ | |
1405 INDchance += 1.0; | |
1406 } | |
1407 | |
1408 #ifdef LOOSING_ADVANTAGE | |
1409 { | |
1410 double la = LOOSING_ADVANTAGE; | |
1411 if (Achance < Bchance) | |
1412 Achance *= (la - (la - 1) * Achance / Bchance); | |
1413 else | |
1414 Bchance *= (la - (la - 1) * Bchance / Achance); | |
1415 } | |
1416 #endif | |
1417 | |
1418 f = drand48() * (INDchance + Achance + Bchance); | |
1419 if (f < INDchance) | |
1420 { | |
1421 #if 0 /* 3rd-race planets and INDs don't pop */ | |
1422 pop_one_planet(&planets[indplanets[--indcount]]); | |
1423 #endif | |
1424 } | |
1425 else if (f - INDchance < Achance) | |
1426 { | |
1427 pop_one_planet(&planets[Aplanets[--Acount]]); | |
1428 } | |
1429 else | |
1430 { | |
1431 pop_one_planet(&planets[Bplanets[--Bcount]]); | |
1432 } | |
1433 | |
1434 } break; | |
1435 } | |
1436 } | |
1437 | |
1438 | |
1439 | |
1440 | |
1441 | |
1442 /*----------------------------------PLFIGHT--------------------------------*/ | |
1443 /* | |
1444 * This function does the fighting for a planet. It decs the warning timer | |
1445 * and clears the REDRAW flag. It then handles the bombing for the players. | |
1446 * It then goes on to see if a player is visible to the other team by | |
1447 * checking the closeness of other players. The planets are then checked to | |
1448 * see if they are close enough to fire on enemy players. | |
1449 */ | |
1450 | |
1451 void | |
1452 plfight() | |
1453 { | |
1454 register int h; /* looping vars */ | |
1455 register struct planet *l; /* for looping through planets */ | |
1456 | |
1457 for (h = 0, l = &planets[h]; h < NUMPLANETS; h++, l++) | |
1458 { | |
1459 l->pl_flags &= ~PLREDRAW; /* clear the PLDRAW flag */ | |
1460 if (l->pl_warning > 0) /* check if timer needs dec */ | |
1461 l->pl_warning--; /* dec the warning timer */ | |
1462 } | |
1463 pbomb(); /* go do bombing for players */ | |
1464 pvisible(); /* check visibility w/ other players */ | |
1465 pfire(); /* let planets fire on other players */ | |
1466 } | |
1467 | |
1468 | |
1469 | |
1470 | |
1471 /*-------------------------------SAVE_PLANETS-----------------------------*/ | |
1472 /* | |
1473 * This function saves the planets structure to disk. The plfd variable is a | |
1474 * handle on the previously opened .planets file. The function also saves | |
1475 * the status to the glfd file. | |
1476 */ | |
1477 | |
1478 void | |
1479 save_planets() | |
1480 { | |
1481 if (plfd >= 0) | |
1482 { /* if plfd file open */ | |
1483 (void) lseek(plfd, (long) 0, 0); /* save the planets */ | |
1484 (void) write(plfd, (char *) planets, sizeof(struct planet) * MAXPLANETS); | |
1485 } | |
1486 if (glfd >= 0) | |
1487 { /* if glfd file open then */ | |
1488 (void) lseek(glfd, (long) 0, 0); /* save the status */ | |
1489 (void) write(glfd, (char *) status, sizeof(struct status)); | |
1490 } | |
1491 } | |
1492 | |
1493 /*-------------------------------------------------------------------------*/ | |
1494 | |
1495 | |
1496 | |
1497 /*----------END OF FILE--------*/ |