diff src/pl_gen3.c @ 4:aa38447a4b21

First entry of Paradise Server 2.9 patch 10 Beta
author darius
date Sat, 06 Dec 1997 04:37:03 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pl_gen3.c	Sat Dec 06 04:37:03 1997 +0000
@@ -0,0 +1,561 @@
+/*--------------------------------------------------------------------------
+NETREK II -- Paradise
+
+Permission to use, copy, modify, and distribute this software and its
+documentation, or any derivative works thereof, for any NON-COMMERCIAL
+purpose and without fee is hereby granted, provided that this copyright
+notice appear in all copies.  No representations are made about the
+suitability of this software for any purpose.  This software is provided
+"as is" without express or implied warranty.
+
+    Xtrek Copyright 1986                            Chris Guthrie
+    Netrek (Xtrek II) Copyright 1989                Kevin P. Smith
+                                                    Scott Silvey
+    Paradise II (Netrek II) Copyright 1993          Larry Denys
+                                                    Kurt Olsen
+                                                    Brandon Gillespie
+--------------------------------------------------------------------------*/
+
+#include "config.h"
+#include <math.h>
+
+#include "defs.h"
+#include "struct.h"
+#include "data.h"
+#include "shmem.h"
+#include "planets.h"
+
+#define SYSWIDTH	(GWIDTH/5.9)	/* width of a system */
+
+#define SYSTEMS		9	/* number of planetary systems */
+
+/* atmosphere chances form a cascade win rand()%100 */
+#define PATMOS1		40	/* chance for normal atmosphere */
+#define PATMOS2		70	/* chance for thin atmosphere */
+#define PATMOS3		90	/* chance for slightly toxic stmos */
+#define PPOISON		100	/* chance for poison atmos */
+
+/* defines that deal with planets resources and types */
+#define NMETAL		13	/* number of metal deposits */
+#define NDILYTH		10	/* number of dilythium deposits */
+#define NARABLE		15	/* number of arable land planets */
+/* defines that deal with star placement */
+
+#define GW	((float)GWIDTH)	/* size of galaxy in floating point */
+#define	STARBORD	(GW*0.27)
+#define TEAMBORD	(GW*0.32)
+#define STARMIN		(GW/5.6)/* min dist between stars */
+#define STARMAX		GW
+#define TEAMMIN		(GW/2.8)/* min dist between team stars */
+#define TEAMMAX		(GW/1.8)/* max dist between team stars */
+
+/* defines that deal with systems and their planets */
+#define SYSADD		2	/* number possible above min number */
+#define SYSBORD		(7000.0 + (float)GWIDTH/200)	/* min distance from
+							 * border wall */
+#define INDBORD		(GW*0.23)
+#define SYSMIN		(5500.0 + (float)GWIDTH/200)	/* min distance between
+							 * objects */
+#define SYSMIN2		(SYSMIN*SYSMIN)	/* square of sysmin distance */
+#define SYSPLMIN	5	/* min number of planets for system */
+#define SYSPLADD	0	/* number of possible extra planets */
+#define MINARMY 8		/* min numer of armies on a planet */
+#define MAXARMY 15		/* max number of armies on a planet */
+
+/* other defines */
+#define HOMEARMIES 30		/* number of armies on home planets */
+#define COLONYARMIES 10		/* number of armies for colony planet */
+
+
+/* defines dealing with growth timers */
+#define PLGFUEL		configvals->plgrow.fuel	/* time for growth of fuel
+						 * depot */
+#define PLGAGRI		configvals->plgrow.agri	/* time for growth of agri */
+#define PLGREPAIR	configvals->plgrow.repair	/* time for growth of
+							 * repair */
+#define PLGSHIP		configvals->plgrow.shipyard	/* time for growth of
+							 * shipyard */
+
+
+#if 0
+/*-------------------------------GENRESOURCES----------------------------*/
+/*
+ * This function goes through the planets structure and determines what kind
+ * of atmosphere and what kind of surface the planets have.  It generates the
+ * stars that will be used as system centers ans then places atmospheres on
+ * the other planets.  It then distributes the resources on the planet
+ * surfaces.
+ */
+
+static void
+genresources()
+{
+  int i;			/* looping vars */
+  int t;			/* temp var */
+
+  for (i = 0; i < SYSTEMS; i++)	/* first planets are stars */
+    planets[i].pl_flags |= PLSTAR;	/* or in star flag */
+  for (i = SYSTEMS; i < NUMPLANETS; i++)
+  {				/* generate atmospheres */
+    t = lrand48() % 100;	/* random # 0-99 */
+    if (t < PATMOS1)		/* is it atmosphere type 1 */
+      planets[i].pl_flags |= PLATYPE1;
+    else if (t < PATMOS2)	/* is it atmosphere type 2 */
+      planets[i].pl_flags |= PLATYPE2;
+    else if (t < PATMOS3)	/* is it atmosphere type 3 */
+      planets[i].pl_flags |= PLATYPE3;
+    else if (t < PPOISON)	/* is it poison atmosphere */
+      planets[i].pl_flags |= PLPOISON;
+  }
+  for (i = 0; i < NMETAL; i++)
+  {				/* place the metal deposits */
+    t = lrand48() % (NUMPLANETS - SYSTEMS) + SYSTEMS;	/* random planet */
+    planets[t].pl_flags |= PLMETAL;	/* OR in the metal flag */
+    if (!configvals->resource_bombing)
+      planets[t].pl_flags |= PLREPAIR;
+  }
+  for (i = 0; i < NDILYTH; i++)
+  {				/* place the metal deposits */
+    t = lrand48() % (NUMPLANETS - SYSTEMS) + SYSTEMS;	/* random planet */
+    planets[t].pl_flags |= PLDILYTH;	/* OR in the dilyth flag */
+    planets[t].pl_flags &= ~(PLATMASK | PLARABLE);	/* zero off previous
+							 * atmos */
+    planets[t].pl_flags |= PLPOISON;	/* dilyth poisons atmosphere */
+    if (!configvals->resource_bombing)
+      planets[t].pl_flags |= PLFUEL;
+  }
+  for (i = 0; i < NARABLE; i++)
+  {				/* place the metal deposits */
+    t = lrand48() % (NUMPLANETS - SYSTEMS) + SYSTEMS;	/* random planet */
+    planets[t].pl_flags |= PLARABLE | PLATYPE1;	/* OR in the arable flag */
+    if (!configvals->resource_bombing)
+      planets[t].pl_flags |= PLAGRI;
+  }
+}
+#endif
+
+
+
+#if 0
+/*--------------------------------PLACESTARS------------------------------*/
+/*
+ * This function places each system's star.  The stars are expected to be in
+ * the first SYSTEMS number of planets.  The coordinates of the stars are
+ * placed in the space grid.
+ */
+
+static int
+placestars()
+{
+  int i, j;			/* looping vars */
+  double x, y;			/* to hold star coordinates */
+  int done;			/* flag to indicate done */
+  double dx, dy;		/* delta x and y's */
+  int attempts;
+  double min, max, dist, bord, nbwidth;
+  double xoff, yoff;
+
+  for (i = 0; i < SYSTEMS; i++)
+  {				/* star for each system */
+    if (i < 2)
+    {				/* choose optimal position for first two */
+      min = TEAMMIN2;
+      max = TEAMMAX2;
+      bord = TEAMBORD;
+    }
+    else if (i < 4)
+    {
+      min = TEAMMIN2;
+      max = STARMAX2;
+      bord = STARBORD * 0.8;
+    }
+    else
+    {
+      min = STARMIN2;
+      max = STARMAX2;
+      bord = STARBORD;
+    }
+    nbwidth = GW - 2 * bord;
+    x = drand48() * nbwidth + bord;	/* pick intial coords */
+    y = drand48() * nbwidth + bord;
+    xoff = 3574.0 - bord;
+    yoff = 1034.0 - bord;
+    attempts = 0;
+    do
+    {				/* do until location found */
+      attempts++;
+      done = 0;			/* not done yet */
+      x = bord + fmod(x + xoff, nbwidth);	/* offset coords a little */
+      y = bord + fmod(y + yoff, nbwidth);	/* every loop */
+#if 0
+      if ((x > GW - bord) || (x < bord)
+	  || (y < bord) || (y > GW - bord))
+	continue;		/* too close to border? */
+#endif
+      done = 1;			/* assume valid cord found */
+      for (j = 0; j < i; j++)
+      {				/* go through previous stars */
+	dx = fabs(x - (double) planets[j].pl_x);
+	dy = fabs(y - (double) planets[j].pl_y);
+	dist = dx * dx + dy * dy;
+	if (dist < min || dist > max)	/* if too close or too far then */
+	  done = 0;		/* we must get another coord */
+      }
+    } while (!done && attempts < 1000);	/* do until location found */
+
+    if (!done)
+      return 0;
+
+    planets[i].pl_owner = NOBODY;	/* no team owns a star */
+    planets[i].pl_flags |= PLSTAR;	/* mark planet as a star */
+    move_planet(i, (int) x, (int) y, 0);
+    planets[i].pl_system = i + 1;	/* mark the sytem number */
+    planets[i].pl_hinfo = ALLTEAM;	/* all teams know its a star */
+    for (j = 0; j < MAXTEAM + 1; j++)
+    {				/* go put in info for teams */
+      planets[i].pl_tinfo[j].owner = NOBODY;	/* nobody owns it */
+      planets[i].pl_tinfo[j].armies = 0;
+      planets[i].pl_tinfo[j].flags = planets[i].pl_flags;
+    }
+  }
+  return 1;
+}
+#endif
+
+
+
+/*-----------------------------PLACESYSTEMS------------------------------*/
+/*
+ * This function places the planets in each star's system.  The function will
+ * return the index of the first planet that was not placed in a system. The
+ * coordinates of the planets are placed in the space grid.
+ */
+
+static int
+placesystems()
+{
+  int i, j, k;			/* looping vars */
+  double x, y;			/* to hold star coordinates */
+  int done;			/* flag to indicate done */
+  double dx, dy;		/* delta x and y's */
+  int n;			/* number of planet to place */
+  int np;			/* number of planets in system */
+  int attempts;
+
+  n = SYSTEMS;			/* first planet to place */
+  for (i = 0; i < SYSTEMS; i++)
+  {				/* planets for each system */
+    np = SYSPLMIN + lrand48() % (SYSPLADD + 1);	/* how many planets */
+    for (k = 0; k < np; k++)
+    {				/* go place the planets */
+      attempts = 0;
+      do
+      {				/* do until location found */
+	attempts++;
+	done = 0;		/* not done yet */
+	dx = (drand48() * SYSWIDTH - SYSWIDTH / 2.0);
+	dy = (drand48() * SYSWIDTH - SYSWIDTH / 2.0);
+	if (dx * dx + dy * dy > (SYSWIDTH / 2.0) * (SYSWIDTH / 2.0))
+	  continue;		/* might orbit its way out of the galaxy */
+	x = planets[i].pl_x + dx;
+	y = planets[i].pl_y + dy;
+	if ((x > GW - SYSBORD) || (x < SYSBORD)
+	    || (y < SYSBORD) || (y > GW - SYSBORD))
+	  continue;		/* too close to border? */
+
+	done = 1;		/* assume valid coord found */
+	for (j = 0; j < n; j++)
+	{			/* go through previous planets */
+	  dx = fabs(x - (double) planets[j].pl_x);
+	  dy = fabs(y - (double) planets[j].pl_y);
+	  if (dx * dx + dy * dy < SYSMIN2)
+	  {			/* if too close to another star */
+	    done = 0;		/* we must get another coord */
+	  }
+	}
+      } while (!done && attempts < 200);	/* do until location found */
+
+      if (!done)
+	return 0;		/* universe too crowded, try again */
+
+      move_planet(n, (int) x, (int) y, 0);
+      planets[n].pl_system = i + 1;	/* mark the sytem number */
+      planets[n].pl_armies = MINARMY + lrand48() % (MAXARMY - MINARMY);
+      n++;			/* go to next planet */
+    }
+  }
+  return (n);			/* return index of next planet */
+}
+
+
+
+
+/*-----------------------------PLACEINDEP------------------------------*/
+/*
+ * This function places idependent planets that are not in a system. They can
+ * appear anywhere in the galaxy as long as they are not too close to another
+ * planet.  The coords are put in the space grid.
+ */
+
+static int
+placeindep(n)
+  int n;
+/* number of planet to start with */
+{
+  int i, j;			/* looping vars */
+  double x, y;			/* to hold star coordinates */
+  int done;			/* flag to indicate done */
+  double dx, dy;		/* delta x and y's */
+  int attempts;
+
+  for (i = n; i < (NUMPLANETS - (WORMPAIRS * 2)); i++)
+  {				/* go through rest of planets */
+    x = drand48() * (GW - 2 * INDBORD) + INDBORD;	/* pick initial coords */
+    y = drand48() * (GW - 2 * INDBORD) + INDBORD;
+    attempts = 0;
+    do
+    {				/* do until location found */
+      attempts++;
+      done = 0;			/* not done yet */
+      x = INDBORD + fmod(x + (3574.0 - INDBORD), GW - 2 * INDBORD);	/* offset coords a
+									 * little */
+      y = INDBORD + fmod(y + (1034.0 - INDBORD), GW - 2 * INDBORD);	/* every loop */
+#if 0
+      if ((x > GW - INDBORD) || (x < INDBORD)
+	  || (y < INDBORD) || (y > GW - INDBORD))
+	continue;		/* too close to border? */
+#endif
+      done = 1;			/* assume valid coord */
+      for (j = 0; j < n; j++)
+      {				/* go through previous planets */
+	dx = fabs(x - (double) planets[j].pl_x);
+	dy = fabs(y - (double) planets[j].pl_y);
+	if (dx * dx + dy * dy < SYSMIN2)
+	{			/* if planet to close */
+	  done = 0;		/* we must get another coord */
+	}
+      }
+    } while (!done && attempts < 200);	/* do until location found */
+
+    if (!done)
+      return 0;
+
+    move_planet(n, (int) x, (int) y, 0);
+    planets[n].pl_system = 0;	/* mark the no sytem */
+    planets[n].pl_armies = MINARMY + lrand48() % (MAXARMY - MINARMY);
+    n++;			/* go to next planet */
+  }
+  for (i = n; i < NUMPLANETS; i++)	/* now place wormholes */
+  {
+    x = drand48() * GW;		/* pick intial coords */
+    y = drand48() * GW;
+    attempts = 0;
+    do
+    {				/* do until location found */
+      attempts++;
+      done = 0;			/* not done yet */
+      x = fmod(x + 3574.0, GW);	/* offset coords a little */
+      y = fmod(y + 1034.0, GW);	/* every loop */
+#if 0
+      if ((x > GW) || (y > GW))
+	continue;		/* too close to border? */
+#endif
+      done = 1;			/* assume valid coord */
+      for (j = 0; j < n; j++)
+      {				/* go through previous planets */
+	dx = fabs(x - (double) planets[j].pl_x);
+	dy = fabs(y - (double) planets[j].pl_y);
+	if (dx * dx + dy * dy < SYSMIN2)
+	{			/* if planet to close */
+	  done = 0;		/* we must get another coord */
+	}
+      }
+    } while (!done && attempts < 200);	/* do until location found */
+
+    if (!done)
+      return 0;
+
+    move_planet(n, (int) x, (int) y, 0);
+    planets[n].pl_system = 0;	/* mark the no system */
+    planets[n].pl_flags |= PLWHOLE;	/* mark the planet as a wormhole */
+    /* the armies in a wormhole is the other wormhole's x coord */
+    /* the radius is the other wormhole's y coord */
+    if (NUMPLANETS % 2)
+    {
+      if (!(n % 2))
+      {
+	planets[n].pl_armies = planets[n - 1].pl_x;
+	planets[n].pl_radius = planets[n - 1].pl_y;
+	planets[n - 1].pl_armies = planets[n].pl_x;
+	planets[n - 1].pl_radius = planets[n].pl_y;
+      }
+    }
+    else
+    {
+      if (n % 2)
+      {
+	planets[n].pl_armies = planets[n - 1].pl_x;
+	planets[n].pl_radius = planets[n - 1].pl_y;
+	planets[n - 1].pl_armies = planets[n].pl_x;
+	planets[n - 1].pl_radius = planets[n].pl_y;
+      }
+    }
+    planets[i].pl_owner = NOBODY;	/* no team owns a star */
+    planets[i].pl_hinfo = ALLTEAM;	/* all teams know its a star */
+    for (j = 0; j < MAXTEAM + 1; j++)
+    {				/* go put in info for teams */
+      planets[i].pl_tinfo[j].owner = NOBODY;	/* nobody owns it */
+      planets[i].pl_tinfo[j].armies = 0;
+      planets[i].pl_tinfo[j].flags = planets[i].pl_flags;
+    }
+    n++;			/* go to next planet */
+  }
+  return 1;
+}
+
+
+
+
+/*---------------------------------PLACERACES------------------------------*/
+/*
+ * This function places the races in the galaxy.  Each race is placed in a
+ * different system.  The race is given a home world with an Agri and Ship-
+ * yard on it and HOMEARMIES.  They are also given a conoly planet with
+ * dilythium deposits and COLONYARMIES on it.
+ */
+
+static void
+placeraces()
+{
+  int i, j, k;			/* looping vars */
+  int p;			/* to hold planet for race */
+  int r[4], t;
+
+  r[0] = r[1] = lrand48() % 4;	/* pick two races at random.  They will be */
+  while (r[0] == r[1])		/* the races whose systems are 'optimally' */
+    r[1] = lrand48() % 4;	/* placed. */
+  i = 0;
+  while (i == r[0] || i == r[1])
+    i++;
+  r[2] = i++;
+  while (i == r[0] || i == r[1])
+    i++;
+  r[3] = i;
+  status2->nontteamlock = (1 << r[0]) | (1 << r[1]);	/* only allow these
+							 * teams */
+
+  for (i = 0; i < 4; i++)
+  {				/* go through races */
+    t = r[i];			/* which team */
+    p = lrand48() % NUMPLANETS;	/* pick random planet */
+    while ((planets[p].pl_system != i + 1)
+	   || (PL_TYPE(planets[p]) == PLSTAR)
+	   || (planets[p].pl_owner != NOBODY))
+      p = (p + 1) % NUMPLANETS;	/* go on to next planet */
+
+    planets[p].pl_flags &= ~PLSURMASK;	/* make sure no dilithium */
+    planets[p].pl_flags |= (PLMETAL | PLARABLE);	/* metal and arable */
+    planets[p].pl_flags |= PLATYPE1;	/* good atmosphere */
+    planets[p].pl_flags |= (PLAGRI | PLSHIPYARD | PLREPAIR);
+    planets[p].pl_tagri = PLGAGRI;	/* set timers for resources */
+    planets[p].pl_tshiprepair = PLGSHIP;
+    planets[p].pl_owner = 1 << t;	/* make race the owner */
+    planets[p].pl_armies = HOMEARMIES;	/* set the armies */
+    planets[p].pl_hinfo = 1 << t;	/* race has info on planet */
+    planets[p].pl_tinfo[1 << t].owner = 1 << t;	/* know about owner */
+    planets[p].pl_tinfo[1 << t].armies = planets[p].pl_armies;
+    planets[p].pl_tinfo[1 << t].flags = planets[p].pl_flags;
+    /* find colony planet */
+    p = lrand48() % NUMPLANETS;	/* pick random planet */
+    while ((planets[p].pl_system != i + 1)
+	   || (PL_TYPE(planets[p]) == PLSTAR)
+	   || (planets[p].pl_owner != NOBODY))
+      p = (p + 1) % NUMPLANETS;	/* go on to next planet */
+    planets[p].pl_flags |= PLFUEL;	/* make fuel depot */
+    planets[p].pl_tfuel = PLGFUEL;	/* set timer for fuel depot */
+    planets[p].pl_flags &= ~PLATMASK;	/* take off previous atmos */
+    planets[p].pl_flags |= PLPOISON;	/* poison atmosphere */
+    planets[p].pl_flags |= PLDILYTH;	/* dilythium deposits */
+    planets[p].pl_owner = 1 << t;	/* make race the owner */
+    planets[p].pl_armies = COLONYARMIES;	/* set the armies */
+    planets[p].pl_hinfo = 1 << t;	/* race knows about */
+    planets[p].pl_tinfo[1 << t].owner = 1 << t;	/* know about owner */
+    planets[p].pl_tinfo[1 << t].armies = planets[p].pl_armies;
+    planets[p].pl_tinfo[1 << t].flags = planets[p].pl_flags;
+    for (j = 0; j < NUMPLANETS; j++)
+    {
+      if ((planets[j].pl_system == i + 1) && (PL_TYPE(planets[j]) != PLSTAR))
+      {
+#ifdef LEAGUE_SUPPORT
+	for (k = (status2->league ? 0 : t);
+	     k < (status2->league ? 4 : t + 1);
+	     k++)
+#else
+	k = t;
+#endif
+	{
+	  planets[j].pl_owner = 1 << t;
+	  planets[j].pl_hinfo =
+#ifdef LEAGUE_SUPPORT
+	    status2->league ? (1 << 4) - 1 :
+#endif
+	    (1 << t);
+	  planets[j].pl_tinfo[1 << k].owner = 1 << t;
+	  planets[j].pl_tinfo[1 << k].armies = planets[j].pl_armies;
+	  planets[j].pl_tinfo[1 << k].flags = planets[j].pl_flags;
+	}
+      }
+    }
+  }
+}
+
+/*
+ * Generate a complete galaxy. This variation is similar to gen_galaxy_1;
+ * except that it tries to place the races at consistent distances from one
+ * another.
+ */
+
+void
+gen_galaxy_3()
+{
+  int t;
+
+  NUMPLANETS = 60;		/* planets + wormholes */
+  GWIDTH = 200000;
+
+  while (1)
+  {
+    initplanets();		/* initialize planet structures */
+
+    /* place the resources */
+    zero_plflags(planets, NUMPLANETS);
+    randomize_atmospheres(planets + SYSTEMS, NUMPLANETS - SYSTEMS,
+			  PATMOS1, PATMOS2, PATMOS3, PPOISON);
+    randomize_resources(planets + SYSTEMS, NUMPLANETS - SYSTEMS,
+			NMETAL, NDILYTH, NARABLE);
+
+    /* place system centers */
+    t = place_stars(planets, 2,
+		    (int) TEAMBORD, (int) TEAMMIN, (int) TEAMMAX,
+		    (struct planet *) 0, 0)
+      && place_stars(planets + 2, 2,
+		     (int) (STARBORD * 0.8), (int) TEAMMIN, (int) STARMAX,
+		     planets, 2)
+      && place_stars(planets + 4, SYSTEMS - 4,
+		     (int) STARBORD, (int) STARMIN, (int) STARMAX,
+		     planets, 4);
+
+    if (!t)
+      continue;
+    t = placesystems();		/* place planets in systems */
+    if (!t)
+      continue;
+    t = placeindep(t);		/* place independent planets */
+    if (t)
+      break;			/* success */
+  }
+  if (configvals->justify_galaxy)
+    justify_galaxy(SYSTEMS);
+  placeraces();			/* place home planets for races */
+
+}