summaryrefslogtreecommitdiff
path: root/src/uqm/planets/generate/gensol.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/uqm/planets/generate/gensol.c')
-rw-r--r--src/uqm/planets/generate/gensol.c671
1 files changed, 671 insertions, 0 deletions
diff --git a/src/uqm/planets/generate/gensol.c b/src/uqm/planets/generate/gensol.c
new file mode 100644
index 0000000..d6041f3
--- /dev/null
+++ b/src/uqm/planets/generate/gensol.c
@@ -0,0 +1,671 @@
+//Copyright Paul Reiche, Fred Ford. 1992-2002
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "genall.h"
+#include "../lander.h"
+#include "../lifeform.h"
+#include "../planets.h"
+#include "../../build.h"
+#include "../../encount.h"
+#include "../../globdata.h"
+#include "../../gamestr.h"
+#include "../../grpinfo.h"
+#include "../../nameref.h"
+#include "../../state.h"
+#include "libs/mathlib.h"
+
+
+static bool GenerateSol_initNpcs (SOLARSYS_STATE *solarSys);
+static bool GenerateSol_reinitNpcs (SOLARSYS_STATE *solarSys);
+static bool GenerateSol_generatePlanets (SOLARSYS_STATE *solarSys);
+static bool GenerateSol_generateMoons (SOLARSYS_STATE *solarSys,
+ PLANET_DESC *planet);
+static bool GenerateSol_generateName (const SOLARSYS_STATE *,
+ const PLANET_DESC *world);
+static bool GenerateSol_generateOrbital (SOLARSYS_STATE *solarSys,
+ PLANET_DESC *world);
+static COUNT GenerateSol_generateEnergy (const SOLARSYS_STATE *,
+ const PLANET_DESC *world, COUNT whichNode, NODE_INFO *);
+static COUNT GenerateSol_generateLife (const SOLARSYS_STATE *,
+ const PLANET_DESC *world, COUNT whichNode, NODE_INFO *);
+static bool GenerateSol_pickupEnergy (SOLARSYS_STATE *solarSys,
+ PLANET_DESC *world, COUNT whichNode);
+
+static int init_probe (void);
+static void check_probe (void);
+
+
+const GenerateFunctions generateSolFunctions = {
+ /* .initNpcs = */ GenerateSol_initNpcs,
+ /* .reinitNpcs = */ GenerateSol_reinitNpcs,
+ /* .uninitNpcs = */ GenerateDefault_uninitNpcs,
+ /* .generatePlanets = */ GenerateSol_generatePlanets,
+ /* .generateMoons = */ GenerateSol_generateMoons,
+ /* .generateName = */ GenerateSol_generateName,
+ /* .generateOrbital = */ GenerateSol_generateOrbital,
+ /* .generateMinerals = */ GenerateDefault_generateMinerals,
+ /* .generateEnergy = */ GenerateSol_generateEnergy,
+ /* .generateLife = */ GenerateSol_generateLife,
+ /* .pickupMinerals = */ GenerateDefault_pickupMinerals,
+ /* .pickupEnergy = */ GenerateSol_pickupEnergy,
+ /* .pickupLife = */ GenerateDefault_pickupLife,
+};
+
+
+static bool
+GenerateSol_initNpcs (SOLARSYS_STATE *solarSys)
+{
+ GLOBAL (BattleGroupRef) = GET_GAME_STATE_32 (URQUAN_PROBE_GRPOFFS0);
+ if (GLOBAL (BattleGroupRef) == 0)
+ {
+ CloneShipFragment (URQUAN_DRONE_SHIP, &GLOBAL (npc_built_ship_q), 0);
+ GLOBAL (BattleGroupRef) = PutGroupInfo (GROUPS_ADD_NEW, 1);
+ ReinitQueue (&GLOBAL (npc_built_ship_q));
+ SET_GAME_STATE_32 (URQUAN_PROBE_GRPOFFS0, GLOBAL (BattleGroupRef));
+ }
+
+ if (!init_probe ())
+ GenerateDefault_initNpcs (solarSys);
+
+ return true;
+}
+
+static bool
+GenerateSol_reinitNpcs (SOLARSYS_STATE *solarSys)
+{
+ if (GET_GAME_STATE (CHMMR_BOMB_STATE) != 3)
+ {
+ GenerateDefault_reinitNpcs (solarSys);
+ check_probe ();
+ }
+ else
+ {
+ GLOBAL (BattleGroupRef) = 0;
+ ReinitQueue (&GLOBAL (ip_group_q));
+ assert (CountLinks (&GLOBAL (npc_built_ship_q)) == 0);
+ }
+ return true;
+}
+
+static bool
+GenerateSol_generatePlanets (SOLARSYS_STATE *solarSys)
+{
+ COUNT planetI;
+
+#define SOL_SEED 334241042L
+ RandomContext_SeedRandom (SysGenRNG, SOL_SEED);
+
+ solarSys->SunDesc[0].NumPlanets = 9;
+ for (planetI = 0; planetI < 9; ++planetI)
+ {
+ COUNT angle;
+ DWORD rand_val;
+ UWORD word_val;
+ PLANET_DESC *pCurDesc = &solarSys->PlanetDesc[planetI];
+
+ pCurDesc->rand_seed = RandomContext_Random (SysGenRNG);
+ rand_val = pCurDesc->rand_seed;
+ word_val = LOWORD (rand_val);
+ angle = NORMALIZE_ANGLE ((COUNT)HIBYTE (word_val));
+
+ switch (planetI)
+ {
+ case 0: /* MERCURY */
+ pCurDesc->data_index = METAL_WORLD;
+ pCurDesc->radius = EARTH_RADIUS * 39L / 100;
+ pCurDesc->NumPlanets = 0;
+ break;
+ case 1: /* VENUS */
+ pCurDesc->data_index = PRIMORDIAL_WORLD;
+ pCurDesc->radius = EARTH_RADIUS * 72L / 100;
+ pCurDesc->NumPlanets = 0;
+ angle = NORMALIZE_ANGLE (FULL_CIRCLE - angle);
+ break;
+ case 2: /* EARTH */
+ pCurDesc->data_index = WATER_WORLD | PLANET_SHIELDED;
+ pCurDesc->radius = EARTH_RADIUS;
+ pCurDesc->NumPlanets = 2;
+ break;
+ case 3: /* MARS */
+ pCurDesc->data_index = DUST_WORLD;
+ pCurDesc->radius = EARTH_RADIUS * 152L / 100;
+ pCurDesc->NumPlanets = 0;
+ break;
+ case 4: /* JUPITER */
+ pCurDesc->data_index = RED_GAS_GIANT;
+ pCurDesc->radius = EARTH_RADIUS * 500L /* 520L */ / 100;
+ pCurDesc->NumPlanets = 4;
+ break;
+ case 5: /* SATURN */
+ pCurDesc->data_index = ORA_GAS_GIANT;
+ pCurDesc->radius = EARTH_RADIUS * 750L /* 952L */ / 100;
+ pCurDesc->NumPlanets = 1;
+ break;
+ case 6: /* URANUS */
+ pCurDesc->data_index = GRN_GAS_GIANT;
+ pCurDesc->radius = EARTH_RADIUS * 1000L /* 1916L */ / 100;
+ pCurDesc->NumPlanets = 0;
+ break;
+ case 7: /* NEPTUNE */
+ pCurDesc->data_index = BLU_GAS_GIANT;
+ pCurDesc->radius = EARTH_RADIUS * 1250L /* 2999L */ / 100;
+ pCurDesc->NumPlanets = 1;
+ break;
+ case 8: /* PLUTO */
+ pCurDesc->data_index = PELLUCID_WORLD;
+ pCurDesc->radius = EARTH_RADIUS * 1550L /* 3937L */ / 100;
+ pCurDesc->NumPlanets = 0;
+ angle = FULL_CIRCLE - OCTANT;
+ break;
+ }
+
+ pCurDesc->location.x = COSINE (angle, pCurDesc->radius);
+ pCurDesc->location.y = SINE (angle, pCurDesc->radius);
+ }
+
+ return true;
+}
+
+static bool
+GenerateSol_generateMoons (SOLARSYS_STATE *solarSys, PLANET_DESC *planet)
+{
+ COUNT planetNr;
+ DWORD rand_val;
+
+ GenerateDefault_generateMoons (solarSys, planet);
+
+ planetNr = planetIndex (solarSys, planet);
+ switch (planetNr)
+ {
+ case 2: /* moons of EARTH */
+ {
+ COUNT angle;
+
+ /* Starbase: */
+ solarSys->MoonDesc[0].data_index = HIERARCHY_STARBASE;
+ solarSys->MoonDesc[0].radius = MIN_MOON_RADIUS;
+ angle = HALF_CIRCLE + QUADRANT;
+ solarSys->MoonDesc[0].location.x =
+ COSINE (angle, solarSys->MoonDesc[0].radius);
+ solarSys->MoonDesc[0].location.y =
+ SINE (angle, solarSys->MoonDesc[0].radius);
+
+ /* Luna: */
+ solarSys->MoonDesc[1].data_index = SELENIC_WORLD;
+ solarSys->MoonDesc[1].radius = MIN_MOON_RADIUS
+ + (MAX_MOONS - 1) * MOON_DELTA;
+ rand_val = RandomContext_Random (SysGenRNG);
+ angle = NORMALIZE_ANGLE (LOWORD (rand_val));
+ solarSys->MoonDesc[1].location.x =
+ COSINE (angle, solarSys->MoonDesc[1].radius);
+ solarSys->MoonDesc[1].location.y =
+ SINE (angle, solarSys->MoonDesc[1].radius);
+ break;
+ }
+ case 4: /* moons of JUPITER */
+ solarSys->MoonDesc[0].data_index = RADIOACTIVE_WORLD;
+ /* Io */
+ solarSys->MoonDesc[1].data_index = HALIDE_WORLD;
+ /* Europa */
+ solarSys->MoonDesc[2].data_index = CYANIC_WORLD;
+ /* Ganymede */
+ solarSys->MoonDesc[3].data_index = PELLUCID_WORLD;
+ /* Callisto */
+ break;
+ case 5: /* moons of SATURN */
+ solarSys->MoonDesc[0].data_index = ALKALI_WORLD;
+ /* Titan */
+ break;
+ case 7: /* moons of NEPTUNE */
+ solarSys->MoonDesc[0].data_index = VINYLOGOUS_WORLD;
+ /* Triton */
+ break;
+ }
+
+ return true;
+}
+
+static bool
+GenerateSol_generateName (const SOLARSYS_STATE *solarSys,
+ const PLANET_DESC *world)
+{
+ COUNT planetNr = planetIndex (solarSys, world);
+ utf8StringCopy (GLOBAL_SIS (PlanetName), sizeof (GLOBAL_SIS (PlanetName)),
+ GAME_STRING (PLANET_NUMBER_BASE + planetNr));
+ SET_GAME_STATE (BATTLE_PLANET, solarSys->PlanetDesc[planetNr].data_index);
+
+ return true;
+}
+
+static bool
+GenerateSol_generateOrbital (SOLARSYS_STATE *solarSys, PLANET_DESC *world)
+{
+ DWORD rand_val;
+ COUNT planetNr;
+
+ if (matchWorld (solarSys, world, 2, 0))
+ {
+ /* Starbase */
+ PutGroupInfo (GROUPS_RANDOM, GROUP_SAVE_IP);
+ ReinitQueue (&GLOBAL (ip_group_q));
+ assert (CountLinks (&GLOBAL (npc_built_ship_q)) == 0);
+
+ EncounterGroup = 0;
+ GLOBAL (CurrentActivity) |= START_ENCOUNTER;
+ SET_GAME_STATE (GLOBAL_FLAGS_AND_DATA, (BYTE)~0);
+ return true;
+ }
+
+ DoPlanetaryAnalysis (&solarSys->SysInfo, world);
+ rand_val = RandomContext_GetSeed (SysGenRNG);
+
+ solarSys->SysInfo.PlanetInfo.ScanSeed[MINERAL_SCAN] = rand_val;
+ GenerateMineralDeposits (&solarSys->SysInfo, GENERATE_ALL, NULL);
+ rand_val = RandomContext_GetSeed (SysGenRNG);
+
+ planetNr = planetIndex (solarSys, world);
+ if (worldIsPlanet (solarSys, world))
+ {
+ switch (planetNr)
+ {
+ case 0: /* MERCURY */
+ solarSys->SysInfo.PlanetInfo.AtmoDensity = 0;
+ solarSys->SysInfo.PlanetInfo.PlanetDensity = 98;
+ solarSys->SysInfo.PlanetInfo.PlanetRadius = 38;
+ solarSys->SysInfo.PlanetInfo.AxialTilt = 3;
+ solarSys->SysInfo.PlanetInfo.Weather = 0;
+ solarSys->SysInfo.PlanetInfo.Tectonics = 2;
+ solarSys->SysInfo.PlanetInfo.RotationPeriod = 59 * 240;
+ solarSys->SysInfo.PlanetInfo.SurfaceTemperature = 165;
+ break;
+ case 1: /* VENUS */
+ solarSys->SysInfo.PlanetInfo.AtmoDensity = 90 *
+ EARTH_ATMOSPHERE;
+ solarSys->SysInfo.PlanetInfo.PlanetDensity = 95;
+ solarSys->SysInfo.PlanetInfo.PlanetRadius = 95;
+ solarSys->SysInfo.PlanetInfo.AxialTilt = 177;
+ solarSys->SysInfo.PlanetInfo.Weather = 7;
+ solarSys->SysInfo.PlanetInfo.Tectonics = 1;
+ solarSys->SysInfo.PlanetInfo.RotationPeriod = 243 * 240;
+ solarSys->SysInfo.PlanetInfo.SurfaceTemperature = 457;
+ break;
+ case 2: /* EARTH */
+ solarSys->SysInfo.PlanetInfo.AtmoDensity =
+ EARTH_ATMOSPHERE;
+ solarSys->SysInfo.PlanetInfo.PlanetDensity = 100;
+ solarSys->SysInfo.PlanetInfo.PlanetRadius = 100;
+ solarSys->SysInfo.PlanetInfo.AxialTilt = 23;
+ solarSys->SysInfo.PlanetInfo.Weather = 1;
+ solarSys->SysInfo.PlanetInfo.Tectonics = 1;
+ solarSys->SysInfo.PlanetInfo.RotationPeriod = 240;
+ solarSys->SysInfo.PlanetInfo.SurfaceTemperature = 22;
+ break;
+ case 3: /* MARS */
+ // XXX: Mars atmo should actually be 1/2 in current units
+ solarSys->SysInfo.PlanetInfo.AtmoDensity = 1;
+ solarSys->SysInfo.PlanetInfo.PlanetDensity = 72;
+ solarSys->SysInfo.PlanetInfo.PlanetRadius = 53;
+ solarSys->SysInfo.PlanetInfo.AxialTilt = 24;
+ solarSys->SysInfo.PlanetInfo.Weather = 1;
+ solarSys->SysInfo.PlanetInfo.Tectonics = 1;
+ solarSys->SysInfo.PlanetInfo.RotationPeriod = 246;
+ solarSys->SysInfo.PlanetInfo.SurfaceTemperature = -53;
+ break;
+ case 4: /* JUPITER */
+ solarSys->SysInfo.PlanetInfo.AtmoDensity =
+ GAS_GIANT_ATMOSPHERE;
+ solarSys->SysInfo.PlanetInfo.PlanetDensity = 24;
+ solarSys->SysInfo.PlanetInfo.PlanetRadius = 1120;
+ solarSys->SysInfo.PlanetInfo.AxialTilt = 3;
+ solarSys->SysInfo.PlanetInfo.Weather = 7;
+ solarSys->SysInfo.PlanetInfo.Tectonics = 0;
+ solarSys->SysInfo.PlanetInfo.RotationPeriod = 98;
+ solarSys->SysInfo.PlanetInfo.SurfaceTemperature = -143;
+ solarSys->SysInfo.PlanetInfo.PlanetToSunDist =
+ EARTH_RADIUS * 520L / 100;
+ break;
+ case 5: /* SATURN */
+ solarSys->SysInfo.PlanetInfo.AtmoDensity =
+ GAS_GIANT_ATMOSPHERE;
+ solarSys->SysInfo.PlanetInfo.PlanetDensity = 13;
+ solarSys->SysInfo.PlanetInfo.PlanetRadius = 945;
+ solarSys->SysInfo.PlanetInfo.AxialTilt = 27;
+ solarSys->SysInfo.PlanetInfo.Weather = 7;
+ solarSys->SysInfo.PlanetInfo.Tectonics = 0;
+ solarSys->SysInfo.PlanetInfo.RotationPeriod = 102;
+ solarSys->SysInfo.PlanetInfo.SurfaceTemperature = -197;
+ solarSys->SysInfo.PlanetInfo.PlanetToSunDist =
+ EARTH_RADIUS * 952L / 100;
+ break;
+ case 6: /* URANUS */
+ solarSys->SysInfo.PlanetInfo.AtmoDensity =
+ GAS_GIANT_ATMOSPHERE;
+ solarSys->SysInfo.PlanetInfo.PlanetDensity = 21;
+ solarSys->SysInfo.PlanetInfo.PlanetRadius = 411;
+ solarSys->SysInfo.PlanetInfo.AxialTilt = 98;
+ solarSys->SysInfo.PlanetInfo.Weather = 7;
+ solarSys->SysInfo.PlanetInfo.Tectonics = 0;
+ solarSys->SysInfo.PlanetInfo.RotationPeriod = 172;
+ solarSys->SysInfo.PlanetInfo.SurfaceTemperature = -217;
+ solarSys->SysInfo.PlanetInfo.PlanetToSunDist =
+ EARTH_RADIUS * 1916L / 100;
+ break;
+ case 7: /* NEPTUNE */
+ solarSys->SysInfo.PlanetInfo.AtmoDensity =
+ GAS_GIANT_ATMOSPHERE;
+ solarSys->SysInfo.PlanetInfo.PlanetDensity = 28;
+ solarSys->SysInfo.PlanetInfo.PlanetRadius = 396;
+ solarSys->SysInfo.PlanetInfo.AxialTilt = 30;
+ solarSys->SysInfo.PlanetInfo.Weather = 7;
+ solarSys->SysInfo.PlanetInfo.Tectonics = 0;
+ solarSys->SysInfo.PlanetInfo.RotationPeriod = 182;
+ solarSys->SysInfo.PlanetInfo.SurfaceTemperature = -229;
+ solarSys->SysInfo.PlanetInfo.PlanetToSunDist =
+ EARTH_RADIUS * 2999L / 100;
+ break;
+ case 8: /* PLUTO */
+ if (!GET_GAME_STATE (FOUND_PLUTO_SPATHI))
+ {
+ LoadStdLanderFont (&solarSys->SysInfo.PlanetInfo);
+ solarSys->PlanetSideFrame[1] =
+ CaptureDrawable (
+ LoadGraphic (SPAPLUTO_MASK_PMAP_ANIM));
+ solarSys->SysInfo.PlanetInfo.DiscoveryString =
+ CaptureStringTable (
+ LoadStringTable (SPAPLUTO_STRTAB));
+ }
+
+ solarSys->SysInfo.PlanetInfo.AtmoDensity = 0;
+ solarSys->SysInfo.PlanetInfo.PlanetDensity = 33;
+ solarSys->SysInfo.PlanetInfo.PlanetRadius = 18;
+ solarSys->SysInfo.PlanetInfo.AxialTilt = 119;
+ solarSys->SysInfo.PlanetInfo.Weather = 0;
+ solarSys->SysInfo.PlanetInfo.Tectonics = 0;
+ solarSys->SysInfo.PlanetInfo.RotationPeriod = 1533;
+ solarSys->SysInfo.PlanetInfo.SurfaceTemperature = -235;
+ solarSys->SysInfo.PlanetInfo.PlanetToSunDist =
+ EARTH_RADIUS * 3937L / 100;
+ break;
+ }
+
+ solarSys->SysInfo.PlanetInfo.SurfaceGravity =
+ CalcGravity (&solarSys->SysInfo.PlanetInfo);
+ LoadPlanet (planetNr == 2 ?
+ CaptureDrawable (LoadGraphic (EARTH_MASK_ANIM)) : NULL);
+ }
+ else
+ {
+ // World is a moon.
+ COUNT moonNr = moonIndex (solarSys, world);
+
+ solarSys->SysInfo.PlanetInfo.AxialTilt = 0;
+ solarSys->SysInfo.PlanetInfo.AtmoDensity = 0;
+ solarSys->SysInfo.PlanetInfo.Weather = 0;
+ switch (planetNr)
+ {
+ case 2: /* moons of EARTH */
+ // NOTE: Even though we save the seed here, it is irrelevant.
+ // The seed will be used to randomly place the tractors, but
+ // since they are mobile, they will be moved to different
+ // locations not governed by this seed.
+ solarSys->SysInfo.PlanetInfo.ScanSeed[BIOLOGICAL_SCAN] =
+ rand_val;
+
+ if (!GET_GAME_STATE (MOONBASE_DESTROYED))
+ {
+ LoadStdLanderFont (&solarSys->SysInfo.PlanetInfo);
+ solarSys->PlanetSideFrame[1] =
+ CaptureDrawable (
+ LoadGraphic (MOONBASE_MASK_PMAP_ANIM));
+ solarSys->SysInfo.PlanetInfo.DiscoveryString =
+ CaptureStringTable (
+ LoadStringTable (MOONBASE_STRTAB));
+ }
+
+ solarSys->SysInfo.PlanetInfo.PlanetDensity = 60;
+ solarSys->SysInfo.PlanetInfo.PlanetRadius = 25;
+ solarSys->SysInfo.PlanetInfo.AxialTilt = 0;
+ solarSys->SysInfo.PlanetInfo.Tectonics = 0;
+ solarSys->SysInfo.PlanetInfo.RotationPeriod = 240 * 29;
+ solarSys->SysInfo.PlanetInfo.SurfaceTemperature = -18;
+ break;
+
+ case 4: /* moons of JUPITER */
+ solarSys->SysInfo.PlanetInfo.PlanetToSunDist =
+ EARTH_RADIUS * 520L / 100;
+ switch (moonNr)
+ {
+ case 0: /* Io */
+ solarSys->SysInfo.PlanetInfo.PlanetDensity = 69;
+ solarSys->SysInfo.PlanetInfo.PlanetRadius = 25;
+ solarSys->SysInfo.PlanetInfo.Tectonics = 3;
+ solarSys->SysInfo.PlanetInfo.RotationPeriod = 390;
+ solarSys->SysInfo.PlanetInfo.SurfaceTemperature = -163;
+ break;
+ case 1: /* Europa */
+ solarSys->SysInfo.PlanetInfo.PlanetDensity = 54;
+ solarSys->SysInfo.PlanetInfo.PlanetRadius = 25;
+ solarSys->SysInfo.PlanetInfo.Tectonics = 1;
+ solarSys->SysInfo.PlanetInfo.RotationPeriod = 840;
+ solarSys->SysInfo.PlanetInfo.SurfaceTemperature = -161;
+ break;
+ case 2: /* Ganymede */
+ solarSys->SysInfo.PlanetInfo.PlanetDensity = 35;
+ solarSys->SysInfo.PlanetInfo.PlanetRadius = 41;
+ solarSys->SysInfo.PlanetInfo.Tectonics = 0;
+ solarSys->SysInfo.PlanetInfo.RotationPeriod = 1728;
+ solarSys->SysInfo.PlanetInfo.SurfaceTemperature = -164;
+ break;
+ case 3: /* Callisto */
+ solarSys->SysInfo.PlanetInfo.PlanetDensity = 35;
+ solarSys->SysInfo.PlanetInfo.PlanetRadius = 38;
+ solarSys->SysInfo.PlanetInfo.Tectonics = 1;
+ solarSys->SysInfo.PlanetInfo.RotationPeriod = 4008;
+ solarSys->SysInfo.PlanetInfo.SurfaceTemperature = -167;
+ break;
+ }
+ break;
+
+ case 5: /* moon of SATURN: Titan */
+ solarSys->SysInfo.PlanetInfo.PlanetToSunDist =
+ EARTH_RADIUS * 952L / 100;
+ solarSys->SysInfo.PlanetInfo.AtmoDensity = 160;
+ solarSys->SysInfo.PlanetInfo.Weather = 2;
+ solarSys->SysInfo.PlanetInfo.PlanetDensity = 34;
+ solarSys->SysInfo.PlanetInfo.PlanetRadius = 40;
+ solarSys->SysInfo.PlanetInfo.Tectonics = 1;
+ solarSys->SysInfo.PlanetInfo.RotationPeriod = 3816;
+ solarSys->SysInfo.PlanetInfo.SurfaceTemperature = -178;
+ break;
+
+ case 7: /* moon of NEPTUNE: Triton */
+ solarSys->SysInfo.PlanetInfo.PlanetToSunDist =
+ EARTH_RADIUS * 2999L / 100;
+ solarSys->SysInfo.PlanetInfo.AtmoDensity = 10;
+ solarSys->SysInfo.PlanetInfo.Weather = 1;
+ solarSys->SysInfo.PlanetInfo.PlanetDensity = 95;
+ solarSys->SysInfo.PlanetInfo.PlanetRadius = 27;
+ solarSys->SysInfo.PlanetInfo.Tectonics = 0;
+ solarSys->SysInfo.PlanetInfo.RotationPeriod = 4300;
+ solarSys->SysInfo.PlanetInfo.SurfaceTemperature = -216;
+ break;
+ }
+
+ solarSys->SysInfo.PlanetInfo.SurfaceGravity =
+ CalcGravity (&solarSys->SysInfo.PlanetInfo);
+ LoadPlanet (NULL);
+ }
+
+ return true;
+}
+
+static COUNT
+GenerateSol_generateEnergy (const SOLARSYS_STATE *solarSys,
+ const PLANET_DESC *world, COUNT whichNode, NODE_INFO *info)
+{
+ if (matchWorld (solarSys, world, 8, MATCH_PLANET))
+ {
+ /* Pluto */
+ // This check is needed because the retrieval bit is not set for
+ // this node to keep it on the surface while the lander is taking off
+ if (GET_GAME_STATE (FOUND_PLUTO_SPATHI))
+ { // already picked up
+ return 0;
+ }
+
+ if (info)
+ {
+ info->loc_pt.x = 20;
+ info->loc_pt.y = MAP_HEIGHT - 8;
+ }
+
+ return 1; // only matters when count is requested
+ }
+
+ if (matchWorld (solarSys, world, 2, 1))
+ {
+ /* Earth Moon */
+ // This check is redundant since the retrieval bit will keep the
+ // node from showing up again
+ if (GET_GAME_STATE (MOONBASE_DESTROYED))
+ { // already picked up
+ return 0;
+ }
+
+ if (info)
+ {
+ info->loc_pt.x = MAP_WIDTH * 3 / 4;
+ info->loc_pt.y = MAP_HEIGHT * 1 / 4;
+ }
+
+ return 1; // only matters when count is requested
+ }
+
+ (void) whichNode;
+ return 0;
+}
+
+static bool
+GenerateSol_pickupEnergy (SOLARSYS_STATE *solarSys, PLANET_DESC *world,
+ COUNT whichNode)
+{
+ if (matchWorld (solarSys, world, 8, MATCH_PLANET))
+ { // Pluto
+ assert (!GET_GAME_STATE (FOUND_PLUTO_SPATHI) && whichNode == 0);
+
+ // Ran into Fwiffo on Pluto
+ #define FWIFFO_FRAGS 8
+ if (!KillLanderCrewSeq (FWIFFO_FRAGS, ONE_SECOND / 20))
+ return false; // lander probably died
+
+ SET_GAME_STATE (FOUND_PLUTO_SPATHI, 1);
+
+ GenerateDefault_landerReport (solarSys);
+ SetLanderTakeoff ();
+
+ // Do not remove the node from the surface while the lander is
+ // taking off. FOUND_PLUTO_SPATHI bit will keep the node from
+ // showing up on subsequent visits.
+ return false;
+ }
+
+ if (matchWorld (solarSys, world, 2, 1))
+ { // Earth Moon
+ assert (!GET_GAME_STATE (MOONBASE_DESTROYED) && whichNode == 0);
+
+ GenerateDefault_landerReport (solarSys);
+ SetLanderTakeoff ();
+
+ SET_GAME_STATE (MOONBASE_DESTROYED, 1);
+ SET_GAME_STATE (MOONBASE_ON_SHIP, 1);
+
+ return true; // picked up
+ }
+
+ (void) whichNode;
+ return false;
+}
+
+static COUNT
+GenerateSol_generateLife (const SOLARSYS_STATE *solarSys,
+ const PLANET_DESC *world, COUNT whichNode, NODE_INFO *info)
+{
+ if (matchWorld (solarSys, world, 2, 1))
+ {
+ /* Earth Moon */
+ return GenerateRandomNodes (&solarSys->SysInfo, BIOLOGICAL_SCAN, 10,
+ NUM_CREATURE_TYPES + 1, whichNode, info);
+ }
+
+ return 0;
+}
+
+
+static int
+init_probe (void)
+{
+ HIPGROUP hGroup;
+
+ if (!GET_GAME_STATE (PROBE_MESSAGE_DELIVERED)
+ && GetGroupInfo (GLOBAL (BattleGroupRef), GROUP_INIT_IP)
+ && (hGroup = GetHeadLink (&GLOBAL (ip_group_q))))
+ {
+ IP_GROUP *GroupPtr;
+
+ GroupPtr = LockIpGroup (&GLOBAL (ip_group_q), hGroup);
+ GroupPtr->task = IN_ORBIT;
+ GroupPtr->sys_loc = 2 + 1; /* orbitting earth */
+ GroupPtr->dest_loc = 2 + 1; /* orbitting earth */
+ GroupPtr->loc.x = 0;
+ GroupPtr->loc.y = 0;
+ GroupPtr->group_counter = 0;
+ UnlockIpGroup (&GLOBAL (ip_group_q), hGroup);
+
+ return 1;
+ }
+ else
+ return 0;
+}
+
+static void
+check_probe (void)
+{
+ HIPGROUP hGroup;
+ IP_GROUP *GroupPtr;
+
+ if (!GLOBAL (BattleGroupRef))
+ return; // nothing to check
+
+ hGroup = GetHeadLink (&GLOBAL (ip_group_q));
+ if (!hGroup)
+ return; // still nothing to check
+
+ GroupPtr = LockIpGroup (&GLOBAL (ip_group_q), hGroup);
+ // REFORM_GROUP was set in ipdisp.c:ip_group_collision()
+ // during a collision with the flagship.
+ if (GroupPtr->race_id == URQUAN_DRONE_SHIP
+ && (GroupPtr->task & REFORM_GROUP))
+ {
+ // We just want the probe to take off as fast as possible,
+ // so clear out REFORM_GROUP
+ GroupPtr->task = FLEE | IGNORE_FLAGSHIP;
+ GroupPtr->dest_loc = 0;
+ }
+ UnlockIpGroup (&GLOBAL (ip_group_q), hGroup);
+}
+