1 //Copyright Paul Reiche, Fred Ford. 1992-2002
2
3 /*
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 */
18
19 #include "genall.h"
20 #include "../lander.h"
21 #include "../lifeform.h"
22 #include "../planets.h"
23 #include "../../build.h"
24 #include "../../encount.h"
25 #include "../../globdata.h"
26 #include "../../gamestr.h"
27 #include "../../grpinfo.h"
28 #include "../../nameref.h"
29 #include "../../state.h"
30 #include "libs/mathlib.h"
31
32
33 static bool GenerateSol_initNpcs (SOLARSYS_STATE *solarSys);
34 static bool GenerateSol_reinitNpcs (SOLARSYS_STATE *solarSys);
35 static bool GenerateSol_generatePlanets (SOLARSYS_STATE *solarSys);
36 static bool GenerateSol_generateMoons (SOLARSYS_STATE *solarSys,
37 PLANET_DESC *planet);
38 static bool GenerateSol_generateName (const SOLARSYS_STATE *,
39 const PLANET_DESC *world);
40 static bool GenerateSol_generateOrbital (SOLARSYS_STATE *solarSys,
41 PLANET_DESC *world);
42 static COUNT GenerateSol_generateEnergy (const SOLARSYS_STATE *,
43 const PLANET_DESC *world, COUNT whichNode, NODE_INFO *);
44 static COUNT GenerateSol_generateLife (const SOLARSYS_STATE *,
45 const PLANET_DESC *world, COUNT whichNode, NODE_INFO *);
46 static bool GenerateSol_pickupEnergy (SOLARSYS_STATE *solarSys,
47 PLANET_DESC *world, COUNT whichNode);
48
49 static int init_probe (void);
50 static void check_probe (void);
51
52
53 const GenerateFunctions generateSolFunctions = {
54 /* .initNpcs = */ GenerateSol_initNpcs,
55 /* .reinitNpcs = */ GenerateSol_reinitNpcs,
56 /* .uninitNpcs = */ GenerateDefault_uninitNpcs,
57 /* .generatePlanets = */ GenerateSol_generatePlanets,
58 /* .generateMoons = */ GenerateSol_generateMoons,
59 /* .generateName = */ GenerateSol_generateName,
60 /* .generateOrbital = */ GenerateSol_generateOrbital,
61 /* .generateMinerals = */ GenerateDefault_generateMinerals,
62 /* .generateEnergy = */ GenerateSol_generateEnergy,
63 /* .generateLife = */ GenerateSol_generateLife,
64 /* .pickupMinerals = */ GenerateDefault_pickupMinerals,
65 /* .pickupEnergy = */ GenerateSol_pickupEnergy,
66 /* .pickupLife = */ GenerateDefault_pickupLife,
67 };
68
69
70 static bool
GenerateSol_initNpcs(SOLARSYS_STATE * solarSys)71 GenerateSol_initNpcs (SOLARSYS_STATE *solarSys)
72 {
73 GLOBAL (BattleGroupRef) = GET_GAME_STATE_32 (URQUAN_PROBE_GRPOFFS0);
74 if (GLOBAL (BattleGroupRef) == 0)
75 {
76 CloneShipFragment (URQUAN_DRONE_SHIP, &GLOBAL (npc_built_ship_q), 0);
77 GLOBAL (BattleGroupRef) = PutGroupInfo (GROUPS_ADD_NEW, 1);
78 ReinitQueue (&GLOBAL (npc_built_ship_q));
79 SET_GAME_STATE_32 (URQUAN_PROBE_GRPOFFS0, GLOBAL (BattleGroupRef));
80 }
81
82 if (!init_probe ())
83 GenerateDefault_initNpcs (solarSys);
84
85 return true;
86 }
87
88 static bool
GenerateSol_reinitNpcs(SOLARSYS_STATE * solarSys)89 GenerateSol_reinitNpcs (SOLARSYS_STATE *solarSys)
90 {
91 if (GET_GAME_STATE (CHMMR_BOMB_STATE) != 3)
92 {
93 GenerateDefault_reinitNpcs (solarSys);
94 check_probe ();
95 }
96 else
97 {
98 GLOBAL (BattleGroupRef) = 0;
99 ReinitQueue (&GLOBAL (ip_group_q));
100 assert (CountLinks (&GLOBAL (npc_built_ship_q)) == 0);
101 }
102 return true;
103 }
104
105 static bool
GenerateSol_generatePlanets(SOLARSYS_STATE * solarSys)106 GenerateSol_generatePlanets (SOLARSYS_STATE *solarSys)
107 {
108 COUNT planetI;
109
110 #define SOL_SEED 334241042L
111 RandomContext_SeedRandom (SysGenRNG, SOL_SEED);
112
113 solarSys->SunDesc[0].NumPlanets = 9;
114 for (planetI = 0; planetI < 9; ++planetI)
115 {
116 COUNT angle;
117 DWORD rand_val;
118 UWORD word_val;
119 PLANET_DESC *pCurDesc = &solarSys->PlanetDesc[planetI];
120
121 pCurDesc->rand_seed = RandomContext_Random (SysGenRNG);
122 rand_val = pCurDesc->rand_seed;
123 word_val = LOWORD (rand_val);
124 angle = NORMALIZE_ANGLE ((COUNT)HIBYTE (word_val));
125
126 switch (planetI)
127 {
128 case 0: /* MERCURY */
129 pCurDesc->data_index = METAL_WORLD;
130 pCurDesc->radius = EARTH_RADIUS * 39L / 100;
131 pCurDesc->NumPlanets = 0;
132 break;
133 case 1: /* VENUS */
134 pCurDesc->data_index = PRIMORDIAL_WORLD;
135 pCurDesc->radius = EARTH_RADIUS * 72L / 100;
136 pCurDesc->NumPlanets = 0;
137 angle = NORMALIZE_ANGLE (FULL_CIRCLE - angle);
138 break;
139 case 2: /* EARTH */
140 pCurDesc->data_index = WATER_WORLD | PLANET_SHIELDED;
141 pCurDesc->radius = EARTH_RADIUS;
142 pCurDesc->NumPlanets = 2;
143 break;
144 case 3: /* MARS */
145 pCurDesc->data_index = DUST_WORLD;
146 pCurDesc->radius = EARTH_RADIUS * 152L / 100;
147 pCurDesc->NumPlanets = 0;
148 break;
149 case 4: /* JUPITER */
150 pCurDesc->data_index = RED_GAS_GIANT;
151 pCurDesc->radius = EARTH_RADIUS * 500L /* 520L */ / 100;
152 pCurDesc->NumPlanets = 4;
153 break;
154 case 5: /* SATURN */
155 pCurDesc->data_index = ORA_GAS_GIANT;
156 pCurDesc->radius = EARTH_RADIUS * 750L /* 952L */ / 100;
157 pCurDesc->NumPlanets = 1;
158 break;
159 case 6: /* URANUS */
160 pCurDesc->data_index = GRN_GAS_GIANT;
161 pCurDesc->radius = EARTH_RADIUS * 1000L /* 1916L */ / 100;
162 pCurDesc->NumPlanets = 0;
163 break;
164 case 7: /* NEPTUNE */
165 pCurDesc->data_index = BLU_GAS_GIANT;
166 pCurDesc->radius = EARTH_RADIUS * 1250L /* 2999L */ / 100;
167 pCurDesc->NumPlanets = 1;
168 break;
169 case 8: /* PLUTO */
170 pCurDesc->data_index = PELLUCID_WORLD;
171 pCurDesc->radius = EARTH_RADIUS * 1550L /* 3937L */ / 100;
172 pCurDesc->NumPlanets = 0;
173 angle = FULL_CIRCLE - OCTANT;
174 break;
175 }
176
177 pCurDesc->location.x = COSINE (angle, pCurDesc->radius);
178 pCurDesc->location.y = SINE (angle, pCurDesc->radius);
179 }
180
181 return true;
182 }
183
184 static bool
GenerateSol_generateMoons(SOLARSYS_STATE * solarSys,PLANET_DESC * planet)185 GenerateSol_generateMoons (SOLARSYS_STATE *solarSys, PLANET_DESC *planet)
186 {
187 COUNT planetNr;
188 DWORD rand_val;
189
190 GenerateDefault_generateMoons (solarSys, planet);
191
192 planetNr = planetIndex (solarSys, planet);
193 switch (planetNr)
194 {
195 case 2: /* moons of EARTH */
196 {
197 COUNT angle;
198
199 /* Starbase: */
200 solarSys->MoonDesc[0].data_index = HIERARCHY_STARBASE;
201 solarSys->MoonDesc[0].radius = MIN_MOON_RADIUS;
202 angle = HALF_CIRCLE + QUADRANT;
203 solarSys->MoonDesc[0].location.x =
204 COSINE (angle, solarSys->MoonDesc[0].radius);
205 solarSys->MoonDesc[0].location.y =
206 SINE (angle, solarSys->MoonDesc[0].radius);
207
208 /* Luna: */
209 solarSys->MoonDesc[1].data_index = SELENIC_WORLD;
210 solarSys->MoonDesc[1].radius = MIN_MOON_RADIUS
211 + (MAX_MOONS - 1) * MOON_DELTA;
212 rand_val = RandomContext_Random (SysGenRNG);
213 angle = NORMALIZE_ANGLE (LOWORD (rand_val));
214 solarSys->MoonDesc[1].location.x =
215 COSINE (angle, solarSys->MoonDesc[1].radius);
216 solarSys->MoonDesc[1].location.y =
217 SINE (angle, solarSys->MoonDesc[1].radius);
218 break;
219 }
220 case 4: /* moons of JUPITER */
221 solarSys->MoonDesc[0].data_index = RADIOACTIVE_WORLD;
222 /* Io */
223 solarSys->MoonDesc[1].data_index = HALIDE_WORLD;
224 /* Europa */
225 solarSys->MoonDesc[2].data_index = CYANIC_WORLD;
226 /* Ganymede */
227 solarSys->MoonDesc[3].data_index = PELLUCID_WORLD;
228 /* Callisto */
229 break;
230 case 5: /* moons of SATURN */
231 solarSys->MoonDesc[0].data_index = ALKALI_WORLD;
232 /* Titan */
233 break;
234 case 7: /* moons of NEPTUNE */
235 solarSys->MoonDesc[0].data_index = VINYLOGOUS_WORLD;
236 /* Triton */
237 break;
238 }
239
240 return true;
241 }
242
243 static bool
GenerateSol_generateName(const SOLARSYS_STATE * solarSys,const PLANET_DESC * world)244 GenerateSol_generateName (const SOLARSYS_STATE *solarSys,
245 const PLANET_DESC *world)
246 {
247 COUNT planetNr = planetIndex (solarSys, world);
248 utf8StringCopy (GLOBAL_SIS (PlanetName), sizeof (GLOBAL_SIS (PlanetName)),
249 GAME_STRING (PLANET_NUMBER_BASE + planetNr));
250 SET_GAME_STATE (BATTLE_PLANET, solarSys->PlanetDesc[planetNr].data_index);
251
252 return true;
253 }
254
255 static bool
GenerateSol_generateOrbital(SOLARSYS_STATE * solarSys,PLANET_DESC * world)256 GenerateSol_generateOrbital (SOLARSYS_STATE *solarSys, PLANET_DESC *world)
257 {
258 DWORD rand_val;
259 COUNT planetNr;
260
261 if (matchWorld (solarSys, world, 2, 0))
262 {
263 /* Starbase */
264 PutGroupInfo (GROUPS_RANDOM, GROUP_SAVE_IP);
265 ReinitQueue (&GLOBAL (ip_group_q));
266 assert (CountLinks (&GLOBAL (npc_built_ship_q)) == 0);
267
268 EncounterGroup = 0;
269 GLOBAL (CurrentActivity) |= START_ENCOUNTER;
270 SET_GAME_STATE (GLOBAL_FLAGS_AND_DATA, (BYTE)~0);
271 return true;
272 }
273
274 DoPlanetaryAnalysis (&solarSys->SysInfo, world);
275 rand_val = RandomContext_GetSeed (SysGenRNG);
276
277 solarSys->SysInfo.PlanetInfo.ScanSeed[MINERAL_SCAN] = rand_val;
278 GenerateMineralDeposits (&solarSys->SysInfo, GENERATE_ALL, NULL);
279 rand_val = RandomContext_GetSeed (SysGenRNG);
280
281 planetNr = planetIndex (solarSys, world);
282 if (worldIsPlanet (solarSys, world))
283 {
284 switch (planetNr)
285 {
286 case 0: /* MERCURY */
287 solarSys->SysInfo.PlanetInfo.AtmoDensity = 0;
288 solarSys->SysInfo.PlanetInfo.PlanetDensity = 98;
289 solarSys->SysInfo.PlanetInfo.PlanetRadius = 38;
290 solarSys->SysInfo.PlanetInfo.AxialTilt = 3;
291 solarSys->SysInfo.PlanetInfo.Weather = 0;
292 solarSys->SysInfo.PlanetInfo.Tectonics = 2;
293 solarSys->SysInfo.PlanetInfo.RotationPeriod = 59 * 240;
294 solarSys->SysInfo.PlanetInfo.SurfaceTemperature = 165;
295 break;
296 case 1: /* VENUS */
297 solarSys->SysInfo.PlanetInfo.AtmoDensity = 90 *
298 EARTH_ATMOSPHERE;
299 solarSys->SysInfo.PlanetInfo.PlanetDensity = 95;
300 solarSys->SysInfo.PlanetInfo.PlanetRadius = 95;
301 solarSys->SysInfo.PlanetInfo.AxialTilt = 177;
302 solarSys->SysInfo.PlanetInfo.Weather = 7;
303 solarSys->SysInfo.PlanetInfo.Tectonics = 1;
304 solarSys->SysInfo.PlanetInfo.RotationPeriod = 243 * 240;
305 solarSys->SysInfo.PlanetInfo.SurfaceTemperature = 457;
306 break;
307 case 2: /* EARTH */
308 solarSys->SysInfo.PlanetInfo.AtmoDensity =
309 EARTH_ATMOSPHERE;
310 solarSys->SysInfo.PlanetInfo.PlanetDensity = 100;
311 solarSys->SysInfo.PlanetInfo.PlanetRadius = 100;
312 solarSys->SysInfo.PlanetInfo.AxialTilt = 23;
313 solarSys->SysInfo.PlanetInfo.Weather = 1;
314 solarSys->SysInfo.PlanetInfo.Tectonics = 1;
315 solarSys->SysInfo.PlanetInfo.RotationPeriod = 240;
316 solarSys->SysInfo.PlanetInfo.SurfaceTemperature = 22;
317 break;
318 case 3: /* MARS */
319 // XXX: Mars atmo should actually be 1/2 in current units
320 solarSys->SysInfo.PlanetInfo.AtmoDensity = 1;
321 solarSys->SysInfo.PlanetInfo.PlanetDensity = 72;
322 solarSys->SysInfo.PlanetInfo.PlanetRadius = 53;
323 solarSys->SysInfo.PlanetInfo.AxialTilt = 24;
324 solarSys->SysInfo.PlanetInfo.Weather = 1;
325 solarSys->SysInfo.PlanetInfo.Tectonics = 1;
326 solarSys->SysInfo.PlanetInfo.RotationPeriod = 246;
327 solarSys->SysInfo.PlanetInfo.SurfaceTemperature = -53;
328 break;
329 case 4: /* JUPITER */
330 solarSys->SysInfo.PlanetInfo.AtmoDensity =
331 GAS_GIANT_ATMOSPHERE;
332 solarSys->SysInfo.PlanetInfo.PlanetDensity = 24;
333 solarSys->SysInfo.PlanetInfo.PlanetRadius = 1120;
334 solarSys->SysInfo.PlanetInfo.AxialTilt = 3;
335 solarSys->SysInfo.PlanetInfo.Weather = 7;
336 solarSys->SysInfo.PlanetInfo.Tectonics = 0;
337 solarSys->SysInfo.PlanetInfo.RotationPeriod = 98;
338 solarSys->SysInfo.PlanetInfo.SurfaceTemperature = -143;
339 solarSys->SysInfo.PlanetInfo.PlanetToSunDist =
340 EARTH_RADIUS * 520L / 100;
341 break;
342 case 5: /* SATURN */
343 solarSys->SysInfo.PlanetInfo.AtmoDensity =
344 GAS_GIANT_ATMOSPHERE;
345 solarSys->SysInfo.PlanetInfo.PlanetDensity = 13;
346 solarSys->SysInfo.PlanetInfo.PlanetRadius = 945;
347 solarSys->SysInfo.PlanetInfo.AxialTilt = 27;
348 solarSys->SysInfo.PlanetInfo.Weather = 7;
349 solarSys->SysInfo.PlanetInfo.Tectonics = 0;
350 solarSys->SysInfo.PlanetInfo.RotationPeriod = 102;
351 solarSys->SysInfo.PlanetInfo.SurfaceTemperature = -197;
352 solarSys->SysInfo.PlanetInfo.PlanetToSunDist =
353 EARTH_RADIUS * 952L / 100;
354 break;
355 case 6: /* URANUS */
356 solarSys->SysInfo.PlanetInfo.AtmoDensity =
357 GAS_GIANT_ATMOSPHERE;
358 solarSys->SysInfo.PlanetInfo.PlanetDensity = 21;
359 solarSys->SysInfo.PlanetInfo.PlanetRadius = 411;
360 solarSys->SysInfo.PlanetInfo.AxialTilt = 98;
361 solarSys->SysInfo.PlanetInfo.Weather = 7;
362 solarSys->SysInfo.PlanetInfo.Tectonics = 0;
363 solarSys->SysInfo.PlanetInfo.RotationPeriod = 172;
364 solarSys->SysInfo.PlanetInfo.SurfaceTemperature = -217;
365 solarSys->SysInfo.PlanetInfo.PlanetToSunDist =
366 EARTH_RADIUS * 1916L / 100;
367 break;
368 case 7: /* NEPTUNE */
369 solarSys->SysInfo.PlanetInfo.AtmoDensity =
370 GAS_GIANT_ATMOSPHERE;
371 solarSys->SysInfo.PlanetInfo.PlanetDensity = 28;
372 solarSys->SysInfo.PlanetInfo.PlanetRadius = 396;
373 solarSys->SysInfo.PlanetInfo.AxialTilt = 30;
374 solarSys->SysInfo.PlanetInfo.Weather = 7;
375 solarSys->SysInfo.PlanetInfo.Tectonics = 0;
376 solarSys->SysInfo.PlanetInfo.RotationPeriod = 182;
377 solarSys->SysInfo.PlanetInfo.SurfaceTemperature = -229;
378 solarSys->SysInfo.PlanetInfo.PlanetToSunDist =
379 EARTH_RADIUS * 2999L / 100;
380 break;
381 case 8: /* PLUTO */
382 if (!GET_GAME_STATE (FOUND_PLUTO_SPATHI))
383 {
384 LoadStdLanderFont (&solarSys->SysInfo.PlanetInfo);
385 solarSys->PlanetSideFrame[1] =
386 CaptureDrawable (
387 LoadGraphic (SPAPLUTO_MASK_PMAP_ANIM));
388 solarSys->SysInfo.PlanetInfo.DiscoveryString =
389 CaptureStringTable (
390 LoadStringTable (SPAPLUTO_STRTAB));
391 }
392
393 solarSys->SysInfo.PlanetInfo.AtmoDensity = 0;
394 solarSys->SysInfo.PlanetInfo.PlanetDensity = 33;
395 solarSys->SysInfo.PlanetInfo.PlanetRadius = 18;
396 solarSys->SysInfo.PlanetInfo.AxialTilt = 119;
397 solarSys->SysInfo.PlanetInfo.Weather = 0;
398 solarSys->SysInfo.PlanetInfo.Tectonics = 0;
399 solarSys->SysInfo.PlanetInfo.RotationPeriod = 1533;
400 solarSys->SysInfo.PlanetInfo.SurfaceTemperature = -235;
401 solarSys->SysInfo.PlanetInfo.PlanetToSunDist =
402 EARTH_RADIUS * 3937L / 100;
403 break;
404 }
405
406 solarSys->SysInfo.PlanetInfo.SurfaceGravity =
407 CalcGravity (&solarSys->SysInfo.PlanetInfo);
408 LoadPlanet (planetNr == 2 ?
409 CaptureDrawable (LoadGraphic (EARTH_MASK_ANIM)) : NULL);
410 }
411 else
412 {
413 // World is a moon.
414 COUNT moonNr = moonIndex (solarSys, world);
415
416 solarSys->SysInfo.PlanetInfo.AxialTilt = 0;
417 solarSys->SysInfo.PlanetInfo.AtmoDensity = 0;
418 solarSys->SysInfo.PlanetInfo.Weather = 0;
419 switch (planetNr)
420 {
421 case 2: /* moons of EARTH */
422 // NOTE: Even though we save the seed here, it is irrelevant.
423 // The seed will be used to randomly place the tractors, but
424 // since they are mobile, they will be moved to different
425 // locations not governed by this seed.
426 solarSys->SysInfo.PlanetInfo.ScanSeed[BIOLOGICAL_SCAN] =
427 rand_val;
428
429 if (!GET_GAME_STATE (MOONBASE_DESTROYED))
430 {
431 LoadStdLanderFont (&solarSys->SysInfo.PlanetInfo);
432 solarSys->PlanetSideFrame[1] =
433 CaptureDrawable (
434 LoadGraphic (MOONBASE_MASK_PMAP_ANIM));
435 solarSys->SysInfo.PlanetInfo.DiscoveryString =
436 CaptureStringTable (
437 LoadStringTable (MOONBASE_STRTAB));
438 }
439
440 solarSys->SysInfo.PlanetInfo.PlanetDensity = 60;
441 solarSys->SysInfo.PlanetInfo.PlanetRadius = 25;
442 solarSys->SysInfo.PlanetInfo.AxialTilt = 0;
443 solarSys->SysInfo.PlanetInfo.Tectonics = 0;
444 solarSys->SysInfo.PlanetInfo.RotationPeriod = 240 * 29;
445 solarSys->SysInfo.PlanetInfo.SurfaceTemperature = -18;
446 break;
447
448 case 4: /* moons of JUPITER */
449 solarSys->SysInfo.PlanetInfo.PlanetToSunDist =
450 EARTH_RADIUS * 520L / 100;
451 switch (moonNr)
452 {
453 case 0: /* Io */
454 solarSys->SysInfo.PlanetInfo.PlanetDensity = 69;
455 solarSys->SysInfo.PlanetInfo.PlanetRadius = 25;
456 solarSys->SysInfo.PlanetInfo.Tectonics = 3;
457 solarSys->SysInfo.PlanetInfo.RotationPeriod = 390;
458 solarSys->SysInfo.PlanetInfo.SurfaceTemperature = -163;
459 break;
460 case 1: /* Europa */
461 solarSys->SysInfo.PlanetInfo.PlanetDensity = 54;
462 solarSys->SysInfo.PlanetInfo.PlanetRadius = 25;
463 solarSys->SysInfo.PlanetInfo.Tectonics = 1;
464 solarSys->SysInfo.PlanetInfo.RotationPeriod = 840;
465 solarSys->SysInfo.PlanetInfo.SurfaceTemperature = -161;
466 break;
467 case 2: /* Ganymede */
468 solarSys->SysInfo.PlanetInfo.PlanetDensity = 35;
469 solarSys->SysInfo.PlanetInfo.PlanetRadius = 41;
470 solarSys->SysInfo.PlanetInfo.Tectonics = 0;
471 solarSys->SysInfo.PlanetInfo.RotationPeriod = 1728;
472 solarSys->SysInfo.PlanetInfo.SurfaceTemperature = -164;
473 break;
474 case 3: /* Callisto */
475 solarSys->SysInfo.PlanetInfo.PlanetDensity = 35;
476 solarSys->SysInfo.PlanetInfo.PlanetRadius = 38;
477 solarSys->SysInfo.PlanetInfo.Tectonics = 1;
478 solarSys->SysInfo.PlanetInfo.RotationPeriod = 4008;
479 solarSys->SysInfo.PlanetInfo.SurfaceTemperature = -167;
480 break;
481 }
482 break;
483
484 case 5: /* moon of SATURN: Titan */
485 solarSys->SysInfo.PlanetInfo.PlanetToSunDist =
486 EARTH_RADIUS * 952L / 100;
487 solarSys->SysInfo.PlanetInfo.AtmoDensity = 160;
488 solarSys->SysInfo.PlanetInfo.Weather = 2;
489 solarSys->SysInfo.PlanetInfo.PlanetDensity = 34;
490 solarSys->SysInfo.PlanetInfo.PlanetRadius = 40;
491 solarSys->SysInfo.PlanetInfo.Tectonics = 1;
492 solarSys->SysInfo.PlanetInfo.RotationPeriod = 3816;
493 solarSys->SysInfo.PlanetInfo.SurfaceTemperature = -178;
494 break;
495
496 case 7: /* moon of NEPTUNE: Triton */
497 solarSys->SysInfo.PlanetInfo.PlanetToSunDist =
498 EARTH_RADIUS * 2999L / 100;
499 solarSys->SysInfo.PlanetInfo.AtmoDensity = 10;
500 solarSys->SysInfo.PlanetInfo.Weather = 1;
501 solarSys->SysInfo.PlanetInfo.PlanetDensity = 95;
502 solarSys->SysInfo.PlanetInfo.PlanetRadius = 27;
503 solarSys->SysInfo.PlanetInfo.Tectonics = 0;
504 solarSys->SysInfo.PlanetInfo.RotationPeriod = 4300;
505 solarSys->SysInfo.PlanetInfo.SurfaceTemperature = -216;
506 break;
507 }
508
509 solarSys->SysInfo.PlanetInfo.SurfaceGravity =
510 CalcGravity (&solarSys->SysInfo.PlanetInfo);
511 LoadPlanet (NULL);
512 }
513
514 return true;
515 }
516
517 static COUNT
GenerateSol_generateEnergy(const SOLARSYS_STATE * solarSys,const PLANET_DESC * world,COUNT whichNode,NODE_INFO * info)518 GenerateSol_generateEnergy (const SOLARSYS_STATE *solarSys,
519 const PLANET_DESC *world, COUNT whichNode, NODE_INFO *info)
520 {
521 if (matchWorld (solarSys, world, 8, MATCH_PLANET))
522 {
523 /* Pluto */
524 // This check is needed because the retrieval bit is not set for
525 // this node to keep it on the surface while the lander is taking off
526 if (GET_GAME_STATE (FOUND_PLUTO_SPATHI))
527 { // already picked up
528 return 0;
529 }
530
531 if (info)
532 {
533 info->loc_pt.x = 20;
534 info->loc_pt.y = MAP_HEIGHT - 8;
535 }
536
537 return 1; // only matters when count is requested
538 }
539
540 if (matchWorld (solarSys, world, 2, 1))
541 {
542 /* Earth Moon */
543 // This check is redundant since the retrieval bit will keep the
544 // node from showing up again
545 if (GET_GAME_STATE (MOONBASE_DESTROYED))
546 { // already picked up
547 return 0;
548 }
549
550 if (info)
551 {
552 info->loc_pt.x = MAP_WIDTH * 3 / 4;
553 info->loc_pt.y = MAP_HEIGHT * 1 / 4;
554 }
555
556 return 1; // only matters when count is requested
557 }
558
559 (void) whichNode;
560 return 0;
561 }
562
563 static bool
GenerateSol_pickupEnergy(SOLARSYS_STATE * solarSys,PLANET_DESC * world,COUNT whichNode)564 GenerateSol_pickupEnergy (SOLARSYS_STATE *solarSys, PLANET_DESC *world,
565 COUNT whichNode)
566 {
567 if (matchWorld (solarSys, world, 8, MATCH_PLANET))
568 { // Pluto
569 assert (!GET_GAME_STATE (FOUND_PLUTO_SPATHI) && whichNode == 0);
570
571 // Ran into Fwiffo on Pluto
572 #define FWIFFO_FRAGS 8
573 if (!KillLanderCrewSeq (FWIFFO_FRAGS, ONE_SECOND / 20))
574 return false; // lander probably died
575
576 SET_GAME_STATE (FOUND_PLUTO_SPATHI, 1);
577
578 GenerateDefault_landerReport (solarSys);
579 SetLanderTakeoff ();
580
581 // Do not remove the node from the surface while the lander is
582 // taking off. FOUND_PLUTO_SPATHI bit will keep the node from
583 // showing up on subsequent visits.
584 return false;
585 }
586
587 if (matchWorld (solarSys, world, 2, 1))
588 { // Earth Moon
589 assert (!GET_GAME_STATE (MOONBASE_DESTROYED) && whichNode == 0);
590
591 GenerateDefault_landerReport (solarSys);
592 SetLanderTakeoff ();
593
594 SET_GAME_STATE (MOONBASE_DESTROYED, 1);
595 SET_GAME_STATE (MOONBASE_ON_SHIP, 1);
596
597 return true; // picked up
598 }
599
600 (void) whichNode;
601 return false;
602 }
603
604 static COUNT
GenerateSol_generateLife(const SOLARSYS_STATE * solarSys,const PLANET_DESC * world,COUNT whichNode,NODE_INFO * info)605 GenerateSol_generateLife (const SOLARSYS_STATE *solarSys,
606 const PLANET_DESC *world, COUNT whichNode, NODE_INFO *info)
607 {
608 if (matchWorld (solarSys, world, 2, 1))
609 {
610 /* Earth Moon */
611 return GenerateRandomNodes (&solarSys->SysInfo, BIOLOGICAL_SCAN, 10,
612 NUM_CREATURE_TYPES + 1, whichNode, info);
613 }
614
615 return 0;
616 }
617
618
619 static int
init_probe(void)620 init_probe (void)
621 {
622 HIPGROUP hGroup;
623
624 if (!GET_GAME_STATE (PROBE_MESSAGE_DELIVERED)
625 && GetGroupInfo (GLOBAL (BattleGroupRef), GROUP_INIT_IP)
626 && (hGroup = GetHeadLink (&GLOBAL (ip_group_q))))
627 {
628 IP_GROUP *GroupPtr;
629
630 GroupPtr = LockIpGroup (&GLOBAL (ip_group_q), hGroup);
631 GroupPtr->task = IN_ORBIT;
632 GroupPtr->sys_loc = 2 + 1; /* orbitting earth */
633 GroupPtr->dest_loc = 2 + 1; /* orbitting earth */
634 GroupPtr->loc.x = 0;
635 GroupPtr->loc.y = 0;
636 GroupPtr->group_counter = 0;
637 UnlockIpGroup (&GLOBAL (ip_group_q), hGroup);
638
639 return 1;
640 }
641 else
642 return 0;
643 }
644
645 static void
check_probe(void)646 check_probe (void)
647 {
648 HIPGROUP hGroup;
649 IP_GROUP *GroupPtr;
650
651 if (!GLOBAL (BattleGroupRef))
652 return; // nothing to check
653
654 hGroup = GetHeadLink (&GLOBAL (ip_group_q));
655 if (!hGroup)
656 return; // still nothing to check
657
658 GroupPtr = LockIpGroup (&GLOBAL (ip_group_q), hGroup);
659 // REFORM_GROUP was set in ipdisp.c:ip_group_collision()
660 // during a collision with the flagship.
661 if (GroupPtr->race_id == URQUAN_DRONE_SHIP
662 && (GroupPtr->task & REFORM_GROUP))
663 {
664 // We just want the probe to take off as fast as possible,
665 // so clear out REFORM_GROUP
666 GroupPtr->task = FLEE | IGNORE_FLAGSHIP;
667 GroupPtr->dest_loc = 0;
668 }
669 UnlockIpGroup (&GLOBAL (ip_group_q), hGroup);
670 }
671
672