summaryrefslogtreecommitdiff
path: root/src/uqm/planets/surface.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/uqm/planets/surface.c')
-rw-r--r--src/uqm/planets/surface.c251
1 files changed, 251 insertions, 0 deletions
diff --git a/src/uqm/planets/surface.c b/src/uqm/planets/surface.c
new file mode 100644
index 0000000..79f9e75
--- /dev/null
+++ b/src/uqm/planets/surface.c
@@ -0,0 +1,251 @@
+//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 "lifeform.h"
+#include "planets.h"
+#include "libs/mathlib.h"
+#include "libs/log.h"
+
+
+//#define DEBUG_SURFACE
+
+const BYTE *Elements;
+const PlanetFrame *PlanData;
+
+static COUNT
+CalcMineralDeposits (const SYSTEM_INFO *SysInfoPtr, COUNT which_deposit,
+ NODE_INFO *info)
+{
+ BYTE j;
+ COUNT num_deposits;
+ const ELEMENT_ENTRY *eptr;
+
+ eptr = &SysInfoPtr->PlanetInfo.PlanDataPtr->UsefulElements[0];
+ num_deposits = 0;
+ j = NUM_USEFUL_ELEMENTS;
+ do
+ {
+ BYTE num_possible;
+
+ num_possible = LOBYTE (RandomContext_Random (SysGenRNG))
+ % (DEPOSIT_QUANTITY (eptr->Density) + 1);
+ while (num_possible--)
+ {
+#define MEDIUM_DEPOSIT_THRESHOLD 150
+#define LARGE_DEPOSIT_THRESHOLD 225
+ COUNT deposit_quality_fine;
+ COUNT deposit_quality_gross;
+
+ deposit_quality_fine = (LOWORD (RandomContext_Random (SysGenRNG)) % 100)
+ + (
+ DEPOSIT_QUALITY (eptr->Density)
+ + SysInfoPtr->StarSize
+ ) * 50;
+ if (deposit_quality_fine < MEDIUM_DEPOSIT_THRESHOLD)
+ deposit_quality_gross = 0;
+ else if (deposit_quality_fine < LARGE_DEPOSIT_THRESHOLD)
+ deposit_quality_gross = 1;
+ else
+ deposit_quality_gross = 2;
+
+ GenerateRandomLocation (&info->loc_pt);
+
+ info->density = MAKE_WORD (
+ deposit_quality_gross, deposit_quality_fine / 10 + 1);
+ info->type = eptr->ElementType;
+#ifdef DEBUG_SURFACE
+ log_add (log_Debug, "\t\t%d units of %Fs",
+ info->density,
+ Elements[eptr->ElementType].name);
+#endif /* DEBUG_SURFACE */
+ if (num_deposits >= which_deposit
+ || ++num_deposits == sizeof (DWORD) * 8)
+ { // reached the maximum or the requested node
+ return num_deposits;
+ }
+ }
+ ++eptr;
+ } while (--j);
+
+ return num_deposits;
+}
+
+// Returns:
+// for whichLife==~0 : the number of nodes generated
+// for whichLife<32 : the index of the last node (no known usage exists)
+// Sets the SysGenRNG to the required state first.
+COUNT
+GenerateMineralDeposits (const SYSTEM_INFO *SysInfoPtr, COUNT whichDeposit,
+ NODE_INFO *info)
+{
+ NODE_INFO temp_info;
+ if (!info) // user not interested in info but we need space for it
+ info = &temp_info;
+ RandomContext_SeedRandom (SysGenRNG,
+ SysInfoPtr->PlanetInfo.ScanSeed[MINERAL_SCAN]);
+ return CalcMineralDeposits (SysInfoPtr, whichDeposit, info);
+}
+
+static COUNT
+CalcLifeForms (const SYSTEM_INFO *SysInfoPtr, COUNT which_life,
+ NODE_INFO *info)
+{
+ COUNT num_life_forms;
+
+ num_life_forms = 0;
+ if (PLANSIZE (SysInfoPtr->PlanetInfo.PlanDataPtr->Type) != GAS_GIANT)
+ {
+#define MIN_LIFE_CHANCE 10
+ SIZE life_var;
+
+ life_var = RandomContext_Random (SysGenRNG) & 1023;
+ if (life_var < SysInfoPtr->PlanetInfo.LifeChance
+ || (SysInfoPtr->PlanetInfo.LifeChance < MIN_LIFE_CHANCE
+ && life_var < MIN_LIFE_CHANCE))
+ {
+ BYTE num_types;
+
+ num_types = 1 + LOBYTE (RandomContext_Random (SysGenRNG))
+ % MAX_LIFE_VARIATION;
+ do
+ {
+ BYTE index, num_creatures;
+ UWORD rand_val;
+
+ rand_val = RandomContext_Random (SysGenRNG);
+ index = LOBYTE (rand_val) % NUM_CREATURE_TYPES;
+ num_creatures = 1 + HIBYTE (rand_val) % 10;
+ do
+ {
+ GenerateRandomLocation (&info->loc_pt);
+ info->type = index;
+ info->density = 0;
+
+ if (num_life_forms >= which_life
+ || ++num_life_forms == sizeof (DWORD) * 8)
+ { // reached the maximum or the requested node
+ return num_life_forms;
+ }
+ } while (--num_creatures);
+ } while (--num_types);
+ }
+#ifdef DEBUG_SURFACE
+ else
+ {
+ log_add (log_Debug, "It's dead, Jim! (%d >= %d)", life_var,
+ SysInfoPtr->PlanetInfo.LifeChance);
+ }
+#endif /* DEBUG_SURFACE */
+ }
+
+ return num_life_forms;
+}
+
+// Returns:
+// for whichLife==~0 : the number of lifeforms generated
+// for whichLife<32 : the index of the last lifeform (no known usage exists)
+// Sets the SysGenRNG to the required state first.
+COUNT
+GenerateLifeForms (const SYSTEM_INFO *SysInfoPtr, COUNT whichLife,
+ NODE_INFO *info)
+{
+ NODE_INFO temp_info;
+ if (!info) // user not interested in info but we need space for it
+ info = &temp_info;
+ RandomContext_SeedRandom (SysGenRNG,
+ SysInfoPtr->PlanetInfo.ScanSeed[BIOLOGICAL_SCAN]);
+ return CalcLifeForms (SysInfoPtr, whichLife, info);
+}
+
+// Returns:
+// for whichLife==~0 : the number of lifeforms generated
+// for whichLife<32 : the index of the last lifeform (no known usage exists)
+// Sets the SysGenRNG to the required state first.
+// lifeTypes[] is terminated with -1
+COUNT
+GeneratePresetLife (const SYSTEM_INFO *SysInfoPtr, const SBYTE *lifeTypes,
+ COUNT whichLife, NODE_INFO *info)
+{
+ COUNT i;
+ NODE_INFO temp_info;
+
+ if (!info) // user not interested in info but we need space for it
+ info = &temp_info;
+
+ // This function may look unnecessarily complicated, but it must be
+ // kept this way to preserve the universe. That is done by preserving
+ // the order and number of Random() calls.
+
+ RandomContext_SeedRandom (SysGenRNG,
+ SysInfoPtr->PlanetInfo.ScanSeed[BIOLOGICAL_SCAN]);
+
+ for (i = 0; lifeTypes[i] >= 0; ++i)
+ {
+ GenerateRandomLocation (&info->loc_pt);
+ info->type = lifeTypes[i];
+ // density is irrelevant for bio nodes
+ info->density = 0;
+
+ if (i >= whichLife)
+ break;
+ }
+
+ return i;
+}
+
+void
+GenerateRandomLocation (POINT *loc)
+{
+ UWORD rand_val;
+
+ rand_val = RandomContext_Random (SysGenRNG);
+ loc->x = 8 + LOBYTE (rand_val) % (MAP_WIDTH - (8 << 1));
+ loc->y = 8 + HIBYTE (rand_val) % (MAP_HEIGHT - (8 << 1));
+}
+
+// Returns:
+// for whichNode==~0 : the number of nodes generated
+// for whichNode<32 : the index of the last node (no known usage exists)
+// Sets the SysGenRNG to the required state first.
+COUNT
+GenerateRandomNodes (const SYSTEM_INFO *SysInfoPtr, COUNT scan, COUNT numNodes,
+ COUNT type, COUNT whichNode, NODE_INFO *info)
+{
+ COUNT i;
+ NODE_INFO temp_info;
+
+ if (!info) // user not interested in info but we need space for it
+ info = &temp_info;
+
+ RandomContext_SeedRandom (SysGenRNG,
+ SysInfoPtr->PlanetInfo.ScanSeed[scan]);
+
+ for (i = 0; i < numNodes; ++i)
+ {
+ GenerateRandomLocation (&info->loc_pt);
+ // type is irrelevant for energy nodes
+ info->type = type;
+ // density is irrelevant for energy and bio nodes
+ info->density = 0;
+
+ if (i >= whichNode)
+ break;
+ }
+
+ return i;
+}