6
|
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--------*/
|