changeset 6:8c6d5731234d

First entry of Paradise Server 2.9 patch 10 Beta
author darius
date Sat, 06 Dec 1997 04:37:04 +0000
parents 054275999194
children 814de70c9f67
files src/pl_gen6.c src/pl_gen7.c src/planets.c src/planets.h src/plasma.c src/player.h src/plutil.c src/plutil.h src/rcslog src/redraw.c src/rmove.c src/robotII.c src/shipvals.c src/shmem.c src/shmem.h src/shmemP.h src/sintab.c src/smessage.c src/snake.c src/snakemove.c src/socket.c
diffstat 21 files changed, 15143 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pl_gen6.c	Sat Dec 06 04:37:04 1997 +0000
@@ -0,0 +1,419 @@
+/*--------------------------------------------------------------------------
+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/4.5)	/* 5.9 width of a system */
+
+#define SYSTEMS		6	/* 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	9	/* 5 min number of planets for system */
+#define SYSPLADD	0	/* number of possible extra planets */
+#define MINARMY 5		/* 8		/* min numer of armies on a
+				 * planet */
+#define MAXARMY 6		/* 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 */
+
+
+/*-----------------------------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, x;		/* 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;
+
+  /* only allow these teams */
+  status2->nontteamlock = (1 << r[0]) | (1 << r[1]);
+
+  for (i = 0; i < 4; i++)
+  {				/* go through races */
+    t = r[i];			/* which team */
+    p = lrand48() % NUMPLANETS;	/* pick random planet */
+    /* for (x=0; x <= 1; x++) {  /* loop twice for 2 systems */
+    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_6()
+{
+  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 */
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pl_gen7.c	Sat Dec 06 04:37:04 1997 +0000
@@ -0,0 +1,547 @@
+/*--------------------------------------------------------------------------
+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		7	/* 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		10	/* number of metal deposits */
+#define NDILYTH		8	/* number of dilythium deposits */
+#define NARABLE		12	/* number of arable land planets */
+/* defines that deal with star placement */
+
+#define GW	((float)GWIDTH)	/* size of galaxy in floating point */
+#define	STARBORD	((GW/5.2)*1.3)
+#define TEAMBORD	((GW/5.2)/1.1)
+#define STARMIN		(GW/5.0)/* min dist between stars */
+#define STARMIN2	(STARMIN*STARMIN)	/* min star dist squared */
+#define STARMAX		GW
+#define STARMAX2	(GW*GW)
+#define TEAMMIN		(GW/2.8)/* min dist between team stars */
+#define TEAMMIN2	(TEAMMIN*TEAMMIN)
+#define TEAMMAX		(GW/1.4)/* max dist between team stars */
+#define TEAMMAX2	(TEAMMAX*TEAMMAX)
+
+/* defines that deal with systems and their planets */
+#define SYSADD		2	/* number possible above min number */
+#define SYSBORD		(4000.0 + (float)GWIDTH/200)	/* min distance from
+							 * border wall */
+#define INDBORD		(GW * 0.1)
+#define SYSMIN		(6000.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 < 4)
+    {
+      min = TEAMMIN2;
+      max = TEAMMAX2;
+      bord = TEAMBORD;
+    }
+    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 */
+	  }
+	  if (ihypot((int) dx, (int) dy) < 3000)
+	    done = 0;
+	}
+      } 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 intial 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 */
+
+  for (i = 0; i < 4; i++)
+  {				/* go through races */
+    /* find home 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 &= ~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 << i;	/* make race the owner */
+#if 0				/* home planets do not have traditional names */
+    strcpy(planets[p].pl_name, homenames[1 << i]);	/* set name and length */
+    planets[p].pl_namelen = strlen(homenames[1 << i]);
+#endif
+    planets[p].pl_armies = HOMEARMIES;	/* set the armies */
+    planets[p].pl_hinfo = 1 << i;	/* race has info on planet */
+    planets[p].pl_tinfo[1 << i].owner = 1 << i;	/* know about owner */
+    planets[p].pl_tinfo[1 << i].armies = planets[p].pl_armies;
+    planets[p].pl_tinfo[1 << i].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 << i;	/* make race the owner */
+    planets[p].pl_armies = COLONYARMIES;	/* set the armies */
+    planets[p].pl_hinfo = 1 << i;	/* race knows about */
+    planets[p].pl_tinfo[1 << i].owner = 1 << i;	/* know about owner */
+    planets[p].pl_tinfo[1 << i].armies = planets[p].pl_armies;
+    planets[p].pl_tinfo[1 << i].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 : i);
+	     k < (status2->league ? 4 : i + 1);
+	     k++)
+#else
+	k = i;
+#endif
+	{
+	  planets[j].pl_owner = 1 << i;
+	  planets[j].pl_hinfo =
+#ifdef LEAGUE_SUPPORT
+	    status2->league ? (1 << 4) - 1 :
+#endif
+	    (1 << i);
+	  planets[j].pl_tinfo[1 << k].owner = 1 << i;
+	  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, deepspace style.  We use a 125k^2 grid with
+ * lots of planets for lots of fun.  We're assuming a no-warp environment.
+ */
+
+void
+gen_galaxy_7()
+{
+  int t;
+
+  GWIDTH = 125000;
+  NUMPLANETS = 60 - WORMPAIRS * 2;
+  configvals->warpdrive = 0;
+
+  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, 4,
+		    (int) TEAMBORD, (int) TEAMMIN, (int) TEAMMAX,
+		    (struct planet *) 0, 0)
+      && 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 */
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/planets.c	Sat Dec 06 04:37:04 1997 +0000
@@ -0,0 +1,1497 @@
+/*--------------------------------------------------------------------------
+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
+--------------------------------------------------------------------------*/
+
+
+#define PLANETS 1
+#define GRID 0			/* for space grid */
+
+#include "config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <setjmp.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <unistd.h>
+
+#include "struct.h"
+#include "data.h"
+#include "daemonII.h"
+#include "planets.h"
+#include "misc.h"
+#include "conquer.h"
+#include "player.h"
+#include "grid.h"
+#include "shmem.h"
+#include "terrain.h"
+
+
+/* define this if you want the experimental dragging-into-star-counts mod */
+#define GIVESTARKILLS
+
+#define	friendly(fred, bart) \
+	(!(fred->p_team & (bart->p_swar|bart->p_hostile)) && \
+	 !(bart->p_team & (fred->p_swar|fred->p_hostile)))
+
+
+/* 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 */
+
+/* other defines */
+#define UCVISIBLE 40000		/* dist for uncloaked visibility */
+#define CVISMIN 12000		/* cloakers always visible distance */
+#define CVISSPEED 2000		/* cloak dist added per warp point */
+#define CVISIBLE 25000		/* dist for cloaked visibility */
+#define PLFIREDIST 1500		/* distance planets fire at players */
+#define PLVISDIST 5000		/* dist planets sense enemy players */
+#define REVOLT 200		/* chance out of 1000 of revolt start */
+#define STARTREV 8		/* for revolt timer */
+/*-------------------------------------------------------------------------*/
+
+
+
+
+
+
+/*-----------------------------MODULE VARIABLES----------------------------*/
+
+/* the list of all possible planet names */
+char *pnames[] =
+{
+  /* Federation planets */
+  "Rigel", "Canopus", "Beta Crucis", "Organia", "Deneb",
+  "Ceti Alpha V", "Altair", "Vega", "Alpha Centauri",
+  /* Romulan worlds */
+  "Eridani", "Aldeberan", "Regulus", "Capella", "Tauri",
+  "Draconis", "Sirius", "Indi", "Hydrae",
+  /* Klingon worlds */
+  "Pleiades V", "Andromeda", "Lalande", "Pollux", "Lyrae",
+  "Scorpii", "Mira", "Cygni", "Castor",
+  /* Orion worlds */
+  "Cassiopia", "El Nath", "Spica", "Procyon", "Polaris",
+  "Arcturus", "Ursae Majoris", "Herculis", "Antares",
+
+  /* new worlds */
+  "Planet 10", "Bezier", "Sequent", "Ophiuchi", "Lacaille",
+  "Luyten", "Pavonis", "Wolf 424", "Ross 882", "Cephei",
+  "Kruger", "Groombridge", "Maanen's Star", "Heinlein",
+  "Pixel", "Lazarus", "Mycroft", "Asimov", "Varley",
+  "Clarke's Star", "Ren", "Stimpy", "Foo", "Jolt Cola",
+  "Kelly Bundy", "Tyrell", "Roy", "Deckard", "Vangelis",
+  "Orpheus", "Xanth", "Tatooine", "Ludicrous", "Ogg",
+  "Scum", "Twink", "Chiapucci", "Bugno", "Hampsten", "Fignon",
+  "Paradise", "Azriel", "Gargamel", "Smurf Village",
+  "Praxis", "Acherner", "Arrakis", "Caladan", "Giedi Prime",
+  "Clue", "Paulina", "Sith", "Salusa", "Ahrain", "Cerranos",
+  "Darkurthe", "Dagobah", "Phaze", "Chatsubu", "Lemond",
+  "Bronco", "Vulcan", "Eden", "Klein", "Merckx", "Tarot",
+  "Mottet", "Roche", "Doorstop", "Shaedron", "Fondriest",
+
+  /* Bob's fave worlds */
+  "Wayne's World", "DanjerHaus", "Anvil", /* B-52s */ "Claire",
+  "Planet Reebok", "Sony Corp.", "SEGA!", "McWorld",
+  "Tokyo", "New York", "D.C.", "Atlanta",	/* places I've never been */
+   /* Tony */ "Levin",
+  "Planet Woogie", "Nancy", "Wilson",	/* real people */
+  "Beavis", "Butthead",
+  "Memolo",			/* Matt Memolo was murdered in Miami in July
+				 * of '93.  He was a really swell guy. "...he
+				 * would go far out of his way to give you
+				 * the shirt off his back." - ajc */
+  /* names from the T.V. shows */
+  "New Berlin",
+  /*
+   * "Bejor", "Cardassia" I'm not including these till I can spell them - RF
+   */
+
+  /* Mike's fave worlds */
+  "Melmac", "Order", "Yosemite", "New Chicago", "Ceptus", "Ork",
+  "Levi 501", "Toughskin", "Wonka",
+
+  /* book names */
+  "Terminus", "Magrathea", "Trantor", "Synnax", "Coruscant",
+
+  /* Moons, names, etc. */
+  "Io ", "Titan", "Europa", "Ganymede", "Charon",
+  "Tholia", "Gor", "Kzin", "Aerth",
+  "Proxima", "Cellust", "Calamar", "Icarus",
+  "New Prague",
+
+  /* How about the solar system? */
+  "Mercury", "Venus", "Mars", "Jupiter", "Saturn", "Neptune",
+  "Uranus", "Pluto",		/* are Neptune and Uranus in order? */
+
+#if 0
+  /* Player's names */
+  "Claypigeon", "Maxout", "Fungus", "Lynx",
+  "Bubbles", "KnightRaven", "Bolo", "Vladimir",
+  "Gajah Mada", "Trippix", "Shrew", "Bob Dobbs", "Wibble",
+  "Rogue"
+#endif
+};
+
+#define MAXNAMES (sizeof(pnames)/sizeof(char *))	/* # of planet names */
+
+char *homenames[] =		/* names of the race's home worlds */
+{
+  " ", "Earth", "Romulus", " ", "Klingus", " ", " ", " ",
+  "Orion"
+};
+
+
+/*
+ * This table is used to turn the four bits of resources flags into a three
+ * bit number.  The shipyard and the repair are ORed together.  All the non
+ * resource bits need to be masked off with PLRESMASK before this table is
+ * used
+ */
+int restores[16] = {0, 1, 2, 3, 4, 5, 6, 7, 1, 1, 3, 3, 5, 5, 7, 7};
+
+
+/*
+ * This is a matrix that determines the chance a planet has of popping.  The
+ * chance is expressed as a chance out of 100.  The matrix is accessed with
+ * the planet's atmosphere type and the resource bits after they have been
+ * converted to 3 bits with the table above.
+ */
+int popchance[4][8] = {
+  /*
+   * 000   00Z   0f0   0fZ   a00   a0Z   af0   afZ--the resources flags,
+   * Z=r|s
+   */
+  {2, 3, 2, 2, 5, 7, 4, 8},	/* poison */
+  {3, 5, 2, 4, 9, 11, 7, 12},	/* atmos #3 */
+  {5, 7, 4, 6, 12, 14, 10, 15},	/* atmos #2 */
+  {8, 12, 7, 10, 20, 24, 18, 23}/* atmos #1 */
+};
+
+
+/*
+ * This is a matrix that determines the multiplier for popping. When popping
+ * the armies on a planet will be multiplied by this multiplier to get the
+ * number of extra armies that grow.  A negative number indicates negative
+ * growth.
+ */
+float popmult[4][8] = {
+  /* 000      00Z    0f0    0fZ    a00    a0Z    af0   afZ  */
+  {-0.08, 0.00, -0.10, -0.03, 0.00, 0.05, -0.05, 0.05},	/* poison */
+  {0.03, 0.05, 0.02, 0.04, 0.06, 0.07, 0.06, 0.07},	/* atmos #3 */
+  {0.05, 0.07, 0.05, 0.06, 0.10, 0.11, 0.08, 0.10},	/* atmos #2 */
+  {0.09, 0.12, 0.08, 0.10, 0.17, 0.19, 0.15, 0.18}	/* atmos #1 */
+};
+
+
+/*
+ * This is a matrix that determines the maximum army capacity of a planet.
+ * Once this capacity is reached, no other armies can grow there.
+ */
+float popcap[4][8] = {
+  /*
+   * 000   00Z   0f0   0fZ   a00   a0Z   af0    afZ--the resources flags,
+   * Z=r|s
+   */
+  {5, 10, 7, 10, 15, 15, 10, 18},	/* poison */
+  {9, 14, 11, 14, 20, 20, 14, 22},	/* atmos #3 */
+  {12, 18, 15, 18, 25, 25, 19, 27},	/* atmos #2 */
+  {15, 22, 18, 25, 40, 35, 27, 40}	/* atmos #1 */
+};
+
+/*-------------------------------------------------------------------------*/
+
+
+
+
+
+
+
+
+#ifdef LEAGUE_SUPPORT
+extern void tlog_res();
+extern void tlog_bomb();
+extern void tlog_bres();
+extern void tlog_plankill();
+extern void tlog_revolt();
+extern void tlog_pop();
+#else
+#define tlog_res(a,b)
+#define tlog_bomb(a,b,c)
+#define tlog_bres(a,b,c)
+#define tlog_plankill(a,b,c)
+#define tlog_revolt(a)
+#define tlog_pop(a,b)
+#endif
+extern void scout_planet();
+extern int inflict_damage();
+extern void killmess();
+extern int enemy_admiral();
+extern off_t lseek();
+extern int write();
+
+/*------------------------------INTERNAL FUNCTIONS-------------------------*/
+
+void fill_planets();
+
+
+#ifndef NO_QSORT
+/* used by the qsort() in sortnames() below */
+static int
+comp_pl_name(a, b)
+  void *a, *b;
+{
+  return strcasecmp(((struct planet *) a)->pl_name,
+		    ((struct planet *) b)->pl_name);
+}
+#endif
+
+/*--------------------------------SORTNAMES---------------------------------*/
+/*
+ * This function sorts the planet into a alphabeticly increasing list.  It
+ * operates on the global planets structure.  This uses a simple bubble sort
+ * because I was too lazy to write anything more sophisticated.
+ */
+
+/*
+ * Bubble sorts suck.  Let's use the qsort library function instead, if
+ * available (HK)
+ */
+
+void
+sortnames()
+{
+#ifdef NO_QSORT
+  struct planet ptemp;		/* temporary space to hold planet */
+  int exchange;			/* flag for exchange made in pass */
+  int i;			/* looping var */
+  int t;			/* temp var */
+
+  exchange = 1;			/* no exchanges done yet */
+  while (exchange)
+  {				/* do until no exchanges */
+    exchange = 0;		/* no exchanges for this pass yet */
+    for (i = 0; i < NUMPLANETS - 1; i++)
+    {				/* go through list */
+      if (strcmp(planets[i].pl_name, planets[i + 1].pl_name) > 0)
+      {
+	t = planets[i].pl_no;	/* exchange planet numbers */
+	planets[i].pl_no = planets[i + 1].pl_no;
+	planets[i + 1].pl_no = t;
+	memcpy(&ptemp, &(planets[i]), sizeof(struct planet));
+	memcpy(&(planets[i]), &(planets[i + 1]), sizeof(struct planet));
+	memcpy(&(planets[i + 1]), &ptemp, sizeof(struct planet));
+	exchange++;		/* we made an exchange this pass */
+      }
+    }
+  }
+#else
+  int i;
+
+  qsort(planets, NUMPLANETS, sizeof(struct planet), comp_pl_name);
+  for (i = 0; i < NUMPLANETS; i++)	/* go through the planets */
+    planets[i].pl_no = i;	/* and fix their pl_no value */
+#endif
+}
+
+
+/*--------------------------------INITPLANETS-------------------------------*/
+/*
+ * This function generates the names and initializes the fields in the
+ * planets structure.  The planet names need to be sorted afterthe planets
+ * have been placed.
+ */
+
+void
+initplanets()
+{
+  int i, j;			/* looping vars */
+  int nused[MAXNAMES];		/* to mark which names are used */
+
+  for (i = 0; i < MAXNAMES; i++)/* go through all possible names */
+    nused[i] = 0;		/* mark name is not used yet */
+  for (i = 0; i < NUMPLANETS; i++)
+  {
+    planets[i].pl_no = i;	/* set planet number */
+    planets[i].pl_flags = PLPARADISE;	/* Paradise planet */
+    planets[i].pl_owner = NOBODY;	/* no owner yet */
+    planets[i].pl_x = 0;	/* just to intialize x and y */
+    planets[i].pl_y = 0;
+    j = lrand48() % MAXNAMES;	/* get a random name */
+    do
+    {				/* do until unused name found */
+      j = (j + 1) % MAXNAMES;	/* go on to next name in list */
+    } while (nused[j]);		/* until unused name found */
+    nused[j] = 1;		/* mark name as used */
+    strcpy(planets[i].pl_name, pnames[j]);	/* copy into planet struct */
+    planets[i].pl_namelen = strlen(pnames[j]);	/* set name's length */
+#if 1
+    planets[i].pl_hostile = 0;	/* planet doesn't hate anyone yet */
+#else
+    planets[i].pl_torbit = 0;	/* no teams orbiting */
+#endif
+    planets[i].pl_tshiprepair = 0;	/* zero the repair growth timer */
+    planets[i].pl_tagri = 0;	/* zero the agri growth timer */
+    planets[i].pl_tfuel = 0;	/* zero the fuel growth timer */
+    planets[i].pl_armies = 0;	/* no armies yet */
+    planets[i].pl_warning = 0;	/* no warning being counted down for */
+    planets[i].pl_system = 0;	/* not in a system yet */
+    planets[i].pl_hinfo = NOBODY;	/* no race has info on planet */
+    for (j = 0; j < MAXTEAM + 1; j++)
+    {				/* go through four races */
+      planets[i].pl_tinfo[j].owner = NOBODY;	/* do not know who owns it */
+      planets[i].pl_tinfo[j].armies = 0;	/* no armies on planet */
+      planets[i].pl_tinfo[j].flags = PLPARADISE;	/* know nothing about
+							 * flags */
+      planets[i].pl_tinfo[j].timestamp = 0;	/* set the timestamp */
+    }
+    planets[i].pl_trevolt = 0;	/* revolt timer not counting down */
+#if GRID
+    planets[i].pl_next = NULL;	/* set fields related to space grid */
+    planets[i].pl_previous = NULL;
+    planets[i].pl_gridnum = 0;
+#endif
+  }
+}
+
+
+
+
+/*-------------------------------GROWPLANETS------------------------------*/
+/*
+ * This function grows resources on planets.  It goes through all planets and
+ * updates the growth timers and checks for growth.  Independent planets do
+ * not grow.  This function also checks to see if any player in a starbase is
+ * orbiting a planet and adjusts the planet's growth rate if so.
+ */
+
+void
+growplanets()
+{
+  int i;			/* looping var */
+  struct planet *p;		/* to point within planets */
+  int add;			/* number to add to timers */
+
+  if (!status->tourn)
+    return;
+
+  if (!configvals->resource_bombing)
+    return;
+
+  for (i = 0; i < MAXPLAYER; i++)
+  {				/* go through all players */
+    struct player *py = &players[i];	/* and look for orbiting */
+    if ((py->p_status != PALIVE) ||	/* starbases */
+	(py->p_ship.s_type != STARBASE) ||
+	!(py->p_flags & PFORBIT))
+      continue;
+    p = &planets[py->p_planet];	/* found one, get planet */
+    p->pl_tfuel += 20;		/* give growth rate a boost */
+    p->pl_tagri += 30;		/* NOTE: change these if PLG consts */
+    p->pl_tshiprepair += 50;	/* change */
+  }
+  p = &planets[0];		/* start with first planet */
+  for (i = 0; i < NUMPLANETS; i++, p++)
+  {				/* through all planets */
+    if (p->pl_owner == NOBODY)	/* if independent then */
+      continue;			/* no growth */
+    add = p->pl_armies / 2;	/* rate based on armies */
+    p->pl_tfuel += add;		/* add to fuel timer */
+    p->pl_tfuel = (p->pl_tfuel > PLGFUEL) ? PLGFUEL : p->pl_tfuel;
+    if ((!(p->pl_flags & PLFUEL))	/* if no fuel */
+	&& (p->pl_flags & PLDILYTH)	/* and dilythium deposits */
+	&& (p->pl_tfuel >= PLGFUEL))
+    {				/* and timer high enough */
+      p->pl_flags |= (PLFUEL | PLREDRAW);	/* create fuel depot */
+      p->pl_tinfo[p->pl_owner].flags = p->pl_flags;
+      p->pl_tinfo[p->pl_owner].timestamp = status->clock;
+      tlog_res(p, "FUEL");
+    }
+    p->pl_tagri += add;		/* add to agri timer */
+    p->pl_tagri = (p->pl_tagri > PLGAGRI) ? PLGAGRI : p->pl_tagri;
+    if ((!(p->pl_flags & PLAGRI))	/* if no agri on planet */
+	&& (p->pl_flags & PLARABLE)	/* and arable */
+	&& (p->pl_tagri >= PLGAGRI))
+    {				/* and timer high enough */
+      p->pl_flags |= (PLAGRI | PLREDRAW);	/* create agri planet */
+      p->pl_tinfo[p->pl_owner].flags = p->pl_flags;
+      p->pl_tinfo[p->pl_owner].timestamp = status->clock;
+      tlog_res(p, "AGRI");
+    }
+    p->pl_tshiprepair += add;	/* add to ship/repair timer */
+    if ((!(p->pl_flags & PLREPAIR))	/* if not repair */
+	&& (p->pl_flags & PLMETAL)	/* and metal deposits */
+	&& (p->pl_tshiprepair >= PLGREPAIR))
+    {				/* and timer high enough */
+      p->pl_flags |= (PLREPAIR | PLREDRAW);	/* create repair station */
+      p->pl_tinfo[p->pl_owner].flags = p->pl_flags;
+      p->pl_tinfo[p->pl_owner].timestamp = status->clock;
+      tlog_res(p, "REPAIR");
+    }
+    p->pl_tshiprepair = (p->pl_tshiprepair > PLGSHIP) ? PLGSHIP :
+      p->pl_tshiprepair;	/* clamp value to max */
+    if ((!(p->pl_flags & PLSHIPYARD))	/* if not repair */
+	&& (p->pl_flags & PLMETAL)	/* and metal deposits */
+	&& (p->pl_tshiprepair >= PLGSHIP))
+    {				/* and timer high enough */
+      p->pl_flags |= (PLSHIPYARD | PLREDRAW);	/* create repair station */
+      p->pl_tinfo[p->pl_owner].flags = p->pl_flags;
+      p->pl_tinfo[p->pl_owner].timestamp = status->clock;
+      tlog_res(p, "SHIPYARD");
+    }
+  }
+}
+
+
+
+
+/*----------------------------------PVISIBLE------------------------------*/
+/*
+ * This function goes through the players and checks the other playes to see
+ * if an enemy is close enough to see him.  THIS FUNCTION SHOULD EVENTUALLY
+ * USE THE SPACE GRID.
+ */
+
+void
+pvisible()
+{
+  struct player *p;		/* to point to a player */
+  int i;			/* looping var */
+  int h;			/* looping var */
+  struct player *pl2;		/* to point to other players */
+  int dx, dy;			/* delta coords */
+  int dist;			/* to hold distance */
+
+  for (i = 0, p = &players[0]; i < MAXPLAYER; i++, p++)
+    p->p_flags &= ~PFSEEN;	/* clear all players' the seen flags */
+  for (i = 0, p = &players[i]; i < MAXPLAYER - 1; i++, p++)
+  {
+    if (p->p_status != PFREE &&	/* only do if player alive */
+	p->p_status != POBSERVE)
+    {				/* observers can't augment team scanning */
+      for (h = i + 1, pl2 = &players[h]; h < MAXPLAYER; h++, pl2++)
+      {
+	if ((pl2->p_status == PFREE) || (pl2->p_status == POBSERVE)
+	    || (pl2->p_flags & PFROBOT)	/* if not alive or robot or */
+	    || (pl2->p_team == p->p_team))	/* same team then continue */
+	  continue;
+	dx = ABS(pl2->p_x - p->p_x);	/* calc delta coords */
+	dy = ABS(pl2->p_y - p->p_y);
+	if ((dx > UCVISIBLE) || (dy > UCVISIBLE))	/* if obviously too far
+							 * away */
+	  continue;		/* then don't bother further */
+	dist = ihypot(dx, dy);
+	if (dist > UCVISIBLE)	/* out of range */
+	  continue;		/* on to next ship */
+	if ((dist < CVISMIN + CVISSPEED * pl2->p_speed) ||
+	    (!(pl2->p_flags & PFCLOAK)))
+	  pl2->p_flags |= PFSEEN;	/* if close then visible */
+	if ((dist < CVISMIN + CVISSPEED * p->p_speed) ||
+	    (!(p->p_flags & PFCLOAK)))
+	  p->p_flags |= PFSEEN;	/* second player */
+      }
+    }
+  }
+}
+
+
+
+void
+blast_resource(p, l, res, dival)
+  struct player *p;
+  struct planet *l;
+  int res;
+  double dival;
+{
+  if (status->tourn)
+  {
+    p->p_stats.st_di += dival;
+    p->p_stats.st_tresbomb++;
+    p->p_resbomb++;
+    status->resbomb++;
+  }
+  l->pl_flags &= ~res;
+  l->pl_tinfo[l->pl_owner].flags = l->pl_flags;
+  l->pl_tinfo[l->pl_owner].timestamp = status->clock;
+  l->pl_tinfo[p->p_team].flags = l->pl_flags;
+  l->pl_tinfo[p->p_team].timestamp = status->clock;
+  l->pl_flags |= PLREDRAW;	/* slate for redraw */
+}
+
+/*-----------------------------------PBOMB---------------------------------*/
+/*
+ * This function goes through the players and does the bombing if any player
+ * is bombing.  This will knock resources off of planets.  If a player is
+ * bombing a planet that another team owns, then that team will see the
+ * player by having the PFSEEN flag set.
+ */
+
+void
+pbomb()
+{
+  struct player *p;		/* to point to a player */
+  int i;			/* looping var */
+  struct planet *l;		/* to point to planet being bombed */
+  char buf[90];			/* to sprintf messages into */
+  char buf1[80];
+  int rnd;			/* to hold armies to knock off */
+
+  for (i = 0, p = &players[0]; i < MAXPLAYER; i++, p++)
+  {				/* go through playrs */
+    if ((p->p_status == PALIVE)	/* only do if player is alive */
+	&& (p->p_flags & PFORBIT)	/* and he is orbiting */
+	&& (p->p_flags & PFBOMB))
+    {				/* and he is bombing */
+
+      l = &planets[p->p_planet];/* get planet being bombed */
+
+      if ((!((p->p_swar | p->p_hostile) & l->pl_owner))
+	  && (l->pl_owner != NOBODY))
+      {
+	/* if he's non-hostile, quit bombing */
+	p->p_flags &= ~PFBOMB;
+	continue;
+      }
+      if ((l->pl_warning <= 0) && (l->pl_owner != NOBODY))
+      {				/* warning? */
+	l->pl_warning = 50 / PLFIGHTFUSE;	/* reset warning timer */
+	sprintf(buf, "We are being attacked by %s %s who is %d%% damaged.",
+		p->p_name, twoletters(p),
+		(100 * p->p_damage) / (p->p_ship.s_maxdamage));
+	sprintf(buf1, "%-3s->%-3s", l->pl_name, teams[l->pl_owner].shortname);
+	pmessage(buf, l->pl_owner, MTEAM | MBOMB, buf1);	/* send message */
+
+	/* CRD feature: shipyard guardians - MAK,  2-Jun-93 */
+	if ((l->pl_flags & PLSHIPYARD) && (!status->tourn))
+	{
+	  rescue(l->pl_owner, 0, l->pl_no);
+	}
+      }
+      p->p_swar |= l->pl_owner;	/* set player at war w/ owner */
+      rnd = (lrand48() % 50) + p->p_ship.s_bomb;	/* pick random number */
+      rnd = (int) ((float) rnd / 33.0 + 0.5);	/* calc armies bombed */
+      if (rnd <= 0)
+	continue;		/* can't bomb negative armies */
+      if (l->pl_armies > 4)
+      {				/* if armies to bomb then */
+	l->pl_armies -= rnd;	/* kill off armies */
+	tlog_bomb(l, p, rnd);
+	l->pl_armies = (l->pl_armies < 1) ? 1 : l->pl_armies;
+	l->pl_tinfo[l->pl_owner].armies = l->pl_armies;
+	l->pl_tinfo[l->pl_owner].timestamp = status->clock;
+	l->pl_tinfo[p->p_team].armies = l->pl_armies;
+	l->pl_tinfo[p->p_team].timestamp = status->clock;
+	if (l->pl_armies < 5)	/* if planet needs to be redrawn */
+	  l->pl_flags |= PLREDRAW;	/* schedule planet for redraw */
+	if (l->pl_owner != NOBODY)
+	{
+	  credit_armiesbombed(p, rnd, l);
+	}
+      }				/* now do the resource bombing */
+      if ((l->pl_armies > 4) ||
+	  (!configvals->resource_bombing))	/* no bombing resources if
+						 * armies */
+	continue;		/* on planet or in bronco-mode */
+#if defined(AEDILE) || defined(SLOW_BOMB)
+      l->pl_tfuel -= rnd * 5;	/* knock fuel timer down */
+#else
+      l->pl_tfuel -= rnd * 8;	/* knock fuel timer down */
+#endif
+      l->pl_tfuel = (l->pl_tfuel < 0) ? 0 : l->pl_tfuel;
+      if ((l->pl_tfuel == 0) && (l->pl_flags & PLFUEL))
+      {
+	blast_resource(p, l, PLFUEL, 0.10);
+	tlog_bres(l, p, "FUEL");
+      }
+#if defined(AEDILE) || defined(SLOW_BOMB)
+      l->pl_tagri -= rnd * 4;	/* attack the agri timer */
+#else
+      l->pl_tagri -= rnd * 6;	/* attack the agri timer */
+#endif
+      l->pl_tagri = (l->pl_tagri < 0) ? 0 : l->pl_tagri;
+      if ((l->pl_tagri == 0) && (l->pl_flags & PLAGRI))
+      {
+	blast_resource(p, l, PLAGRI, 0.25);
+	tlog_bres(l, p, "AGRI");
+      }
+#if defined(AEDILE) || defined(SLOW_BOMB)
+      l->pl_tshiprepair -= rnd * 5;	/* knock ship/repr down */
+#else
+      l->pl_tshiprepair -= rnd * 8;	/* knock ship/repr down */
+#endif
+      l->pl_tshiprepair = (l->pl_tshiprepair < 0) ? 0 :
+	l->pl_tshiprepair;
+      if ((l->pl_tshiprepair < PLGREPAIR) && (l->pl_flags & PLSHIPYARD))
+      {
+	blast_resource(p, l, PLSHIPYARD, 0.10);
+	tlog_bres(l, p, "SHIPYARD");
+      }
+      if ((l->pl_tshiprepair == 0) && (l->pl_flags & PLREPAIR))
+      {
+	blast_resource(p, l, PLREPAIR, 0.20);
+	tlog_bres(l, p, "REPAIR");
+      }
+    }
+  }
+}
+
+
+
+
+/*---------------------------------PFIRE-----------------------------------*/
+/*
+ * This function goes through the planets and sees if any enemy players are
+ * close enough to be fired upon by the planet.  It also checks to see if
+ * players are close enough to the planet so that the planet should be
+ * redrawn. Enemy planets will 'see' players that are very close to them.
+ * THIS FUNCTION SHOULD EVENTUALLY USE THE SPACE GRID.
+ */
+
+void
+pfire()
+{
+  struct player *p;		/* to point to a player */
+  int i, j;			/* looping vars */
+  struct planet *l;		/* to point to the planets */
+  int dx, dy;			/* to hold delta coords */
+  int dist;			/* to hold distance */
+  int dam;			/* to hold damage */
+  int boost;			/* for warp zones, total boost [BDyess] */
+
+  for (j = 0, p = &players[0]; j < MAXPLAYER; j++, p++)
+  {
+    if (p->p_status != PALIVE)
+      continue;
+    boost = 0;			/* default no bonus or penalty [BDyess] */
+    for (i = 0, l = &planets[0]; i < NUMPLANETS; i++, l++)
+    {
+      if ((p->p_team == l->pl_owner) && (PL_TYPE(*l) != PLSTAR)
+	  && !configvals->warpzone)
+	continue;		/* no, then continue */
+      dx = ABS(l->pl_x - p->p_x);	/* calc delta coorda between */
+      dy = ABS(l->pl_y - p->p_y);	/* planet and player */
+      dist = ihypot(dx, dy);
+
+      if (dist < configvals->warpzone)
+      {
+	/* within warp boost/block range [BDyess] */
+	if (p->p_team == l->pl_owner)
+	  boost += configvals->warpzone - dist;
+	else if (l->pl_owner != NOBODY &&
+		 ((p->p_swar | p->p_hostile) & l->pl_owner))
+	  boost -= configvals->warpzone - dist;
+      }
+
+      if (dx < 6 * PLFIREDIST && dy < 6 * PLFIREDIST)	/* redraw planet */
+	l->pl_flags |= PLREDRAW;/* if player is very close */
+
+      if (dist <= p->p_ship.s_scanrange)
+      {				/* check for scanners */
+	scout_planet(p->p_no, l->pl_no);
+#if 0
+	handled in scout_planet now.
+	    l->pl_hinfo |= p->p_team;
+	l->pl_tinfo[p->p_team].armies = l->pl_armies;
+	l->pl_tinfo[p->p_team].flags = l->pl_flags;
+	l->pl_tinfo[p->p_team].owner = l->pl_owner;
+	l->pl_tinfo[p->p_team].timestamp = status->clock;
+#endif
+      }
+
+      if (dist > PLVISDIST)
+	continue;
+      if ((dist < PLVISDIST) && (l->pl_owner != NOBODY)	/* enemy planet */
+	  && ((p->p_swar | p->p_hostile) & l->pl_owner))	/* see players */
+	p->p_flags |= PFSEEN;	/* let team see enemy */
+      if ((dist > PFIREDIST) ||
+	  ((dist > PFIREDIST / 2) &&
+	   (PL_TYPE(*l) == PLWHOLE)))	/* if not within range */
+	continue;		/* go on to next playert */
+      if (((p->p_swar | p->p_hostile) & l->pl_owner)
+	  || ((l->pl_owner == NOBODY)
+#if 1
+	      && (l->pl_hostile & p->p_team)
+#else
+	      && (l->pl_torbit & (p->p_team << 4))
+#endif
+	      && (l->pl_armies != 0))
+	  || (PL_TYPE(*l) == PLWHOLE) || (PL_TYPE(*l) == PLSTAR))
+      {
+	dam = l->pl_armies / 7 + 2;	/* calc the damage */
+	if (PL_TYPE(*l) == PLWHOLE)
+	{			/* if a wormhole... */
+	  /* ...place outside the new wormhole's radius. */
+	  if ((wh_effect[SS_WARP] && !(p->p_flags & PFWARP))
+	      || (!wh_effect[SS_WARP]))
+	  {
+	    p->p_x = l->pl_armies +
+	      (((PLFIREDIST / 2) + 50) * Cos[p->p_dir]);
+	    p->p_y = l->pl_radius +
+	      (((PLFIREDIST / 2) + 50) * Sin[p->p_dir]);
+	  }
+	  if ((p->p_speed > (p->p_ship.s_imp.maxspeed / 2)) &&
+	      (wh_effect[SS_IMPULSE]))
+	  {
+	    dam = ((p->p_ship.s_mass / 100) * (p->p_speed -
+					     p->p_ship.s_imp.maxspeed / 2));
+	  }
+	  else
+	    dam = 0;
+
+	}
+	else if (PL_TYPE(*l) == PLSTAR)	/* if planet is a star */
+	  dam = 150;		/* do massive damage */
+	/*
+	 * this needs to be reworked and most of it jammed into
+	 * inflict_damage
+	 */
+	p->p_whodead = i;	/* which planet is shooting */
+	if (dam > 0 && inflict_damage(0, 0, p, dam, KPLANET))
+	{
+	  struct player *killer = 0;
+	  p->p_whydead = KPLANET;	/* set killed by a planet */
+	  if (PL_TYPE(*l) == PLSTAR)
+	  {			/* killed by star? */
+#ifdef GIVESTARKILLS
+	    int pln;
+	    for (pln = 0, killer = &players[0];
+		 pln < MAXPLAYER;
+		 pln++, killer++)
+	    {
+	      if (killer->p_status != PALIVE)
+		continue;
+	      if (!friendly(killer, p) && killer->p_tractor == p->p_no
+		  && killer->p_flags & (PFTRACT | PFPRESS))
+	      {
+
+		killer->p_kills += 1 + (p->p_armies + p->p_kills) / 10;
+		killerstats(killer->p_no, p);
+		checkmaxkills(killer->p_no);
+		break;
+	      }
+	    }
+	    if (pln >= MAXPLAYER)
+	      killer = 0;
+#endif
+	  }
+	  killmess(p, killer);
+	  tlog_plankill(p, l, killer);
+	}
+      }
+    }
+    /* found the boost for this player, make adjustments if in warp [BDyess] */
+    if (configvals->warpzone && p->p_flags & PFWARP)
+    {
+      if (boost == 0 && p->p_zone > 0)
+      {				/* did get warp bonus, lost it */
+	if (p->p_desspeed > p->p_ship.s_warp.maxspeed)
+	  p->p_desspeed = p->p_ship.s_warp.maxspeed;
+      }
+      else if (boost < 0 && p->p_zone >= 0)
+      {				/* warp no longer allowed */
+	p->p_desspeed = p->p_ship.s_imp.maxspeed;
+	if (!configvals->warpdecel)
+	  p->p_flags &= ~PFWARP;
+      }
+    }
+    p->p_zone = boost;
+  }
+}
+
+
+
+
+/*---------------------------------REVOLT---------------------------------*/
+/*
+ * This function does the revolt of a planet.  It updates the revolt timer
+ * and prints the messages that warn the team.
+ */
+
+void
+revolt(l)
+  struct planet *l;		/* the planet to check */
+{
+  if (!configvals->revolts)
+    return;
+
+  if (l->pl_trevolt > 0)
+  {				/* revolt timer running? */
+    char buf[80];		/* to sprintf into */
+
+    {
+      int i;
+      for (i = 0; i < MAXPLAYER; i++)
+      {
+	if (players[i].p_status == PALIVE
+	    && (players[i].p_flags & (PFORBIT | PFDOCK)) == PFORBIT
+	    && players[i].p_planet == l->pl_no
+	    && players[i].p_team == l->pl_owner)
+	  return;		/* orbiting ship delays revolt */
+      }
+    }
+
+    l->pl_trevolt--;		/* dec the timer */
+    if ((l->pl_trevolt == 0) && (l->pl_armies > 2))
+    {
+      l->pl_trevolt = 0;	/* turn off revolt timer */
+      sprintf(buf, "The revolution on %s has been put down.",
+	      l->pl_name);	/* get message to display */
+      pmessage(buf, l->pl_owner, MTEAM | MCONQ, "PREFECT->");
+    }
+    else if ((l->pl_trevolt == 0) && (l->pl_armies == 2))
+    {
+      l->pl_trevolt = STARTREV;	/* more time til last army */
+      l->pl_armies--;		/* kill one army */
+      l->pl_tinfo[l->pl_owner].armies = l->pl_armies;
+      l->pl_tinfo[l->pl_owner].timestamp = status->clock;
+      sprintf(buf, "We cannot hold out much longer on %s",
+	      l->pl_name);	/* get message to display */
+      pmessage(buf, l->pl_owner, MTEAM | MCONQ, "PREFECT->");
+    }
+    else if (l->pl_trevolt == 0)
+    {
+      l->pl_trevolt = 0;	/* revolution succeeded */
+      sprintf(buf, "The planet %s has been lost to revolutionaries",
+	      l->pl_name);	/* get message to display */
+      pmessage(buf, l->pl_owner, MTEAM | MCONQ, "PREFECT->");
+
+      tlog_revolt(l);
+
+      l->pl_tinfo[l->pl_owner].timestamp = status->clock;
+      l->pl_tinfo[l->pl_owner].owner = NOBODY;
+      l->pl_owner = NOBODY;
+      l->pl_flags |= PLREDRAW;	/* slate for redraw */
+      checkwin(enemy_admiral(-1));	/* check for game end */
+
+    }
+  }
+  else
+  {				/* no revolt timer--check for start */
+    if ((l->pl_armies <= 2) && (!(l->pl_armies == 0))
+	&& ((lrand48() % 1000) <= REVOLT))
+    {
+      char buf[80];		/* to sprintf message into */
+
+      sprintf(buf, "There is civil unrest on %s", l->pl_name);
+      pmessage(buf, l->pl_owner, MTEAM | MCONQ, "PREFECT>>");
+      l->pl_trevolt = STARTREV;	/* time before revolution */
+    }
+  }
+}
+
+void 
+check_revolt()
+{
+  static int planetlist[MAXPLANETS];
+  static int count = 0;
+  int idx;
+  struct planet *l;
+
+  if (!status->tourn)
+    return;
+
+  if (count < 1)
+    fill_planets(planetlist, &count, -1);
+
+  idx = planetlist[--count];
+  l = &planets[idx];
+
+  if (l->pl_armies > 0 && l->pl_owner != NOBODY)
+    revolt(l);
+}
+
+/*-------------------------------------------------------------------------*/
+
+
+
+
+
+
+/* struct planet *stars[NUMPLANETS + 1]; */
+
+static void
+build_stars_array()
+{
+  int i;
+  struct planet *pl;
+
+  for (i = 0; i < NUMPLANETS; i++)
+  {
+    pl = &planets[i];
+    if (PL_TYPE(*pl) == PLSTAR)
+      stars[pl->pl_system] = i;
+  }
+}
+
+/*------------------------------VISIBLE FUNCTIONS-------------------------*/
+
+/*-------------------------------GEN_PLANETS-------------------------------*/
+/*
+ * This function generates a number of random planets.  The planets are
+ * arranged in systems and are also placed so that they are not too close to
+ * any other planets.  The races are then given home planets.
+ */
+
+void
+gen_planets()
+{
+  int i;
+  struct planet *pl;
+
+  status->clock = 0;		/* reset the timestamp clock */
+
+  switch (configvals->galaxygenerator)
+  {
+   case 2:
+    gen_galaxy_2();		/* Bob Forsman's compact galaxy generator */
+    break;
+   case 3:
+    gen_galaxy_3();		/* Heath's better race placement galaxy
+				 * generator */
+    break;
+   case 4:
+    gen_galaxy_4();		/* Mike's Bronco emulator */
+    break;
+   case 5:
+    gen_galaxy_5();		/* Mike's small-galaxy generator */
+    break;
+   case 6:
+    gen_galaxy_6();		/* Brandon's hack on Heath's to give 2 */
+    break;			/* systems to each race */
+   case 7:
+    gen_galaxy_7();		/* Eric Dormans deepspace galaxy gen, rooted
+				 * in galaxy gen 6. */
+    break;
+   case 1:
+   default:
+    gen_galaxy_1();		/* original paradiseII galaxy generator */
+    break;
+  }
+
+  if (configvals->galaxygenerator != 4)
+  {
+    /* gotta do this before they are sorted */
+    for (i = 0; i < NUMPLANETS; i++)
+    {
+      pl = &planets[i];
+      if (PL_TYPE(*pl) == PLSTAR ||
+	  ((pl->pl_system == 0) && (PL_TYPE(*pl) != PLWHOLE)))
+      {
+	pl->pl_radius = 0;
+	pl->pl_angle = 0;
+      }
+      else if (PL_TYPE(*pl) != PLWHOLE)
+      {
+	int dx, dy;
+	dx = pl->pl_x - planets[pl->pl_system - 1].pl_x;
+	dy = pl->pl_y - planets[pl->pl_system - 1].pl_y;
+	pl->pl_radius = ihypot(dx, dy);
+	pl->pl_angle = atan2((double) dy, (double) dx);
+      }
+    }
+    sortnames();		/* sort the names of planets */
+    build_stars_array();
+    if (configvals->neworbits)
+      pl_neworbit();
+    generate_terrain();
+  }
+}
+
+void 
+pl_neworbit()
+/*
+ * rearranges a pre-existing galaxy setup such that planets orbit at more
+ * "unique" distances from their star.  Asteroids look and probably play bad
+ * when all the planets are approx. the same dist from the star, so I'd
+ * suggest turning this on if you plan to have asteroids or orbiting planets
+ * on your server.  I'd suggest turning it on even if you don't. :)  -MDM
+ */
+{
+  register int i, j;
+  register struct planet *p;
+  register int numStars = 0, planetsThisStar = 0;
+#ifndef IRIX
+  int planetList[NUMPLANETS];
+#else
+  int planetList[70];
+#endif
+
+  /* find the number of stars */
+  for (i = 0; i < MAXPLANETS; i++)
+    if (PL_TYPE(planets[i]) == PLSTAR)
+      numStars++;
+
+  /* for each star, find the number of planets, and the average distance */
+
+  for (i = 1; i <= numStars; i++)
+  {
+    planetsThisStar = 0;
+    for (j = 0; j < MAXPLANETS; j++)
+      if (planets[j].pl_system == i)
+	planetList[planetsThisStar++] = j;
+
+    /*
+     * now move the planets such that each planet we came across gets its
+     * previous distance from it's star, times (it's position in the
+     * planetList array)/(planetsThisStar/1.6).  also make sure that new
+     * radius isin't so close to star ship can't orbit it.  Heh.  Separate
+     * the men from the boyz, eh?
+     */
+
+    for (j = 0; j < planetsThisStar; j++)
+    {
+      planets[planetList[j]].pl_radius =
+	(int) ((float) planets[planetList[j]].pl_radius *
+	       ((float) (j + 1) / (float) (planetsThisStar / 1.6))) + 1500;
+      planets[planetList[j]].pl_x =
+	planets[stars[i]].pl_x +
+	(int) ((float) cos(planets[planetList[j]].pl_angle) *
+	       (float) planets[planetList[j]].pl_radius);
+      planets[planetList[j]].pl_y =
+	planets[stars[i]].pl_y +
+	(int) ((float) sin(planets[planetList[j]].pl_angle) *
+	       (float) planets[planetList[j]].pl_radius);
+    }
+  }
+}
+
+void
+moveplanets()
+{
+  register int i;		/* for looping */
+  register struct planet *l;	/* to point to individual plaent */
+
+  if (stars[1] < 0)
+    build_stars_array();
+
+  /* totally experimental planet moving stuff */
+  for (i = 0; i < NUMPLANETS; i++)
+  {
+    int x, y;
+    double r;
+    l = &planets[i];
+    if (PL_TYPE(*l) == PLSTAR || l->pl_system == 0)
+      continue;			/* write code for them another time */
+
+    r = l->pl_radius;
+    l->pl_angle += configvals->planupdspd * 1e2 / sqrt(r * r * r);
+    if (l->pl_angle > 2 * M_PI)
+      l->pl_angle -= 2 * M_PI;
+    x = planets[stars[l->pl_system]].pl_x + cos(l->pl_angle) * l->pl_radius;
+    y = planets[stars[l->pl_system]].pl_y + sin(l->pl_angle) * l->pl_radius;
+    move_planet(i, x, y, 1);
+  }
+}
+
+
+/*
+ * This function pops the armies on planets.  It now uses the tables that are
+ * in this module.  Negative growth is supported.
+ */
+
+static void
+pop_one_planet1(l)
+  struct planet *l;
+{
+  int r;			/* to hold resource index */
+  int a;			/* to hold atmosphere index */
+  int t;			/* temp var */
+  float ft;			/* another temp */
+
+  r = (l->pl_flags & PLRESMASK) >> PLRESSHIFT;	/* get resource bits */
+  r = restores[r];		/* convert to 3 bits */
+  a = l->pl_flags & PLATMASK;	/* get atmosphere bits */
+  a = a >> PLATSHIFT;		/* shift to lower two bits of int */
+
+#ifdef UFL
+  t = status2->league ? popchance[a][r] : 8;
+#else
+  t = popchance[a][r];		/* get pop chance */
+#endif
+  if (t < lrand48() % 100)	/* if planet misses chance */
+    return;			/* then on to next planet */
+  ft = popmult[a][r];		/* get pop multiplier */
+  if (ft >= 0)
+  {				/* positive multiplier */
+    int incr;
+
+    if (l->pl_armies >= popcap[a][r])
+      return;
+
+    if (l->pl_armies < 4)	/* chance of going over four */
+      l->pl_flags |= PLREDRAW;	/* slate planet for redraw */
+    if (configvals->new_army_growth)
+#ifdef AEDILE
+      incr = 0.5 + ft * 2.0 * (float) (lrand48() % 6 + 3);
+#else
+      incr = 1 + 0.5 + ft * (float) (l->pl_armies);
+#endif
+    else
+      /* what about agri? */
+      incr = 1 + lrand48() % 3;	/* bronco is always 1-3 armies/pop */
+    tlog_pop(l, incr);
+    l->pl_armies += incr;	/* add on multiplier armies */
+    l->pl_tinfo[l->pl_owner].armies = l->pl_armies;
+    l->pl_tinfo[l->pl_owner].timestamp = status->clock;
+  }
+  else
+  {				/* negative multiplier */
+    int decr;
+    if (l->pl_armies < 4)	/* no killing all the armies on */
+      return;			/* a planet */
+    l->pl_flags |= PLREDRAW;	/* slate planet for redraw */
+    decr = 1 + 0.5 - ft * (float) (l->pl_armies);
+    tlog_pop(l, -decr);
+    l->pl_armies -= decr;	/* subtract armies */
+    l->pl_armies = (l->pl_armies < 0) ? 0 : l->pl_armies;
+    if (l->pl_armies <= 0)
+    {				/* if all died then */
+      l->pl_armies = 0;		/* no negative armies */
+      l->pl_tinfo[l->pl_owner].armies = 0;	/* old owner knows */
+      l->pl_tinfo[l->pl_owner].timestamp = status->clock;
+      l->pl_tinfo[l->pl_owner].owner = NOBODY;
+      l->pl_owner = NOBODY;	/* planet is neutral */
+    }
+    l->pl_tinfo[l->pl_owner].armies = l->pl_armies;
+    l->pl_tinfo[l->pl_owner].timestamp = status->clock;
+    if (l->pl_armies == 0)	/* if all armies died */
+      checkwin(enemy_admiral(-1));	/* check if game over */
+  }
+}
+/*
+ * */
+
+static void
+pop_one_planet2(l)
+  struct planet *l;
+{
+  int delta = 0;
+  int atmosphere = (l->pl_flags & PLATMASK) >> PLATSHIFT;
+  int surface = (l->pl_flags & PLSURMASK) >> PLSURSHIFT;
+
+  if (l->pl_armies < 4 && (l->pl_flags & PLAGRI))
+    delta++;
+
+  if (atmosphere == 0)
+  {
+    if (l->pl_armies >= 4 && drand48() < 0.5)
+    {
+      delta--;
+    }
+  }
+  else if (atmosphere < 3)
+  {
+    if (drand48() <
+	((atmosphere == 1)
+	 ? (l->pl_armies < 4 ? 0.2 : 0.1)
+	 : (l->pl_armies < 4 ? 0.5 : 0.2)))
+    {
+      delta++;
+    }
+  }
+  else
+  {
+    if (drand48() < (l->pl_armies < 4 ? 0.3 : 0.2))
+    {
+      static int table[] = {2, 2, 2, 3, 3, 3, 4, 4};
+      int max = table[surface];
+      delta++;
+      if (l->pl_flags & PLAGRI && l->pl_armies >= 4)
+	max++;			/* armies<4 handled at top */
+      delta += lrand48() % max;
+    }
+  }
+
+  if (l->pl_armies == 0 && delta > 1)
+    delta = 1;			/* training that first army is tough */
+
+  tlog_pop(l, delta);
+
+  if (delta > 0 &&
+      l->pl_armies > popcap[atmosphere]
+      [restores[(l->pl_flags & PLRESMASK) >> PLRESSHIFT]])
+    delta = 0;
+  l->pl_armies += delta;
+
+  /*
+   * I doubt this if statement will ever get executed unless someone's
+   * frobbing shmem
+   */
+  if (l->pl_armies <= 0)
+  {				/* if all died then */
+    l->pl_armies = 0;		/* no negative armies */
+
+    tlog_revolt(l);		/* well, not exactly. */
+
+    l->pl_tinfo[l->pl_owner].armies = 0;	/* old owner knows */
+    l->pl_tinfo[l->pl_owner].timestamp = status->clock;
+    l->pl_tinfo[l->pl_owner].owner = NOBODY;
+    l->pl_owner = NOBODY;	/* planet is neutral */
+    checkwin(enemy_admiral(-1));/* check if game over */
+  }
+
+  l->pl_tinfo[l->pl_owner].armies = l->pl_armies;
+  l->pl_tinfo[l->pl_owner].timestamp = status->clock;
+}
+
+void
+pop_one_planet(l)
+  struct planet *l;
+{
+#if 0
+  printf("popping planet #%d  %x\n", l->pl_no, l->pl_owner);
+  fflush(stdout);
+#endif
+
+  switch (configvals->popscheme)
+  {
+   case 1:
+    pop_one_planet2(l);
+    break;
+   default:
+   case 0:
+    pop_one_planet1(l);
+    break;
+  }
+}
+
+
+/*-------------------------------UDPLANETS----------------------------------*/
+
+void
+fill_planets(plist, count, owner)
+  int *plist;			/* array */
+  int *count;			/* scalar */
+  int owner;
+{
+  int i;
+  *count = 0;
+  for (i = 0; i < configvals->numplanets; i++)
+  {
+    if (owner < 0 || planets[i].pl_owner == owner)
+      plist[(*count)++] = i;
+  }
+
+  for (i = *count - 1; i > 0; i--)
+  {
+    int idx = lrand48() % (i + 1);
+    int temp = plist[idx];
+    plist[idx] = plist[i];
+    plist[i] = temp;
+  }
+}
+
+int
+find_other_team(teammask)
+  int teammask;
+{
+  int counts[NUMTEAM];
+  int i;
+  for (i = 0; i < NUMTEAM; i++)
+    counts[i] = 0;
+  for (i = 0; i < MAXPLAYER; i++)
+  {
+    int teamidx = mask_to_idx(players[i].p_team);
+    if (teamidx >= 0 && teamidx < NUMTEAM && !(teammask & (1 << teamidx)))
+      counts[teamidx]++;
+  }
+
+  {
+    int max = -1;
+    int rval = 0;
+    for (i = 0; i < NUMTEAM; i++)
+    {
+      if (counts[i] > max && !(teammask & (1 << i)))
+      {
+	max = counts[i];
+	rval = 1 << i;
+      }
+    }
+    return rval;
+  }
+}
+
+void
+popplanets()
+{
+  register int i;		/* for looping */
+  register struct planet *l;	/* to point to individual plaent */
+
+  if (!status->tourn)		/* check t-mode */
+    return;			/* do not pop planets */
+
+  switch (configvals->popchoice)
+  {
+   case 0:
+    {
+      static int fuse = 0;
+      if (++fuse < PLANETFUSE)
+	return;			/* nothing to do */
+      fuse = 0;
+      for (i = 0, l = &planets[i]; i < NUMPLANETS; i++, l++)
+      {
+	if ((l->pl_armies == 0) ||
+	    (PL_TYPE(*l) == PLSTAR) ||
+	    (PL_TYPE(*l) == PLWHOLE))	/* if no armies to pop */
+	  continue;		/* go to next planet */
+#if 0
+	if (l->pl_owner != NOBODY)	/* only team planets can revolt */
+	  revolt(l);		/* check for revolt */
+#endif
+	pop_one_planet(l);
+      }
+    } break;
+   case 1:
+    {
+#if 0
+      static int indplanets[MAXPLANETS];
+      static int indcount = 0;
+#endif
+      static int Aplanets[MAXPLANETS];
+      static int Acount = 0, Amask = 0;
+      static int Bplanets[MAXPLANETS];
+      static int Bcount = 0, Bmask = 0;
+
+      int INDchance;
+      float Achance, Bchance;
+      float f;
+
+      /* make sure there's planets in the lists */
+#if 0
+      if (indcount < 1)
+	fill_planets(indplanets, &indcount, NOBODY);
+#endif
+      if (Acount < 1)
+      {
+	Amask = find_other_team(Bmask);
+	fill_planets(Aplanets, &Acount, Amask);
+      }
+      if (Bcount < 1)
+      {
+	Bmask = find_other_team(Amask);
+	fill_planets(Bplanets, &Bcount, Bmask);
+      }
+
+      /* figure out the probabilities */
+      INDchance = Achance = Bchance = 0;
+      for (i = 0; i < configvals->numplanets; i++)
+      {
+	if (planets[i].pl_owner == Amask)
+	  Achance += 1.0;
+	else if (planets[i].pl_owner == Bmask)
+	  Bchance += 1.0;
+	else if (!((PL_TYPE(planets[i]) == PLSTAR) ||
+		   (PL_TYPE(planets[i]) == PLWHOLE)))
+	  /* if (planets[i].pl_owner == NOBODY) */
+	  INDchance += 1.0;
+      }
+
+#ifdef LOOSING_ADVANTAGE
+      {
+	double la = LOOSING_ADVANTAGE;
+	if (Achance < Bchance)
+	  Achance *= (la - (la - 1) * Achance / Bchance);
+	else
+	  Bchance *= (la - (la - 1) * Bchance / Achance);
+      }
+#endif
+
+      f = drand48() * (INDchance + Achance + Bchance);
+      if (f < INDchance)
+      {
+#if 0				/* 3rd-race planets and INDs don't pop */
+	pop_one_planet(&planets[indplanets[--indcount]]);
+#endif
+      }
+      else if (f - INDchance < Achance)
+      {
+	pop_one_planet(&planets[Aplanets[--Acount]]);
+      }
+      else
+      {
+	pop_one_planet(&planets[Bplanets[--Bcount]]);
+      }
+
+    } break;
+  }
+}
+
+
+
+
+
+/*----------------------------------PLFIGHT--------------------------------*/
+/*
+ * This function does the fighting for a planet.  It decs the warning timer
+ * and clears the REDRAW flag.  It then handles the bombing for the players.
+ * It then goes on to see if a player is visible to the other team by
+ * checking the closeness of other players.  The planets are then checked to
+ * see if they are close enough to fire on enemy players.
+ */
+
+void
+plfight()
+{
+  register int h;		/* looping vars */
+  register struct planet *l;	/* for looping through planets */
+
+  for (h = 0, l = &planets[h]; h < NUMPLANETS; h++, l++)
+  {
+    l->pl_flags &= ~PLREDRAW;	/* clear the PLDRAW flag */
+    if (l->pl_warning > 0)	/* check if timer needs dec */
+      l->pl_warning--;		/* dec the warning timer */
+  }
+  pbomb();			/* go do bombing for players */
+  pvisible();			/* check visibility w/ other players */
+  pfire();			/* let planets fire on other players */
+}
+
+
+
+
+/*-------------------------------SAVE_PLANETS-----------------------------*/
+/*
+ * This function saves the planets structure to disk.  The plfd variable is a
+ * handle on the previously opened .planets file.  The function also saves
+ * the status to the glfd file.
+ */
+
+void
+save_planets()
+{
+  if (plfd >= 0)
+  {				/* if plfd file open */
+    (void) lseek(plfd, (long) 0, 0);	/* save the planets */
+    (void) write(plfd, (char *) planets, sizeof(struct planet) * MAXPLANETS);
+  }
+  if (glfd >= 0)
+  {				/* if glfd file open then */
+    (void) lseek(glfd, (long) 0, 0);	/* save the status */
+    (void) write(glfd, (char *) status, sizeof(struct status));
+  }
+}
+
+/*-------------------------------------------------------------------------*/
+
+
+
+/*----------END OF FILE--------*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/planets.h	Sat Dec 06 04:37:04 1997 +0000
@@ -0,0 +1,61 @@
+/*--------------------------------------------------------------------------
+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 "defs.h"		/* for GWIDTH */
+
+
+/*--------------------------------NUMBER DEFINES-------------------------*/
+
+/*-----------------------------------------------------------------------*/
+
+
+
+/*------------------------PLANETS FUNCTION PROTOTYPES----------------------*/
+void gen_planets();		/* generate planets positions */
+void popplanets();		/* update planets pop */
+void growplanets();		/* grow planets facilities */
+void plfight();			/* do fighting for planets */
+void save_planets();		/* save the planets to '.planets' file */
+/*-------------------------------------------------------------------------*/
+
+/*--------------------------PLANET UTILITY FUNCTIONS-----------------------*/
+#ifdef __STDC__
+extern int 
+place_stars(struct planet * first, int count, int border,
+	    int minpad, int maxpad, struct planet * othercheck,
+	    int ocount);
+extern void zero_plflags(struct planet * first, int count);
+extern void 
+randomize_atmospheres(struct planet * first, int count,
+		      int p1, int p2, int p3, int p4);
+extern void 
+randomize_resources(struct planet * first, int count,
+		    int nm, int nd, int na);
+extern void justify_galaxy(int numsystems);
+#else
+extern int place_stars();
+extern void zero_plflags();
+extern void randomize_atmospheres();
+extern void randomize_resources();
+extern void justify_galaxy();
+#endif
+void pl_neworbit();
+/*-------------------------------------------------------------------------*/
+
+
+/*----------END OF FILE-------*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/plasma.c	Sat Dec 06 04:37:04 1997 +0000
@@ -0,0 +1,130 @@
+/*--------------------------------------------------------------------------
+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 <stdio.h>
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include "defs.h"
+#include "struct.h"
+#include "data.h"
+#include "shmem.h"
+
+
+
+
+
+/*-----------------------------VISIBLE FUNCTIONS---------------------------*/
+
+/*--------------------------------NPLASMATORP------------------------------*/
+/*
+ * This function fires a plasma torp.  It checks a number of conditions to
+ * see if it is allowable to fire a plasma torp.  If so the the plasma if
+ * fire. The two styles of plasma torp are ones that fire in the direction
+ * the ship is going and ones that can fire independent of the ships
+ * direction.
+ */
+
+void
+nplasmatorp(course, type)
+  unsigned char course;		/* direction plasma should go */
+  int type;			/* type of plasma */
+{
+  register int i;		/* looping var */
+  register struct plasmatorp *k;/* to point to plasma torp */
+
+  if (weaponsallowed[WP_PLASMA] == 0)
+  {				/* are plasmas enabled */
+    warning("Plasmas haven't been invented yet.");
+    return;
+  }
+  if (me->p_ship.s_plasma.cost <= 0)
+  {				/* ship can have plasma */
+    warning("Weapon's Officer:  Captain, this ship can't carry plasma torpedoes!");
+    return;
+  }
+  if (!(me->p_specweap & SFNPLASMAARMED))
+  {				/* ship equiped with plasma */
+    warning("Weapon's Officer:  Captain, this ship is not armed with plasma torpedoes!");
+    return;
+  }
+  if (me->p_flags & PFWEP)
+  {				/* ship not w-temped */
+    warning("Plasma torpedo launch tube has exceeded the maximum safe temperature!");
+    return;
+  }
+  if (me->p_nplasmatorp == MAXPLASMA)
+  {
+    warning("Our fire control system limits us to 1 live torpedo at a time captain!");
+    return;
+  }
+  if (me->p_fuel < myship->s_plasma.cost)
+  {				/* have enough fuel? */
+    warning("We don't have enough fuel to fire a plasma torpedo!");
+    return;
+  }
+  if (me->p_flags & PFREPAIR)
+  {				/* not while in repair mode */
+    warning("We cannot fire while our vessel is undergoing repairs.");
+    return;
+  }
+  if ((me->p_cloakphase) && (me->p_ship.s_type != ATT))
+  {
+    warning("We are unable to fire while in cloak, captain!");
+    return;			/* not while cloaked */
+  }
+
+  if (!check_fire_warp()
+      || !check_fire_warpprep()
+      || !check_fire_docked())
+    return;
+  me->p_nplasmatorp++;		/* inc plasma torps fired */
+  me->p_fuel -= myship->s_plasma.cost;	/* take off the fuel */
+  me->p_wtemp += myship->s_plasma.wtemp;	/* do the w-temp */
+  for (i = me->p_no * MAXPLASMA, k = &plasmatorps[i];
+       i < (me->p_no + 1) * MAXPLASMA; i++, k++)
+  {
+    if (k->pt_status == PTFREE)	/* find a free plasma to fire */
+      break;
+  }
+
+  k->pt_no = i;			/* set plasmas number */
+  k->pt_status = type;		/* set what type plasma is */
+  k->pt_owner = me->p_no;	/* set the owner */
+  k->pt_team = me->p_team;	/* set the team */
+  k->pt_x = me->p_x;		/* set starting coords */
+  k->pt_y = me->p_y;
+  if (myship->s_nflags & SFNPLASMASTYLE)	/* depending on type set */
+    k->pt_dir = course;		/* any direction */
+  else
+    k->pt_dir = me->p_dir;	/* or straight ahead of ship */
+  k->pt_damage = myship->s_plasma.damage;	/* set the damage it will do */
+  k->pt_speed = myship->s_plasma.speed;	/* set its speed */
+  k->pt_war = me->p_hostile | me->p_swar;	/* who it doesn't like */
+  k->pt_fuse = myship->s_plasma.fuse;	/* how long it will live */
+  k->pt_turns = myship->s_plasma.aux;	/* how much will it track */
+}
+
+/*-------------------------------------------------------------------------*/
+
+
+
+
+
+/*------END OF FILE-----*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/player.h	Sat Dec 06 04:37:04 1997 +0000
@@ -0,0 +1,39 @@
+/*--------------------------------------------------------------------------
+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
+--------------------------------------------------------------------------*/
+
+
+
+
+
+/*----------------------------FUNCTION PROTOTYPES-------------------------*/
+void fractbomb();		/* do fractional bombing */
+void loserstats();		/* inc a killed player's losses */
+void killerstats();		/* inc killers kills */
+void checkmaxkills();		/* adjust player's maxkills if need be */
+void blowup();			/* inflict damage on nearby players */
+void beam();			/* beam up and down for players */
+void udcloak();			/* inc/dec the cloakphases for players */
+void udplayers();		/* update the players */
+/*-----------------------------------------------------------------------*/
+
+
+
+
+
+
+/*----------END OF FILE--------*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/plutil.c	Sat Dec 06 04:37:04 1997 +0000
@@ -0,0 +1,272 @@
+/*--------------------------------------------------------------------------
+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 "plutil.h"
+#include "data.h"
+#include "shmem.h"
+
+int
+idx_to_mask(i)
+  int i;
+{
+  if (i >= 0)
+    return 1 << i;
+  else
+    return 0;
+}
+
+int
+mask_to_idx(m)
+  int m;
+{
+  int i;
+  if (!m)
+    return -1;
+  for (i = 0; m > 1; i++, m >>= 1);
+  return i;
+}
+
+/*
+ */
+
+int
+in_warp(pl)
+  struct player *pl;
+{
+  if (pl->p_flags & PFDOCK)
+  {
+    /* if we are docked, then we have the same state as our base */
+    return in_warp(&players[pl->p_docked]);
+  }
+  return (pl->p_flags & PFWARP) || pl->p_warptime;
+}
+
+
+int
+undock_player(pl)
+  struct player *pl;
+{
+  struct player *base;
+
+  if (!(pl->p_flags & PFDOCK))
+    return 0;
+
+  base = &players[pl->p_docked];
+  base->p_docked--;		/* base no longer has as many docked */
+  base->p_port[pl->p_port[0]] = VACANT;	/* the port is vacant */
+
+  /* what if the player is being undocked because he died? */
+  if (base->p_ship.s_type == JUMPSHIP)
+  {
+    pl->p_jsdock = 1;
+    pl->p_lastjs = pl->p_docked;
+  }
+  pl->p_flags &= ~PFDOCK;
+  pl->p_docked = -1;
+  pl->p_port[0] = VACANT;
+
+  return 1;
+}
+
+int
+base_undock(base, port_id)
+  struct player *base;
+  int port_id;
+{
+  struct player *pl;
+
+  if (base->p_port[port_id] < 0)
+    return 0;
+
+  pl = &players[base->p_port[port_id]];
+
+  base->p_docked--;
+  base->p_port[port_id] = VACANT;
+
+  /* if the jumpship kicks you off, he doesn't get credited.  -RF */
+
+  pl->p_flags &= ~PFDOCK;
+  pl->p_docked = -1;
+  pl->p_port[0] = VACANT;
+  return 1;
+}
+
+void
+enforce_dock_position(pl)
+  struct player *pl;
+{
+  struct player *base;
+  unsigned char angle;
+  int port_id;
+
+  if (!(pl->p_flags & PFDOCK))
+    return;
+
+  base = &players[pl->p_docked];
+  port_id = pl->p_port[0];
+
+  if ((base->p_ship.s_type == STARBASE) || (base->p_ship.s_type == WARBASE) ||
+      (base->p_ship.s_type == JUMPSHIP))
+    angle = (port_id * 2 + 1) * 128 / base->p_ship.s_numports;
+  else
+    angle = base->p_dir + 64 + (128 * port_id);	/* max of two ports, really */
+  move_player(pl->p_no, (int) (base->p_x + DOCKDIST * Cos[angle]),
+	      (int) (base->p_y + DOCKDIST * Sin[angle]), 1);
+
+  pl->p_speed = pl->p_desspeed = 0;
+  if ((base->p_ship.s_type == STARBASE) || (base->p_ship.s_type == WARBASE) ||
+      (base->p_ship.s_type == JUMPSHIP))
+    pl->p_dir = pl->p_desdir = angle + 64;
+  else
+    pl->p_dir = pl->p_desdir = base->p_dir;
+}
+
+void
+dock_to(pl, base_num, port_id)
+  struct player *pl;
+  int base_num, port_id;
+{
+  struct player *base = &players[base_num];
+
+  undock_player(pl);
+
+  base->p_docked++;
+  base->p_port[port_id] = pl->p_no;
+
+  pl->p_flags |= PFDOCK;	/* we are docked */
+  pl->p_docked = base_num;	/* to this base */
+  pl->p_port[0] = port_id;	/* in this docking bay */
+
+  enforce_dock_position(pl);
+}
+
+void
+scout_planet(p_no, pl_no)
+  int p_no;
+  int pl_no;
+{
+  struct player *fred = &players[p_no];
+  struct planet *mars = &planets[pl_no];
+  int oldness = status->clock - mars->pl_tinfo[fred->p_team].timestamp;
+
+  if (!status->tourn)
+    return;
+
+  if ((mars->pl_owner != fred->p_team) &&
+      (oldness > 2))
+  {
+#define LOG2OFe 1.442695
+    double scoutdi = log((double) oldness) * LOG2OFe / 100;
+    if (scoutdi > 0.1)
+      scoutdi = 0.1;
+    fred->p_stats.st_di += scoutdi;
+  }
+  mars->pl_hinfo |= fred->p_team;
+  if (mars->pl_owner != fred->p_team)
+  {
+    mars->pl_tinfo[fred->p_team].flags = mars->pl_flags;
+    mars->pl_tinfo[fred->p_team].armies = mars->pl_armies;
+    mars->pl_tinfo[fred->p_team].owner = mars->pl_owner;
+    mars->pl_tinfo[fred->p_team].timestamp = status->clock;
+  }
+}
+
+/*
+ * */
+
+void
+evaporate(pl)
+  struct player *pl;
+{
+  /* put someone on the outfit screen with no ill effects */
+
+  undock_player(pl);		/* if docked then undock me */
+
+  if (allows_docking(pl->p_ship))
+  {				/* if ships can dock */
+    int k;
+    for (k = 0; k < pl->p_ship.s_numports; k++)
+      base_undock(pl, k);	/* remove all docked ships */
+    pl->p_docked = 0;		/* no ships docked anymore */
+  }
+  if (pl->p_flags & PFORBIT)
+  {				/* if orbiting then */
+    pl->p_flags &= ~PFORBIT;	/* eject from orbit */
+  }
+
+  pl->p_status = POUTFIT;
+  pl->p_whydead = KPROVIDENCE;
+}
+
+void
+explode_everyone(whydead, minlive)
+  int whydead;
+  int minlive;
+{
+  int i;
+  for (i = 0; i < MAXPLAYER; i++)
+  {
+    if (players[i].p_status != PALIVE
+	&& players[i].p_status != POBSERVE)
+      continue;
+
+    if (players[i].p_updates < minlive)
+      continue;
+
+    players[i].p_whydead = whydead;
+    players[i].p_whodead = 0;
+    players[i].p_status = PEXPLODE;
+    players[i].p_explode = 10;
+    players[i].p_ntorp = 0;	/* no torps shot */
+    players[i].p_nplasmatorp = 0;	/* no plasmas shot */
+  }
+}
+
+
+/* round randomly, but weighted by the fractional part */
+
+int
+random_round(d)
+  double d;
+{
+  int rval = floor(d);
+  if (drand48() < d - rval)
+    rval++;
+  return rval;
+}
+
+
+char *
+twoletters(pl)
+  struct player *pl;
+/* calculate the two letters that form the players designation (e.g. R4) */
+{
+#define RINGSIZE MAXPLAYER+3
+  static char buf[RINGSIZE][3];	/* ring of buffers so that this */
+  static int idx;		/* proc can be called several times before
+				 * the results are used */
+  if (idx >= RINGSIZE)
+    idx = 0;
+  buf[idx][0] = teams[pl->p_team].letter;
+  buf[idx][1] = shipnos[pl->p_no];
+  buf[idx][2] = 0;
+  return buf[idx++];
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/plutil.h	Sat Dec 06 04:37:04 1997 +0000
@@ -0,0 +1,40 @@
+/*--------------------------------------------------------------------------
+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
+--------------------------------------------------------------------------*/
+
+
+#ifndef plutil_h_
+#define plutil_h_
+
+/* is the player in warp? */
+int in_warp( /* struct player * */ );
+
+
+/*
+ * remove the player from his base. Returns 1 if the player was really
+ * docked, 0 otherwise
+ */
+int undock_player( /* struct player * */ );
+
+/* make sure the player has the proper coordinates */
+void enforce_dock_position( /* struct player * */ );
+
+/* dock a player onto a base at a certain port */
+void
+    dock_to( /* struct player *, int base_num, int port_id */ );
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/rcslog	Sat Dec 06 04:37:04 1997 +0000
@@ -0,0 +1,190 @@
+daemonII.c
+----------------------------
+revision 1.3
+date: 1996/10/11 01:39:48;  author: edorman;  state: Exp;  lines: +2 -2
+old vsn would wipe out loadcheck data if PARAVERS was too long (doh!)
+we only care about 1st number anyway so print that.
+----------------------------
+revision 1.2
+date: 1996/10/11 01:17:22;  author: edorman;  state: Exp;  lines: +2 -0
+FreeBSD doesn't need lseek decl conflicts with POSIXness
+----------------------------
+
+data.c
+----------------------------
+revision 1.2	locked by: edorman;
+date: 1996/10/11 01:34:13;  author: edorman;  state: Exp;  lines: +1 -1
+Experimental notation.
+----------------------------
+
+feature.c
+----------------------------
+revision 1.3
+date: 1996/10/18 23:54:33;  author: edorman;  state: Exp;  lines: +5 -1
+make sure we tell the client what features the server supports.
+----------------------------
+revision 1.2
+date: 1996/10/16 00:22:38;  author: edorman;  state: Exp;  lines: +4 -0
+no change
+----------------------------
+
+getship.c
+----------------------------
+revision 1.2
+date: 1996/10/12 02:10:01;  author: edorman;  state: Exp;  lines: +7 -0
+check and see if WARPDRIVE got unset later and
+fix it when we give a ship to a player.
+----------------------------
+
+listen.c
+----------------------------
+revision 1.3
+date: 1996/10/11 02:26:59;  author: edorman;  state: Exp;  lines: +1 -1
+bad syntax causes bad inetaddr in cases where dns won't resolve to a name
+----------------------------
+revision 1.2
+date: 1996/10/11 01:21:09;  author: edorman;  state: Exp;  lines: +2 -0
+FreeBSD doesn't want sys_errlist defined this way; use system proto
+----------------------------
+
+main.c
+----------------------------
+revision 1.3
+date: 1996/10/16 00:27:41;  author: edorman;  state: Exp;  lines: +3 -0
+added player default to RCD off
+----------------------------
+revision 1.2
+date: 1996/10/15 23:50:12;  author: edorman;  state: Exp;  lines: +3 -3
+added rtt, sdv, pckloss to logging
+,.
+----------------------------
+
+pl_gen7.c
+----------------------------
+revision 1.2
+date: 1996/10/24 21:27:57;  author: edorman;  state: Exp;  lines: +1 -2
+include wormholes
+----------------------------
+
+planets.c
+----------------------------
+revision 1.5
+date: 1996/10/12 03:29:12;  author: edorman;  state: Exp;  lines: +2 -2
+hope i fixed it this time.
+----------------------------
+revision 1.4
+date: 1996/10/12 03:22:22;  author: edorman;  state: Exp;  lines: +1 -1
+not quite far enuf
+----------------------------
+revision 1.3
+date: 1996/10/12 02:50:05;  author: edorman;  state: Exp;  lines: +4 -2
+fix so no planet is so close to star that can't orbit.  maybe
+should leave it that way, eh?  pisser to have SY that way tho.
+----------------------------
+revision 1.2
+date: 1996/10/12 02:10:58;  author: edorman;  state: Exp;  lines: +4 -0
+planets.c
+----------------------------
+
+player.c
+----------------------------
+revision 1.4
+date: 1996/10/12 03:22:28;  author: edorman;  state: Exp;  lines: +22 -4
+fixed ship operation at empty fuel
+----------------------------
+revision 1.3
+date: 1996/10/12 02:42:28;  author: edorman;  state: Exp;  lines: +2 -3
+old etemp code too good :) fixed now 2x rate for helpfulplanets
+----------------------------
+revision 1.2
+date: 1996/10/12 02:32:57;  author: edorman;  state: Exp;  lines: +20 -6
+added helpfulplanets configvals
+----------------------------
+
+shmem.c
+----------------------------
+revision 1.3
+date: 1996/10/24 21:28:04;  author: edorman;  state: Exp;  lines: +1 -1
+fixed so planet generator can set numplanets.
+----------------------------
+revision 1.2
+date: 1996/10/11 01:59:56;  author: edorman;  state: Exp;  lines: +1 -1
+fix for galaxy gen setup
+----------------------------
+
+socket.c
+----------------------------
+revision 1.3	locked by: edorman;
+date: 1996/10/12 02:10:58;  author: edorman;  state: Exp;  lines: +4 -4
+planets.c
+----------------------------
+revision 1.2
+date: 1996/10/12 01:07:28;  author: edorman;  state: Exp;  lines: +1 -1
+must update ship _first_ when using shortpackets
+elsewise client gets confused; nonshort sends abs addr anyway.
+----------------------------
+
+sysdefaults.c
+----------------------------
+revision 1.3
+date: 1996/11/01 22:09:10;  author: edorman;  state: Exp;  lines: +0 -1
+deleted unused debugging code
+----------------------------
+revision 1.2
+date: 1996/10/12 02:10:58;  author: edorman;  state: Exp;  lines: +2 -0
+planets.c
+----------------------------
+config.h
+----------------------------
+revision 1.3
+date: 1996/10/16 00:23:21;  author: edorman;  state: Exp;  lines: +5 -0
+added RC_DISTRESS stuff
+----------------------------
+revision 1.2
+date: 1996/10/15 23:36:12;  author: edorman;  state: Exp;  lines: +5 -0
+added LOG_LONG_INFO for more info.
+----------------------------
+
+defs.h
+----------------------------
+revision 1.2
+date: 1996/10/11 01:41:01;  author: edorman;  state: Exp;  lines: +1 -1
+metaserver..ecst > metaserver..ecst asthetic change.
+----------------------------
+
+shmem.h
+----------------------------
+revision 1.2
+date: 1996/10/11 02:08:31;  author: edorman;  state: Exp;  lines: +1 -0
+helpfulplanets for fuel/etemp recovery
+----------------------------
+
+struct.h
+----------------------------
+revision 1.5
+date: 1996/10/16 00:32:38;  author: edorman;  state: Exp;  lines: +1 -0
+added MDISTR message type
+----------------------------
+revision 1.4
+date: 1996/10/16 00:24:47;  author: edorman;  state: Exp;  lines: +7 -7
+changed u_char to 'unsigned char'
+----------------------------
+revision 1.3
+date: 1996/10/16 00:20:49;  author: edorman;  state: Exp;  lines: +2 -2
+changed #ifdef RCD to #ifdef RC_DISTRESS to reflect paradise usage
+----------------------------
+revision 1.2
+date: 1996/10/16 00:16:37;  author: edorman;  state: Exp;  lines: +122 -0
+Added RCD definitions
+----------------------------
+
+Makefile.in
+----------------------------
+revision 1.3
+date: 1996/10/12 02:18:01;  author: edorman;  state: Exp;  lines: +1 -1
+fixed pl_gen6/7
+----------------------------
+revision 1.2
+date: 1996/10/11 01:49:35;  author: edorman;  state: Exp;  lines: +2 -1
+added pl_gen7.c
+----------------------------
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/redraw.c	Sat Dec 06 04:37:04 1997 +0000
@@ -0,0 +1,689 @@
+/*--------------------------------------------------------------------------
+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 <stdio.h>
+#include <signal.h>
+#include <setjmp.h>		/* change 4/14/91 TC */
+#include <string.h>
+#include <time.h>
+
+#include <math.h>
+#include "defs.h"
+#include "struct.h"
+#include "data.h"
+#include "packets.h"
+#include "shmem.h"
+
+extern char start_login[], start_name[];	/* change 4/14/91 TC */
+extern int goAway;		/* change 4/14/91 TC */
+extern jmp_buf env;		/* change 4/14/91 TC */
+
+
+#ifdef AUTHORIZE
+extern int makeReservedPacket();
+#endif
+extern int sendClientPacket();
+#ifndef	IRIX
+extern int fprintf();
+#endif
+extern void death();
+void auto_features();
+extern int set_speed();
+extern int orbit();
+extern int set_course();
+int newcourse();
+extern void imm_warning();
+
+#ifdef AUTHORIZE
+void
+check_authentication()
+{
+  /* if (!configvals->binconfirm) testtime=0; */
+  if (testtime == -1)
+  {
+    struct reserved_spacket sp;
+
+#ifdef RSA_EXEMPTION_FILE
+    if (site_rsa_exempt())
+    {
+      printf("site exempt from RSA authentication\n");
+      strcpy(RSA_client_type, "site/player is RSA exempt");
+      testtime = 0;
+    }
+    else
+#endif				/* RSA_EXEMPTION_FILE */
+    {
+      /*
+       * Give reasonable period of time to respond to query (and test code if
+       * they need to)
+       */
+
+      testtime = 200;
+      makeReservedPacket(&sp);
+      memcpy(testdata, sp.data, KEY_SIZE);
+      sendClientPacket((struct player_spacket *) & sp);
+    }				/* RSA EXEMPTION */
+  }
+  else if (testtime != 0)
+  {
+    testtime--;
+    if (testtime == 0)
+    {
+      /* User failed to respond to verification query.  Bye! */
+      if (!configvals->binconfirm)
+	me->p_stats.st_flags |= ST_CYBORG;	/* mark for reference 7/27/91
+						 * TC */
+      else
+      {
+	me->p_explode = 10;
+	me->p_whydead = KQUIT;
+	me->p_status = PEXPLODE;
+	fprintf(stderr, "User binary failed to verify\n");
+	if (RSA_Client == 1)
+	  warning("No customized binaries.  Please use a blessed one.");
+	else if (RSA_Client == 2)
+	  warning("Wrong Client Version Number!");
+	else
+	  warning("You need a spiffy new RSA client for this server!");
+      }
+    }
+  }
+}
+#endif				/* AUTHORIZE */
+
+void
+intrupt()
+{
+#ifdef AUTHORIZE
+  check_authentication();
+#endif
+
+  if (me->p_status == PFREE)
+  {
+    me->p_ghostbuster = 0;
+    me->p_status = PDEAD;
+  }
+  /* Change 4/14/91 TC: fixing 2 players/1 slot bug here, since this is */
+  /* where the ghostbust check is */
+
+#if 0
+  if ((strcmp(me->p_login, start_login) != 0) ||
+      (strcmp(me->p_name, start_name) != 0))
+  {
+    struct pstatus_spacket pstatus;
+    goAway = 1;			/* get rid of this client! */
+    warning("Sorry, your slot has been taken by another player.");
+    pstatus.type = SP_PSTATUS;
+    pstatus.pnum = 0;
+    pstatus.status = PDEAD;
+    sendClientPacket(&pstatus);
+    longjmp(env, 0);
+  }
+#endif
+
+  if (me->p_status == PEXPLODE || me->p_status == PDEAD)
+  {
+    inputMask = 0;
+  }
+  if (((me->p_status == PDEAD) || (me->p_status == POUTFIT))
+      && (me->p_ntorp <= 0) && (me->p_nplasmatorp <= 0))
+  {
+    death();
+  }
+  auto_features();
+  updateClient();
+}
+
+
+static void
+selfdestruct_countdown()
+{
+  char buf[180];
+  if (!(me->p_flags & PFSELFDEST))
+    return;
+
+  if ((me->p_updates >= selfdest) ||
+      ((me->p_flags & PFGREEN) && (me->p_damage == 0)
+       && (me->p_shield == me->p_ship.s_maxshield)))
+  {
+    me->p_flags &= ~PFSELFDEST;
+    me->p_explode = 10;
+    me->p_whydead = KQUIT;
+    me->p_status = PEXPLODE;
+  }
+  else
+  {
+    switch ((selfdest - me->p_updates) / 10)
+    {
+     case 5:
+     case 4:
+      imm_warning("You notice everyone on the bridge is staring at you.");
+      break;
+     default:
+      sprintf(buf, "Stand by ... Self destruct in %d seconds",
+	      (selfdest - me->p_updates) / 10);
+      imm_warning(buf);
+      break;
+    }
+  }
+}
+
+static void
+warp_powerup()
+{
+  static int sequence = 0;
+  int time = myship->s_warpinittime;
+
+  if (me->p_warptime <= 0 && sequence == 0)
+    return;
+
+  if (me->p_speed > myship->s_warpprepspeed && !(me->p_flags & PFWARP))
+  {
+    if (sequence < 1)
+    {
+      warning("Prepping for warp jump");
+      sequence = 1;
+    }
+  }
+  else if (me->p_warptime >= time * 9 / 10 /* 37 */ )
+  {
+    if (sequence < 2)
+    {
+      warning("Starting power buildup for warp");
+      sequence = 2;
+    }
+  }
+  else if (me->p_warptime >= time * 3 / 4 /* 30 */ )
+  {
+    if (sequence < 3)
+    {
+      imm_warning("Warp power buildup at 30%");
+      sequence = 3;
+    }
+  }
+  else if (me->p_warptime >= time * 3 / 5 /* 23 */ )
+  {
+    if (sequence < 4)
+    {
+      imm_warning("Warp power buildup at 60%");
+      sequence = 4;
+    }
+  }
+  else if (me->p_warptime >= time * 2 / 5 /* 16 */ )
+  {
+    if (sequence < 5)
+    {
+      imm_warning("Warp power buildup at 90%");
+      sequence = 5;
+    }
+  }
+  else if (me->p_warptime >= time * 1 / 5 /* 8 */ )
+  {
+    if (sequence < 6)
+    {
+      imm_warning("Commander Hoek: `Prepare to surge to sub-light speed'");
+      sequence = 6;
+    }
+  }
+  else if (me->p_warptime == 0)
+  {
+    warning((me->p_flags & PFWARP) ? "Engage" : "Warp drive aborted");
+    sequence = 0;
+  }
+}
+
+static void
+refit_countdown()
+{
+  char buf[120];
+  static int lastRefitValue = 0;/* for smooth display */
+
+  if (!(me->p_flags & PFREFITTING))
+    return;
+
+  if (lastRefitValue != (rdelay - me->p_updates) / 10)
+  {
+    lastRefitValue = (rdelay - me->p_updates) / 10;	/* CSE to the rescue? */
+    switch (lastRefitValue)
+    {
+     case 3:
+     case 2:
+      sprintf(buf, "Engineering:  Energizing transporters in %d seconds", lastRefitValue);
+      warning(buf);
+      break;
+     case 1:
+      warning("Engineering:  Energize. [ SFX: chimes ]");
+      break;
+     case 0:
+      switch (lrand48() % 5)
+      {
+       case 0:
+	warning("Wait, you forgot your toothbrush!");
+	break;
+       case 1:
+	warning("Nothing like turning in a used ship for a new one.");
+	break;
+       case 2:
+	warning("First officer:  Oh no, not you again... we're doomed!");
+	break;
+       case 3:
+	warning("First officer:  Uh, I'd better run diagnostics on the escape pods.");
+	break;
+       case 4:
+	warning("Shipyard controller:  `This time, *please* be more careful, okay?'");
+	break;
+      }
+      break;
+    }
+  }
+}
+
+static void
+backstab_countdown()
+{
+  static int lastWarValue = 0;
+
+  if (!(me->p_flags & PFWAR))
+    return;
+
+  if (lastWarValue != (delay - me->p_updates) / 10)
+  {
+    char *str = 0;
+    lastWarValue = (delay - me->p_updates) / 10;	/* CSE to the rescue? */
+    if (lastWarValue == 0)
+    {
+      static char buf[1024];
+      static char *msgs[7] = {
+	"tires on the ether",
+	"Klingon bitmaps are ugly",
+	"Federation bitmaps are gay",
+	"all admirals have scummed",
+	"Mucus Pig exists",
+	"guests advance 5x faster",
+	"Iggy has infinite fuel",
+      };
+      sprintf(buf, "First Officer: laws of the universe, like '%s'.",
+	      msgs[lrand48() % 7]);
+      str = buf;
+    }
+    else if (lastWarValue <= 9)
+    {
+      static char *msgs[10] = {
+	"First Officer:  Easy, big guy... it's just one of those mysterious",
+	"Weapons officer:  Bah! [ bangs fist on inoperative console ]",
+	"Weapons officer:  Just to twiddle a few bits of the ship's memory?",
+	"Weapons officer:  ...the whole ship's computer is down?",
+	"Weapons officer:  Not again!  This is absurd...",
+      };
+      str = msgs[(lastWarValue - 1) / 2];
+    }
+    else
+    {
+      str = "urk";
+    }
+    if (str)
+    {
+      warning(str);
+    }
+  }
+}
+
+static void
+bombing_info()
+{
+  char buf[120];
+
+  if (!(me->p_flags & PFBOMB))
+    return;
+
+  if (planets[me->p_planet].pl_armies < 5)
+  {
+    if (configvals->facilitygrowth)
+      imm_warning("Weapons Officer: Bombing resources off planet, sir.");
+    else
+    {
+      sprintf(buf, "Weapons Officer: Bombing is ineffective. Sensor read %d armies left.",
+	      planets[me->p_planet].pl_armies);
+      imm_warning(buf);
+    }
+  }
+  else
+  {
+    sprintf(buf, "Weapons Officer: Bombarding %s...  Sensors read %d armies left.",
+	    planets[me->p_planet].pl_name,
+	    planets[me->p_planet].pl_armies);
+    imm_warning(buf);
+  }
+}
+
+
+static void
+operate_transporters()
+{
+  char buf[120];
+  int troop_capacity = 0;
+
+  if ((me->p_ship.s_nflags & SFNARMYNEEDKILL) &&
+      (me->p_kills * myship->s_armyperkill) < myship->s_maxarmies)
+  {
+    troop_capacity = (int) (me->p_kills * myship->s_armyperkill);
+  }
+  else
+    troop_capacity = me->p_ship.s_maxarmies;
+
+  if (me->p_flags & PFBEAMUP)
+  {
+    if (me->p_flags & PFORBIT)
+    {
+      if (planets[me->p_planet].pl_armies < 1)
+      {
+	sprintf(buf, "%s: Too few armies to beam up",
+		planets[me->p_planet].pl_name);
+	warning(buf);
+	me->p_flags &= ~PFBEAMUP;
+      }
+      else if ((planets[me->p_planet].pl_armies <= 4) &&
+	       (me->p_lastman != 2))
+      {
+	strcpy(buf, "Hit beam again to beam up all armies.");
+	warning(buf);
+	me->p_flags &= ~PFBEAMUP;
+      }
+      else if (me->p_armies == troop_capacity)
+      {
+	sprintf(buf, "No more room on board for armies");
+	warning(buf);
+	me->p_flags &= ~PFBEAMUP;
+      }
+      else
+      {
+	sprintf(buf, "Beaming up.  (%d/%d)", me->p_armies, troop_capacity);
+	imm_warning(buf);
+      }
+    }
+    else if (me->p_flags & PFDOCK)
+    {
+      if (players[me->p_docked].p_armies == 0)
+      {
+	sprintf(buf, "Starbase %s: Too few armies to beam up",
+		players[me->p_docked].p_name);
+	warning(buf);
+	me->p_flags &= ~PFBEAMUP;
+      }
+      else if (me->p_armies >= troop_capacity)
+      {
+	sprintf(buf, "No more room on board for armies");
+	warning(buf);
+	me->p_flags &= ~PFBEAMUP;
+      }
+      else
+      {
+	sprintf(buf, "Beaming up.  (%d/%d)", me->p_armies, troop_capacity);
+	imm_warning(buf);
+      }
+    }
+  }
+  if (me->p_flags & PFBEAMDOWN)
+  {
+    if (me->p_armies == 0)
+    {
+      if (me->p_flags & PFDOCK)
+      {
+	sprintf(buf, "No more armies to beam down to Starbase %s.",
+		players[me->p_docked].p_name);
+	warning(buf);
+      }
+      else
+      {
+	sprintf(buf, "No more armies to beam down to %s.",
+		planets[me->p_planet].pl_name);
+	warning(buf);
+      }
+      me->p_flags &= ~PFBEAMDOWN;
+    }
+    else if (me->p_flags & PFORBIT)
+    {
+      sprintf(buf, "Beaming down.  (%d/%d) %s has %d armies left",
+	      me->p_armies,
+	      troop_capacity,
+	      planets[me->p_planet].pl_name,
+	      planets[me->p_planet].pl_armies);
+      imm_warning(buf);
+    }
+    else if (me->p_flags & PFDOCK)
+    {
+      if (players[me->p_docked].p_armies ==
+	  players[me->p_docked].p_ship.s_maxarmies)
+      {
+	sprintf(buf, "Transporter Room:  Starbase %s reports all troop bunkers are full!",
+		players[me->p_docked].p_name);
+	warning(buf);
+	me->p_flags &= ~PFBEAMDOWN;
+      }
+      else
+      {
+	sprintf(buf, "Transfering ground units.  (%d/%d) Starbase %s has %d armies left",
+		me->p_armies,
+		troop_capacity,
+		players[me->p_docked].p_name,
+		players[me->p_docked].p_armies);
+	imm_warning(buf);
+      }
+    }
+  }
+}
+
+#if 0
+static void
+reduce_speed()
+{
+  if (me->p_desspeed > myship->s_imp.maxspeed)
+  {
+    /* drop out of warp */
+    me->p_desspeed = myship->s_imp.maxspeed + 1;
+    me->p_flags &= ~(PFWARP | PFAFTER);
+    warning("Approaching planet, dropping out of warp");
+  }
+  set_speed(me->p_desspeed - 1, 0);
+}
+#endif
+
+static void
+decelerate_at_range(dist)
+  int dist;
+{
+  int speed;
+  int maximp = myship->s_imp.maxspeed;
+
+#define FUDGEFACT	1.15
+
+  if (me->p_flags & PFWARP)
+  {
+    if (configvals->warpdecel)
+    {
+      /*
+       * int impdist = 1000*(maximp*10*WARP1*maximp*10*WARP1)/ (2 *
+       * myship->s_imp.dec*10*10*warp1);
+       */
+
+      int impdist = FUDGEFACT * (maximp * maximp - 2 * 2) * 500 * WARP1 / myship->s_imp.dec;
+
+      for (speed = maximp;
+	   speed < me->p_desspeed && speed < me->p_speed;
+	   speed++)
+      {
+	int decdist;
+	decdist = FUDGEFACT * 500 * ((speed * speed) - (maximp * maximp)) * WARP1 /
+	  myship->s_warp.dec;
+	if (dist - impdist - ENTORBDIST < decdist)
+	  break;
+      }
+      if (speed == maximp && speed < me->p_speed)
+	warning("Approaching planet, dropping out of warp");
+      if (speed < me->p_desspeed &&
+	  speed < me->p_speed)
+      {
+	/* printf("(W) curr: %d, ideal %d\n", me->p_speed, speed); */
+	me->p_desspeed = speed;
+      }
+    }
+    else
+    {
+      int impdist;
+      maximp = (3 * maximp + myship->s_warp.maxspeed) / 4;
+      impdist = FUDGEFACT * ((maximp) * (maximp) - 2 * 2) *
+	500 * WARP1 / myship->s_imp.dec;
+      if (dist - impdist - ENTORBDIST < 0)
+	me->p_flags &= ~PFWARP;
+    }
+  }
+  else
+  {
+    for (speed = 2; speed < me->p_desspeed && speed < me->p_speed; speed++)
+    {
+      int decdist;
+      decdist = FUDGEFACT * 500 * (speed * speed - 2 * 2) * WARP1 / myship->s_imp.dec;
+      if (dist - ENTORBDIST < decdist)
+	break;
+    }
+    if (speed < me->p_desspeed &&
+	speed < me->p_speed)
+    {
+      /* printf("(I) curr: %d, ideal %d\n", me->p_speed, speed); */
+      me->p_desspeed = speed;
+    }
+  }
+}
+
+static void
+follow_player()
+{
+  struct player *pl;
+  int dist;
+
+  if (!(me->p_flags & PFPLOCK))
+    return;
+
+  /* set course to player x */
+
+  pl = &players[me->p_playerl];
+  if (pl->p_status != PALIVE)
+    me->p_flags &= ~PFPLOCK;
+  if (allows_docking(pl->p_ship))
+  {
+    dist = ihypot(me->p_x - pl->p_x, me->p_y - pl->p_y);
+
+    decelerate_at_range(dist);
+
+    if ((dist < DOCKDIST) && (me->p_speed <= 2))
+    {
+      orbit();
+      me->p_flags &= ~PFPLOCK;
+    }
+  }
+  if (me->p_flags & PFPLOCK)
+    set_course(newcourse(pl->p_x, pl->p_y));
+
+}
+
+static void
+follow_planet()
+{				/* follow a planet?  How silly. Will it
+				 * perhaps outmaneuver you? */
+  struct planet *pln;
+  int dist;
+  /* int speed = me->p_speed; */
+
+  if (!(me->p_flags & PFPLLOCK))
+    return;
+
+  /* set course to planet x */
+
+  pln = &planets[me->p_planet];
+  dist = ihypot(me->p_x - pln->pl_x, me->p_y - pln->pl_y);
+
+  decelerate_at_range(dist);
+
+  if ((dist < ENTORBDIST) && (me->p_speed <= 2))
+  {
+    orbit();
+    me->p_flags &= ~PFPLLOCK;
+  }
+  else
+  {
+    int course = newcourse(pln->pl_x, pln->pl_y);
+    set_course(course);
+  }
+}
+
+/*
+ * These are routines that need to be done on interrupts but don't belong in
+ * the redraw routine and particularly don't belong in the daemon.
+ */
+
+void
+auto_features()
+{
+  selfdestruct_countdown();
+
+  warp_powerup();
+
+  /* provide a refit countdown 4/6/92 TC */
+  refit_countdown();
+
+  /* provide a war declaration countdown 4/6/92 TC */
+  backstab_countdown();
+
+  /* give certain information about bombing or beaming */
+  bombing_info();
+
+  operate_transporters();
+
+  if (me->p_flags & PFREPAIR)
+  {
+    if ((me->p_damage == 0) && (me->p_shield == me->p_ship.s_maxshield))
+      me->p_flags &= ~PFREPAIR;
+  }
+  if (me->p_status != POBSERVE)
+  {
+    /* these mess up the observer mode */
+    follow_player();
+    follow_planet();
+  }
+
+#if defined(CLUECHECK1) || defined(CLUECHECK2)
+  if (
+#ifdef LEAGUE_SUPPORT
+      !status2->league &&
+#endif
+      configvals->cluecheck)
+    countdown_clue();
+#endif
+}
+
+int
+newcourse(x, y)
+  int x, y;
+{
+  if (x == me->p_x && y == me->p_y)
+    return 0;
+
+  return (int) (atan2((double) (x - me->p_x),
+		      (double) (me->p_y - y)) / 3.14159 * 128.);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/rmove.c	Sat Dec 06 04:37:04 1997 +0000
@@ -0,0 +1,1539 @@
+/*--------------------------------------------------------------------------
+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 <stdio.h>
+#include <signal.h>
+#include <math.h>
+#include "defs.h"
+#include "struct.h"
+#include "data.h"
+#include "weapons.h"
+#include "shmem.h"
+
+#define SIZEOF(s)		(sizeof (s) / sizeof (*(s)))
+#define AVOID_TIME		4
+#define AVOID_CLICKS		200
+
+#define BOREDOM_TIME		1200	/* 10 minutes since last torp fired
+					 * => become hostile to all 4/13/92
+					 * TC */
+
+#define AVOID_STAR 8000		/* Distance from star within which collision
+				 * avoidance is invoked. - MAK, 16-Jun-93 */
+#define AVOID_MELT 2000		/* Distance from star within which collision
+				 * prevention is invoked. - MAK, 16-Jun-93 */
+
+#define NORMALIZE(d) 		(((d) + 256) % 256)
+
+#define E_INTRUDER	0x01
+#define E_TSHOT		0x02
+#define E_PSHOT 	0x04
+#define E_TRACT 	0x08
+#define NOENEMY (struct Enemy *) -1
+
+struct Enemy
+{
+  int e_info;
+  int e_dist;
+  unsigned char e_course;	/* course to enemy */
+  unsigned char e_edir;		/* enemy's current heading */
+  unsigned char e_tcourse;	/* torpedo intercept course to enemy */
+  unsigned int e_flags;
+  int e_tractor;		/* who he's tractoring/pressoring */
+  int e_phrange;		/* his phaser range */
+  unsigned int e_hisflags;	/* his pflags. bug fix: 6/24/92 TC */
+};
+
+static int avoidTime;
+
+#define MESSFUSEVAL 200		/* maint: removed trailing ';' 6/22/92 TC */
+static int messfuse = MESSFUSEVAL;
+static char rmessage[110];
+static char tmessage[110];
+static char *rmessages[] = {
+  /* I got bored and actually made it say something: 'DIE SCUM' */
+  "1000100 1001001 1000101 100000 1010011 1000011 1010101 1001101 !"
+  "Crush, Kill, DESTROY!!",
+  "Run coward!",
+  "Hey!  Come on you Hoser!  I dare you!",
+  "Resistance is useless!",
+  "Dry up and blow away you weenie!",
+  "Go ahead, MAKE MY DAY!",
+  "Just hit '<shift> Q' ... and spare both of us the trouble",
+  "Is that REALLY you Kurt?",
+  "I have you now!",
+  "By the way, any last requests?",
+  "Dropping your shields is considered a peaceful act.",
+  "Drop your shields, and I MAY let you live ...",
+  "Don't you have midterms coming up or something?",
+  "Ya wanna Tango baby?",
+  "Hey! Outta my turf you filthy $t!",
+  "I seeeee you...",
+  "I claim this space for the $f.",
+  "Give up fool ... you're meat.",
+  "And another one bites the dust ...",
+  "Surrender ... NOW!",
+  "Hey!  Have you heard about the clever $t?  No?.. Me neither.",
+  "You have been registered for termination.",
+  "This'll teach you to mind your own business!",
+  "Man, you stupid $ts never learn!",
+  "ALL RIGHT, enough goofing off ... you're toast buster!",
+  "You pesky humans just NEVER give up, do you?",
+  "You're actually paying money so you can play this game?",
+  "My job is to put over-zealous newbies like you out of your misery.",
+  "How can you stand to be $T?!?  What a hideous life!",
+  "All $ts are losers!",
+  "$ts all suck.  Come join the $f!",
+  "The $f shall crush all filthy $ts like you!",
+  "TWINK",
+  "How can your friends stand to let you live?",
+  "Happy, Happy, Joy, Joy."
+};
+
+char *termie_messages[] = {
+  "$n:  Hasta la vista, Baby.",
+  "Come quietly, or there will be trouble. [thump] [thump]",
+  "Make your peace with GOD.",
+  "$n:  Say your prayers",
+  "This galaxy isn't big enough for the two of us, $n.",
+  "$n, I have a warrant for your arrest.",
+  "$n, self-destruct now.",
+  "Coming through.  Out of my way.",
+  "You feel lucky, punk?",
+  "Killing is our business.  Business is good.",
+  "$n, Die.  You have 10 seconds to comply.",
+  "You can run $n, but you can't hide!",
+  "Sorry, I am out of cool quotes.  Just die.",
+  "$n: duck."
+};
+
+extern int debug;
+extern int hostile;
+extern int sticky;
+extern int practice;
+extern int polymorphic;
+
+extern int startplanet;		/* CRD feature - MAK,  2-Jun-93 */
+
+extern int target;		/* robotII.c 7/27/91 TC */
+extern int phrange;		/* robotII.c 7/31/91 TC */
+extern int trrange;		/* robotII.c 8/2/91 TC */
+
+extern int dogslow;		/* robotII.c 8/9/91 TC */
+extern int dogfast;
+extern int runslow;
+extern int runfast;
+extern int closeslow;
+extern int closefast;
+
+unsigned char getcourse();
+char *robo_message();
+char *termie_message();		/* added 8/2/91 TC */
+
+
+extern void (*r_signal()) ();
+#ifndef	IRIX
+extern int fprintf();
+#endif
+extern unsigned int sleep();
+void exitRobot();
+extern void move_player();
+void messAll();
+int phaser_plasmas();
+void pmessage2();
+int do_repair();
+void go_home();
+extern int ntorp();
+extern int repair_off();
+extern int cloak_off();
+extern int phaser();
+extern int angdist();
+int isTractoringMe();
+extern int pressor_player();
+extern int tractor_player();
+int projectDamage();
+extern int set_course();
+extern int cloak_on();
+extern int shield_up();
+extern void detothers();
+extern int shield_down();
+extern int set_speed();
+extern int lock_planet();
+extern int orbit();
+extern int repair();
+#ifdef ROBOTSTATS
+extern void save_robot();
+#endif
+
+void
+rmove()
+{
+  register struct player *j;
+  register struct planet *l;
+  register int i;
+  register int burst;
+  register int numHits, tDir;
+  int avDir;
+  extern struct Enemy *get_nearest();
+  struct Enemy *enemy_buf;
+  struct player *enemy;
+  static int clock = 0;
+  static int avoid[2] = {-32, 32};
+  int no_cloak;
+  char towhom[80];
+  int timer;
+  static int lastTorpped = 0;	/* when we last fired a torp 4/13/92 TC */
+
+  clock++;
+  /* Check that I'm alive */
+  if (me->p_status == PEXPLODE)
+  {
+    r_signal(SIGALRM, SIG_IGN);
+    if (debug)
+      fprintf(stderr, "Robot: Augh! exploding.\n");
+
+
+    /* hack:  get rid of robot processes! */
+
+    if (1)
+    {
+      sleep(3);
+    }
+    else
+    {
+      while (me->p_status == PEXPLODE);
+    }
+    if (debug)
+      fprintf(stderr, "Robot: done exploding.\n");
+    if (1)
+    {
+      sleep(3);
+    }
+    else
+    {
+      while (me->p_ntorp > 0);
+    }
+    if (debug)
+      fprintf(stderr, "Robot: torps are gone.\n");
+    exitRobot();
+  }
+  if (me->p_status == PDEAD)
+  {
+    r_signal(SIGALRM, SIG_IGN);
+    /*
+     * me->p_status = PFREE; move_player(me->p_no, -1,-1, 1); exit(0);
+     */
+    exitRobot();
+  }
+  /* keep ghostbuster away */
+  me->p_ghostbuster = 0;
+
+  timer = 0;
+  for (i = 0, j = &players[i]; i < MAXPLAYER; i++, j++)
+  {
+    if ((j->p_status != PFREE) && !(j->p_flags & PFROBOT))
+      timer = 1;
+  }
+  if (!timer && !sticky)
+  {
+    r_signal(SIGALRM, SIG_IGN);
+    me->p_status = PFREE;
+    move_player(me->p_no, -1, -1, 1);
+    exit(0);
+  }
+  /* if I'm a Terminator, quit if he quits, and quit if he dies and */
+  /* I'm not "sticky" (-s) */
+
+  if (target >= 0)
+  {
+    if (players[target].p_status == PFREE)
+    {				/* he went away */
+      me->p_status = PEXPLODE;
+      return;
+    }
+    if ((!sticky) && (players[target].p_status != PALIVE))
+    {				/* he died */
+      me->p_status = PEXPLODE;
+      return;
+    }
+  }
+  /*
+   * If it's been BOREDOM_TIME updates since we fired a torp, become hostile
+   * to all races, if we aren't already, and if we're not a practice robot
+   * (intended for guardian bots). 4/13/92 TC
+   */
+
+  if ((clock - lastTorpped > BOREDOM_TIME) && (!practice) && (!hostile) &&
+      (me->p_team != 0))
+  {
+    messAll("Bored, Bored, Bored.");
+    hostile++;
+    declare_war(ALLTEAM);
+  }
+  /* Our first priority is to phaser plasma torps in nearby vicinity... */
+  /* If we fire, we aren't allowed to cloak... */
+  no_cloak = phaser_plasmas();
+
+  /* Find an enemy */
+
+  enemy_buf = get_nearest();
+
+  if ((enemy_buf != NULL) && (enemy_buf != NOENEMY))
+  {				/* Someone to kill */
+    enemy = &players[enemy_buf->e_info];
+    if (((lrand48() % messfuse) == 0) &&
+	(ihypot(me->p_x - enemy->p_x, me->p_y - enemy->p_y) < 20000))
+    {
+      /* change 5/10/21 TC ...neut robots don't message */
+      messfuse = MESSFUSEVAL;
+      if (me->p_team != 0)
+      {
+	sprintf(towhom, " %s->%s",
+		twoletters(&players[me->p_no]),
+		twoletters(&players[enemy->p_no]));
+	pmessage2(robo_message(enemy), enemy->p_no,
+		  MINDIV, towhom, me->p_no);
+      }
+      else if (target >= 0)
+      {
+	/*
+	 * MAK, 28-Apr-92 - send termie messages only to target
+	 * messAll(termie_message(enemy));
+	 */
+	sprintf(towhom, " %s->%s",
+		twoletters(&players[me->p_no]),
+		twoletters(&players[enemy->p_no]));
+	pmessage2(termie_message(enemy), enemy->p_no,
+		  MINDIV, towhom, me->p_no);
+      }
+    }
+    else if (--messfuse == 0)
+      messfuse = 1;
+    timer = 0;
+    if (debug)
+      fprintf(stderr, "%d) noticed %d\n", me->p_no, enemy_buf->e_info);
+  }
+  else if (enemy_buf == NOENEMY)
+  {				/* no more players. wait 1 minute. */
+    if (do_repair())
+    {
+      return;
+    }
+    go_home(0);
+    /*
+     * if (debug) fprintf(stderr, "%d) No players in game.\n", me->p_no);
+     */
+    return;
+  }
+  else if (enemy_buf == 0)
+  {				/* no one hostile */
+    /*
+     * if (debug) fprintf(stderr, "%d) No hostile players in game.\n",
+     * me->p_no);
+     */
+    if (do_repair())
+    {
+      return;
+    }
+    go_home(0);
+    timer = 0;
+    return;
+  }
+  /*
+   * Note a bug in this algorithm: * Once someone dies, he is forgotten.
+   * This makes robots particularly easy *  to kill on a suicide run, where
+   * you aim to where you think he will turn *  as you die.  Once dead, the
+   * robot will ignore you and all of your *  active torpedoes!
+   */
+
+  /*
+   * Algorithm: * We have an enemy. * First priority: shoot at target in
+   * range. * Second: Dodge stars, torps, and plasma torps. * Third: Get away
+   * if we are damaged. * Fourth: repair. * Fifth: attack.
+   */
+
+  /*
+   * * If we are a practice robot, we will do all but the second.  One * will
+   * be modified to shoot poorly and not use phasers.
+   */
+  /* Fire weapons!!! */
+  /*
+   * get_nearest() has already determined if torpedoes and phasers * will
+   * hit.  It has also determined the courses which torps and * phasers
+   * should be fired.  If so we will go ahead and shoot here. * We will lose
+   * repair and cloaking for the rest of this interrupt. * if we fire here.
+   */
+
+  if (practice)
+  {
+    no_cloak = 1;
+    if (enemy_buf->e_flags & E_TSHOT)
+    {
+      /*
+       * if (debug) fprintf(stderr, "%d) firing torps\n", me->p_no);
+       */
+      for (burst = 0; (burst < 3) && (me->p_ntorp < MAXTORP); burst++)
+      {
+	ntorp(enemy_buf->e_tcourse, TMOVE);
+      }
+    }
+  }
+  else
+  {
+    if (enemy_buf->e_flags & E_TSHOT)
+    {
+      /*
+       * if (debug) fprintf(stderr, "%d) firing torps\n", me->p_no);
+       */
+      for (burst = 0; (burst < 2) && (me->p_ntorp < MAXTORP); burst++)
+      {
+	repair_off();
+	cloak_off();
+	ntorp(enemy_buf->e_tcourse, TMOVE);	/* was TSTRAIGHT 8/9/91 TC */
+	no_cloak++;
+	lastTorpped = clock;	/* record time of firing 4/13/92 TC */
+      }
+    }
+    if (enemy_buf->e_flags & E_PSHOT)
+    {
+      /*
+       * if (debug) fprintf(stderr, "%d) phaser firing\n", me->p_no);
+       */
+      no_cloak++;
+      repair_off();
+      cloak_off();
+      phaser(enemy_buf->e_course);
+    }
+  }
+
+  /* auto pressor 7/27/91 TC */
+  /* tractor/pressor rewritten on 5/1/92... glitches galore :-| TC */
+
+  /*
+   * whoa, too close for comfort, or he's tractoring me, or headed in for me,
+   * or I'm hurt
+   */
+
+  /* a little tuning -- 0.8 on phrange and +/- 90 degrees in for pressor */
+
+  /*
+   * pressor_player(-1); this didn't do anything before, so we'll let the
+   * pressors disengage by themselves 5/1/92 TC
+   */
+  if (enemy_buf->e_flags & E_TRACT)
+  {				/* if pressorable */
+    if (((enemy_buf->e_dist < 0.8 * enemy_buf->e_phrange) &&
+	 (angdist(enemy_buf->e_edir, enemy_buf->e_course) > 64)) ||
+	(isTractoringMe(enemy_buf)) ||
+	(me->p_damage > 0))
+    {
+      if (!(enemy->p_flags & PFCLOAK))
+      {
+	if (debug)
+	  fprintf(stderr, "%d) pressoring %d\n", me->p_no,
+		  enemy_buf->e_info);
+	pressor_player(enemy->p_no);
+	no_cloak++;
+	repair_off();
+	cloak_off();
+      }
+    }
+  }
+  /* auto tractor 7/31/91 TC */
+
+  /* tractor if not pressoring and... */
+
+  /* tractor if: in range, not too close, and not headed +/- 90 degrees */
+  /* of me, and I'm not hurt */
+
+  if ((!(me->p_flags & PFPRESS)) &&
+      (enemy_buf->e_flags & E_TRACT) &&
+      (angdist(enemy_buf->e_edir, enemy_buf->e_course) < 64) &&
+      (enemy_buf->e_dist > 0.7 * enemy_buf->e_phrange))
+  {
+    if (!(me->p_flags & PFTRACT))
+    {
+      if (debug)
+	fprintf(stderr, "%d) tractoring %d\n", me->p_no,
+		enemy_buf->e_info);
+      tractor_player(enemy->p_no);
+      no_cloak++;
+    }
+  }
+  else
+    tractor_player(-1);		/* otherwise don't tractor */
+
+  /* Avoid stars - MAK, 16-Jun-93 */
+  /*
+   * This section of code allows robots to avoid crashing into stars. Within
+   * a specific range (AVOID_STAR), they will check to see if their current
+   * course will take them close to the star.  If so, course will be adjusted
+   * to avoid the star. Within a smaller range (AVOID_MELT), course is
+   * adjusted directly away from the star. Collision avoidance is all they
+   * will do for this round, other than shooting.
+   */
+  for (i = 0, l = &planets[0]; i < NUMPLANETS; i++, l++)
+  {
+    if (PL_TYPE(*l) == PLSTAR)
+    {
+      int dx, dy, stardir, newcourse = -1;
+      dx = ABS(l->pl_x - me->p_x);
+      dy = ABS(l->pl_y - me->p_y);
+      /* Avoid over box rather than circle to speed calculations */
+      if (dx < AVOID_STAR && dy < AVOID_STAR)
+      {
+	stardir = getcourse(l->pl_x, l->pl_y);
+
+	if (dx < AVOID_MELT && dy < AVOID_MELT)
+	{
+	  /* Emergency! Way too close! */
+	  newcourse = NORMALIZE(stardir - 128);
+	  if (debug)
+	  {
+	    fprintf(stderr, "Steering away from star %s, dir = %d\n",
+		    l->pl_name, newcourse);
+	  }
+	}
+	else if (angdist(me->p_dir, stardir) < 16)
+	{
+	  /* Heading towards star, so adjust course. */
+	  newcourse =
+	    NORMALIZE((me->p_dir < stardir) ? stardir - 32 : stardir + 32);
+	  if (debug)
+	  {
+	    fprintf(stderr, "Adjusting course away from star %s, dir = %d\n",
+		    l->pl_name, newcourse);
+	  }
+	}
+	if (newcourse != -1)
+	{			/* Change course and speed */
+	  me->p_desdir = newcourse;
+	  if (angdist(me->p_desdir, me->p_dir) > 64)
+	    me->p_desspeed = dogslow;
+	  else
+	    me->p_desspeed = dogfast;
+	  return;
+	}
+      }
+    }
+  }
+
+  /* Avoid torps */
+  /*
+   * This section of code allows robots to avoid torps. * Within a specific
+   * range they will check to see if * any of the 'closest' enemies torps
+   * will hit them. * If so, they will evade for four updates. * Evading is
+   * all they will do for this round, other than shooting.
+   */
+
+  if (!practice)
+  {
+    if ((enemy->p_ntorp < 5))
+    {
+      if ((enemy_buf->e_dist < 15000) || (avoidTime > 0))
+      {
+	numHits = projectDamage(enemy->p_no, &avDir);
+	if (debug)
+	{
+	  /*
+	   * fprintf(stderr, "%d hits expected from %d from dir = %d\n",
+	   * numHits, enemy->p_no, avDir);
+	   */
+	}
+	if (numHits == 0)
+	{
+	  if (--avoidTime > 0)
+	  {			/* we may still be avoiding */
+	    if (angdist(me->p_desdir, me->p_dir) > 64)
+	      me->p_desspeed = dogslow;
+	    else
+	      me->p_desspeed = dogfast;
+	    return;
+	  }
+	}
+	else
+	{
+	  /* Actually avoid Torps */
+	  avoidTime = AVOID_TIME;
+	  tDir = avDir - me->p_dir;
+	  /* put into 0->255 range */
+	  tDir = NORMALIZE(tDir);
+	  if (debug)
+	    fprintf(stderr, "mydir = %d avDir = %d tDir = %d q = %d\n",
+		    me->p_dir, avDir, tDir, tDir / 64);
+	  switch (tDir / 64)
+	  {
+	   case 0:
+	   case 1:
+	    set_course(NORMALIZE(avDir + 64));
+	    break;
+	   case 2:
+	   case 3:
+	    set_course(NORMALIZE(avDir - 64));
+	    break;
+	  }
+	  if (!no_cloak)
+	    cloak_on();
+
+	  if (angdist(me->p_desdir, me->p_dir) > 64)
+	    me->p_desspeed = dogslow;
+	  else
+	    me->p_desspeed = dogfast;
+
+	  shield_up();
+	  detothers();		/* hmm */
+	  if (debug)
+	    fprintf(stderr, "evading to dir = %d\n", me->p_desdir);
+	  return;
+	}
+      }
+    }
+    /*
+     * Trying another scheme. * Robot will keep track of the number of torps
+     * a player has * launched.  If they are greater than say four, the robot
+     * will * veer off immediately.  Seems more humanlike to me.
+     */
+
+    else if (enemy_buf->e_dist < 15000)
+    {
+      if (--avoidTime > 0)
+      {				/* we may still be avoiding */
+	if (angdist(me->p_desdir, me->p_dir) > 64)
+	  me->p_desspeed = dogslow;
+	else
+	  me->p_desspeed = dogfast;
+	return;
+      }
+      if (lrand48() % 2)
+      {
+	me->p_desdir = NORMALIZE(enemy_buf->e_course - 64);
+	avoidTime = AVOID_TIME;
+      }
+      else
+      {
+	me->p_desdir = NORMALIZE(enemy_buf->e_course + 64);
+	avoidTime = AVOID_TIME;
+      }
+      if (angdist(me->p_desdir, me->p_dir) > 64)
+	me->p_desspeed = dogslow;
+      else
+	me->p_desspeed = dogfast;
+      shield_up();
+      return;
+    }
+  }
+  /* Run away */
+  /*
+   * The robot has taken damage.  He will now attempt to run away from * the
+   * closest player.  This obviously won't do him any good if there * is
+   * another player in the direction he wants to go. * Note that the robot
+   * will not run away if he dodged torps, above. * The robot will lower his
+   * shields in hopes of repairing some damage.
+   */
+
+#define STARTDELTA 5000		/* ships appear +/- delta of home planet */
+
+  if (me->p_damage > 0 && enemy_buf->e_dist < 13000)
+  {
+    if (me->p_etemp > 900)	/* 90% of 1000 */
+      me->p_desspeed = runslow;
+    else
+      me->p_desspeed = runfast;
+    if (!no_cloak)
+      cloak_on();
+    repair_off();
+    shield_down();
+    set_course(enemy_buf->e_course - 128);
+    if (debug)
+      fprintf(stderr, "%d(%d)(%d/%d) running from %s %16s damage (%d/%d) dist %d\n",
+	      me->p_no,
+	      (int) me->p_kills,
+	      me->p_damage,
+	      me->p_shield,
+	      twoletters(enemy),
+	      enemy->p_login,
+	      enemy->p_damage,
+	      enemy->p_shield,
+	      enemy_buf->e_dist);
+    return;
+  }
+  /* Repair if necessary (we are safe) */
+  /*
+   * The robot is safely away from players.  It can now repair in peace. * It
+   * will try to do so now.
+   */
+
+  if (do_repair())
+  {
+    return;
+  }
+  /* Attack. */
+  /*
+   * The robot has nothing to do.  It will check and see if the nearest *
+   * enemy fits any of its criterion for attack.  If it does, the robot *
+   * will speed in and deliver a punishing blow.  (Well, maybe)
+   */
+
+  if ((enemy_buf->e_flags & E_INTRUDER) || (enemy_buf->e_dist < 15000)
+      || (hostile))
+  {
+    if ((!no_cloak) && (enemy_buf->e_dist < 10000))
+      cloak_on();
+    shield_up();
+    if (debug)
+      fprintf(stderr, "%d(%d)(%d/%d) attacking %s %16s damage (%d/%d) dist %d\n",
+	      me->p_no,
+	      (int) me->p_kills,
+	      me->p_damage,
+	      me->p_shield,
+	      twoletters(enemy),
+	      enemy->p_login,
+	      enemy->p_damage,
+	      enemy->p_shield,
+	      enemy_buf->e_dist);
+
+    if (enemy_buf->e_dist < 15000)
+    {
+      set_course(enemy_buf->e_course +
+		 avoid[(clock / AVOID_CLICKS) % SIZEOF(avoid)]);
+      if (angdist(me->p_desdir, me->p_dir) > 64)
+	set_speed(closeslow, 1);
+      else
+	set_speed(closefast, 1);
+    }
+    else
+    {
+      me->p_desdir = enemy_buf->e_course;
+      if (angdist(me->p_desdir, me->p_dir) > 64)
+	set_speed(closeslow, 1);
+      if (target >= 0)		/* 7/27/91 TC */
+	set_speed(12, 1);
+      else if (me->p_etemp > 900)	/* 90% of 1000 */
+	set_speed(runslow, 1);
+      else
+	set_speed(runfast, 1);
+    }
+  }
+  else
+  {
+    go_home(enemy_buf);
+  }
+}
+
+unsigned char
+getcourse(x, y)
+  int x, y;
+{
+  return ((unsigned char) (int) (atan2((double) (x - me->p_x),
+				 (double) (me->p_y - y)) / 3.14159 * 128.));
+}
+
+/* the 100000's here were once GWIDTHs... */
+struct
+{
+  int x;
+  int y;
+}   center[] =
+{
+  {
+
+    100000 / 2, 100000 / 2
+  },				/* change 5/20/91 TC was {0,0} */
+  {
+    100000 / 4, 100000 * 3 / 4
+  },				/* Fed */
+  {
+    100000 / 4, 100000 / 4
+  },				/* Rom */
+  {
+    0, 0
+  },
+  {
+    100000 *3 / 4, 100000 / 4
+  }  ,				/* Kli */
+  {
+    0, 0
+  }  ,
+  {
+    0, 0
+  }  ,
+  {
+    0, 0
+  }  ,
+  {
+    100000 *3 / 4, 100000 * 3 / 4
+  }
+};				/* Ori */
+
+/*
+ * This function means that the robot has nothing better to do. If there are
+ * hostile players in the game, it will try to get as close to them as it
+ * can, while staying in its own space. Otherwise, it will head to the center
+ * of its own space.
+ */
+/* CRD feature: robots now hover near their start planet - MAK,  2-Jun-93 */
+
+#define GUARDDIST 8000
+
+void
+go_home(ebuf)
+  struct Enemy *ebuf;
+{
+  int x, y;
+  double dx, dy;
+  struct player *j;
+
+  if (ebuf == 0)
+  {				/* No enemies */
+    /*
+     * if (debug) fprintf(stderr, "%d) No enemies\n", me->p_no);
+     */
+    if (target >= 0)
+    {
+      /* First priority, current target (if any) */
+      j = &players[target];
+      x = j->p_x;
+      y = j->p_y;
+    }
+    else if (startplanet == -1)
+    {
+      /* No start planet, so go to center of galaxy */
+      x = (GWIDTH / 2);
+      y = (GWIDTH / 2);
+    }
+    else
+    {
+      /* Return to start planet */
+      x = planets[startplanet].pl_x + (lrand48() % 2000) - 1000;
+      y = planets[startplanet].pl_y + (lrand48() % 2000) - 1000;
+    }
+  }
+  else
+  {				/* Let's get near him */
+    j = &players[ebuf->e_info];
+    x = j->p_x;
+    y = j->p_y;
+
+    if (startplanet != -1)
+    {
+      /* Get between enemy and planet */
+      int px, py;
+      double theta;
+
+      px = planets[startplanet].pl_x;
+      py = planets[startplanet].pl_y;
+      theta = atan2((double) (y - py), (double) (x - px));
+      x = px + GUARDDIST * cos(theta);
+      y = py + GUARDDIST * sin(theta);
+    }
+  }
+  /*
+   * if (debug) fprintf(stderr, "%d) moving towards (%d/%d)\n", me->p_no, x,
+   * y);
+   */
+
+  /*
+   * Note that I've decided that robots should never stop moving. * It makes
+   * them too easy to kill
+   */
+
+  me->p_desdir = getcourse(x, y);
+  if (angdist(me->p_desdir, me->p_dir) > 64)
+    set_speed(dogslow, 1);
+  else if (me->p_etemp > 900)	/* 90% of 1000 */
+    set_speed(runslow, 1);
+  else
+  {
+    dx = x - me->p_x;
+    dy = y - me->p_y;
+    set_speed((ihypot((int) dx, (int) dy) / 5000) + 3, 1);
+  }
+  cloak_off();
+}
+
+int
+phaser_plasmas()
+{
+  register struct plasmatorp *pt;
+  register int i;
+  int myphrange;
+
+  myphrange = phrange;		/* PHASEDIST * me->p_ship.s_phaserdamage /
+				 * 100; */
+  for (i = 0, pt = &plasmatorps[0]; i < MAXPLASMA * MAXPLAYER; i++, pt++)
+  {
+    if (pt->pt_status != PTMOVE)
+      continue;
+    if (i == me->p_no)
+      continue;
+    if (!(pt->pt_war & me->p_team) && !(me->p_hostile & pt->pt_team))
+      continue;
+    if (abs(pt->pt_x - me->p_x) > myphrange)
+      continue;
+    if (abs(pt->pt_y - me->p_y) > myphrange)
+      continue;
+    if (ihypot(pt->pt_x - me->p_x, pt->pt_y - me->p_y) > myphrange)
+      continue;
+    repair_off();
+    cloak_off();
+    phaser(getcourse(pt->pt_x, pt->pt_y));
+    return 1;			/* was this missing? 3/25/92 TC */
+    break;
+  }
+  return 0;			/* was this missing? 3/25/92 TC */
+}
+
+int
+projectDamage(eNum, dirP)
+  int eNum;
+  int *dirP;
+{
+  register int i, j, numHits = 0, mx, my, tx, ty, dx, dy;
+  double tdx, tdy, mdx, mdy;
+  register struct torp *t;
+
+  *dirP = 0;
+  for (i = 0, t = &torps[eNum * MAXTORP]; i < MAXTORP; i++, t++)
+  {
+    if (t->t_status == TFREE)
+      continue;
+    tx = t->t_x;
+    ty = t->t_y;
+    mx = me->p_x;
+    my = me->p_y;
+    tdx = (double) t->t_speed * Cos[t->t_dir] * WARP1;
+    tdy = (double) t->t_speed * Sin[t->t_dir] * WARP1;
+    mdx = (double) me->p_speed * Cos[me->p_dir] * WARP1;
+    mdy = (double) me->p_speed * Sin[me->p_dir] * WARP1;
+    for (j = t->t_fuse; j > 0; j--)
+    {
+      tx += tdx;
+      ty += tdy;
+      mx += mdx;
+      my += mdy;
+      dx = tx - mx;
+      dy = ty - my;
+      if (ABS(dx) < EXPDIST && ABS(dy) < EXPDIST)
+      {
+	numHits++;
+	*dirP += t->t_dir;
+	break;
+      }
+    }
+  }
+  if (numHits > 0)
+    *dirP /= numHits;
+  return (numHits);
+}
+
+int
+isTractoringMe(enemy_buf)
+  struct Enemy *enemy_buf;
+{
+  return ((enemy_buf->e_hisflags & PFTRACT) &&	/* bug fix: was using */
+	  !(enemy_buf->e_hisflags & PFPRESS) &&	/* e_flags 6/24/92 TC */
+	  (enemy_buf->e_tractor == me->p_no));
+}
+
+struct Enemy ebuf;
+
+struct Enemy *
+get_nearest()
+{
+  int pcount = 0;
+  register int i;
+  register struct player *j;
+  int intruder = 0;
+  int tdist;
+  double dx, dy;
+  double vxa, vya, l;		/* Used for trap shooting */
+  double vxt, vyt;
+  double vxs, vys;
+  double dp;
+
+  /* Find an enemy */
+  ebuf.e_info = me->p_no;
+  ebuf.e_dist = GWIDTH + 1;
+
+  pcount = 0;			/* number of human players in game */
+
+  if (target >= 0)
+  {
+    j = &players[target];
+    if (!((me->p_swar | me->p_hostile) & j->p_team))
+      declare_war(players[target].p_team);	/* make sure we're at war
+						 * 7/31/91 TC */
+
+    /* We have an enemy */
+    /* Get his range */
+    dx = j->p_x - me->p_x;
+    dy = j->p_y - me->p_y;
+    tdist = ihypot((int) dx, (int) dy);
+
+    if (j->p_status != POUTFIT)
+    {				/* ignore target if outfitting */
+      ebuf.e_info = target;
+      ebuf.e_dist = tdist;
+      ebuf.e_flags &= ~(E_INTRUDER);
+    }
+    /* need a loop to find hostile ships */
+    /* within tactical range */
+
+    for (i = 0, j = &players[i]; i < MAXPLAYER; i++, j++)
+    {
+      if ((j->p_status != PALIVE) || (j == me) ||
+	  ((j->p_flags & PFROBOT) && (!hostile)))
+	continue;
+      else
+	pcount++;		/* Other players in the game */
+      if (((j->p_swar | j->p_hostile) & me->p_team)
+	  || ((me->p_swar | me->p_hostile) & j->p_team))
+      {
+	/* We have an enemy */
+	/* Get his range */
+	dx = j->p_x - me->p_x;
+	dy = j->p_y - me->p_y;
+	tdist = ihypot((int) dx, (int) dy);
+
+	/* if target's teammate is too close, mark as nearest */
+
+	if ((tdist < ebuf.e_dist) && (tdist < 15000))
+	{
+	  ebuf.e_info = i;
+	  ebuf.e_dist = tdist;
+	  ebuf.e_flags &= ~(E_INTRUDER);
+	}
+      }				/* end if */
+    }				/* end for */
+  }
+  else
+  {				/* no target */
+    /* avoid dead slots, me, other robots (which aren't hostile) */
+    for (i = 0, j = &players[i]; i < MAXPLAYER; i++, j++)
+    {
+      if ((j->p_status != PALIVE) || (j == me) ||
+	  ((j->p_flags & PFROBOT) && (!hostile)))
+	continue;
+      else
+	pcount++;		/* Other players in the game */
+      if (((j->p_swar | j->p_hostile) & me->p_team)
+	  || ((me->p_swar | me->p_hostile) & j->p_team))
+      {
+	/* We have an enemy */
+	/* Get his range */
+	dx = j->p_x - me->p_x;
+	dy = j->p_y - me->p_y;
+	tdist = ihypot((int) dx, (int) dy);
+
+	/* Check to see if ship is near our planet. */
+	if (startplanet != -1)
+	{
+	  int px, py;
+	  px = planets[startplanet].pl_x;
+	  py = planets[startplanet].pl_y;
+
+	  intruder = (ihypot(j->p_x - px, j->p_y - py)
+		      < GUARDDIST);
+	}
+	if (tdist < ebuf.e_dist)
+	{
+	  ebuf.e_info = i;
+	  ebuf.e_dist = tdist;
+	  if (intruder)
+	    ebuf.e_flags |= E_INTRUDER;
+	  else
+	    ebuf.e_flags &= ~(E_INTRUDER);
+	}
+      }				/* end if */
+    }				/* end for */
+  }				/* end else */
+  if (pcount == 0)
+  {
+    return (NOENEMY);		/* no players in game */
+  }
+  else if (ebuf.e_info == me->p_no)
+  {
+    return (0);			/* no hostile players in the game */
+  }
+  else
+  {
+    j = &players[ebuf.e_info];
+
+    /* Get torpedo course to nearest enemy */
+    ebuf.e_flags &= ~(E_TSHOT);
+
+    vxa = (j->p_x - me->p_x);
+    vya = (j->p_y - me->p_y);
+    l = ihypot((int) vxa, (int) vya);	/* Normalize va */
+    if (l != 0)
+    {
+      vxa /= l;
+      vya /= l;
+    }
+    vxs = (Cos[j->p_dir] * j->p_speed) * WARP1;
+    vys = (Sin[j->p_dir] * j->p_speed) * WARP1;
+    dp = vxs * vxa + vys * vya;	/* Dot product of (va vs) */
+    dx = vxs - dp * vxa;
+    dy = vys - dp * vya;
+    l = hypot(dx, dy);		/* Determine how much speed is required */
+    dp = (float) (me->p_ship.s_torp.speed * WARP1);
+    l = (dp * dp - l * l);
+    if (l > 0)
+    {
+      double he_x, he_y, area;
+
+      /* Only shoot if within distance */
+      he_x = j->p_x + Cos[j->p_dir] * j->p_speed * 50 * WARP1;
+      he_y = j->p_y + Sin[j->p_dir] * j->p_speed * 50 * WARP1;
+      area = 50 * me->p_ship.s_torp.speed * WARP1;
+      if (ihypot(he_x - me->p_x, he_y - me->p_y) < area)
+      {
+	l = sqrt(l);
+	vxt = l * vxa + dx;
+	vyt = l * vya + dy;
+	ebuf.e_flags |= E_TSHOT;
+	ebuf.e_tcourse = getcourse((int) vxt + me->p_x, (int) vyt + me->p_y);
+      }
+    }
+    /* Get phaser shot status */
+    if (ebuf.e_dist < 0.8 * phrange)
+      ebuf.e_flags |= E_PSHOT;
+    else
+      ebuf.e_flags &= ~(E_PSHOT);
+
+    /* Get tractor/pressor status */
+    if (ebuf.e_dist < trrange)
+      ebuf.e_flags |= E_TRACT;
+    else
+      ebuf.e_flags &= ~(E_TRACT);
+
+
+    /* get his phaser range */
+    ebuf.e_phrange = PHASEDIST * j->p_ship.s_phaser.damage / 100;
+
+    /* get course info */
+    ebuf.e_course = getcourse(j->p_x, j->p_y);
+    ebuf.e_edir = j->p_dir;
+    ebuf.e_hisflags = j->p_flags;
+    ebuf.e_tractor = j->p_tractor;
+    /*
+     * if (debug) fprintf(stderr, "Set course to enemy is %d (%d)\n",
+     * (int)ebuf.e_course, (int) ebuf.e_course * 360 / 256);
+     */
+
+    /* check to polymorph */
+
+    if ((polymorphic) && (j->p_ship.s_type != me->p_ship.s_type) &&
+	(j->p_ship.s_type != ATT))
+    {				/* don't polymorph to ATT 4/8/92 TC */
+      extern int config();
+      extern int getship();
+      int old_shield;
+      int old_damage;
+      old_shield = me->p_ship.s_maxshield;
+      old_damage = me->p_ship.s_maxdamage;
+
+      getship(&(me->p_ship), j->p_ship.s_type);
+      config();
+      if (me->p_speed > me->p_ship.s_imp.maxspeed)
+	me->p_speed = me->p_ship.s_imp.maxspeed;
+      me->p_shield = (me->p_shield * (float) me->p_ship.s_maxshield)
+	/ (float) old_shield;
+      me->p_damage = (me->p_damage * (float) me->p_ship.s_maxdamage)
+	/ (float) old_damage;
+    }
+    return (&ebuf);
+  }
+}
+
+struct planet *
+get_nearest_planet()
+{
+  register int i;
+  register struct planet *l;
+  register struct planet *nearest;
+  int dist = GWIDTH;		/* Manhattan distance to nearest planet */
+  int ldist;
+
+  nearest = &planets[0];
+  for (i = 0, l = &planets[i]; i < NUMPLANETS; i++, l++)
+  {
+    if ((ldist = (abs(me->p_x - l->pl_x) + abs(me->p_y - l->pl_y))) <
+	dist)
+    {
+      dist = ldist;
+      nearest = l;
+    }
+  }
+  return nearest;
+}
+
+int
+do_repair()
+{
+  /* Repair if necessary (we are safe) */
+
+  register struct planet *l;
+  int dx, dy;
+  int dist;
+
+  l = get_nearest_planet();
+  dx = abs(me->p_x - l->pl_x);
+  dy = abs(me->p_y - l->pl_y);
+
+  if (me->p_damage > 0)
+  {
+    if ((me->p_swar | me->p_hostile) & l->pl_owner)
+    {
+      if (l->pl_armies > 0)
+      {
+	if ((dx < PFIREDIST) && (dy < PFIREDIST))
+	{
+	  if (debug)
+	    fprintf(stderr, "%d) on top of hostile planet (%s)\n", me->p_no, l->pl_name);
+	  return (0);		/* can't repair on top of hostile planets */
+	}
+	if (ihypot((int) dx, (int) dy) < PFIREDIST)
+	{
+	  if (debug)
+	    fprintf(stderr, "%d) on top of hostile planet (%s)\n", me->p_no, l->pl_name);
+	  return (0);
+	}
+      }
+      me->p_desspeed = 0;
+    }
+    else
+    {				/* if friendly */
+      if ((l->pl_flags & PLREPAIR) &&
+	  !(me->p_flags & PFORBIT))
+      {				/* oh, repair! */
+	dist = ihypot((int) dx, (int) dy);
+
+	if (debug)
+	  fprintf(stderr, "%d) locking on to planet %d\n",
+		  me->p_no, l->pl_no);
+	cloak_off();
+	shield_down();
+	me->p_desdir = getcourse(l->pl_x, l->pl_y);
+	lock_planet(l->pl_no);
+	me->p_desspeed = 4;
+	if (dist - (ORBDIST / 2) < (11500 * me->p_speed * me->p_speed) /
+	    me->p_ship.s_imp.dec)
+	{
+	  if (me->p_desspeed > 2)
+	  {
+	    set_speed(2, 1);
+	  }
+	}
+	if ((dist < ENTORBDIST) && (me->p_speed <= 2))
+	{
+	  me->p_flags &= ~PFPLLOCK;
+	  orbit();
+	}
+	return (1);
+      }
+      else
+      {				/* not repair, so ignore it */
+	me->p_desspeed = 0;
+      }
+    }
+    shield_down();
+    if (me->p_speed == 0)
+      repair();
+    if (debug)
+      fprintf(stderr, "%d) repairing damage at %d\n",
+	      me->p_no,
+	      me->p_damage);
+    return (1);
+  }
+  else
+  {
+    return (0);
+  }
+}
+
+
+void
+pmessage(str, recip, group, address)
+  char *str;
+  int recip;
+  int group;
+  char *address;
+{
+  pmessage2(str, recip, group, address, 255);
+}
+
+
+void
+pmessage2(str, recip, group, address, from)
+  char *str;
+  int recip;
+  int group;
+  char *address;
+  unsigned char from;
+{
+  struct message *cur;
+  int mesgnum;
+
+  if ((mesgnum = ++(mctl->mc_current)) >= MAXMESSAGE)
+  {
+    mctl->mc_current = 0;
+    mesgnum = 0;
+  }
+  cur = &messages[mesgnum];
+  cur->m_no = mesgnum;
+  cur->m_flags = group;
+  cur->m_recpt = recip;
+  cur->m_from = from;
+  (void) sprintf(cur->m_data, "%-9s %s", address, str);
+  cur->m_flags |= MVALID;
+}
+
+
+char *
+robo_message(enemy)
+  struct player *enemy;
+{
+  int i;
+  char *s, *t;
+
+  i = (lrand48() % (sizeof(rmessages) / sizeof(rmessages[0])));
+
+  for (t = rmessages[i], s = rmessage; *t != '\0'; s++, t++)
+  {
+    switch (*t)
+    {
+     case '$':
+      switch (*(++t))
+      {
+       case '$':
+	*s = *t;
+	break;
+       case 'T':		/* "a Fed" or "a Klingon" ... */
+	if (enemy->p_team != me->p_team &&
+	    enemy->p_team == ORI)
+	{
+	  strcpy(s, "an ");
+	}
+	else
+	{
+	  strcpy(s, "a ");
+	}
+	s = s + strlen(s);
+       case 't':		/* "Fed" or "Orion" */
+	if (enemy->p_team != me->p_team)
+	{
+	  switch (enemy->p_team)
+	  {
+	   case FED:
+	    strcpy(s, "Fed");
+	    break;
+	   case ROM:
+	    strcpy(s, "Romulan");
+	    break;
+	   case KLI:
+	    strcpy(s, "Klingon");
+	    break;
+	   case ORI:
+	    strcpy(s, "Orion");
+	    break;
+	  }
+	}
+	else
+	{
+	  strcpy(s, "TRAITOR");
+	}
+	s = s + strlen(s) - 1;
+	break;
+       case 'f':
+	switch (me->p_team)
+	{
+	 case FED:
+	  strcpy(s, "Federation");
+	  break;
+	 case ROM:
+	  strcpy(s, "Romulan empire");
+	  break;
+	 case KLI:
+	  strcpy(s, "Klingon empire");
+	  break;
+	 case ORI:
+	  strcpy(s, "Orion empire");
+	  break;
+	}
+	s = s + strlen(s) - 1;
+	break;
+       default:
+	*s = *t;
+      }
+      break;
+     default:
+      *s = *t;
+      break;
+    }
+  }
+  *s = '\0';
+  return (rmessage);
+}
+
+char *
+termie_message(enemy)
+  struct player *enemy;
+{
+  int i;
+  char *s, *t;
+
+  i = (lrand48() % (sizeof(termie_messages) / sizeof(termie_messages[0])));
+
+  for (t = termie_messages[i], s = tmessage; *t != '\0'; s++, t++)
+  {
+    switch (*t)
+    {
+     case '$':
+      switch (*(++t))
+      {
+       case '$':
+	*s = *t;
+	break;
+       case 'T':		/* "a Fed" or "a Klingon" ... */
+	if (enemy->p_team != me->p_team &&
+	    enemy->p_team == ORI)
+	{
+	  strcpy(s, "an ");
+	}
+	else
+	{
+	  strcpy(s, "a ");
+	}
+	s = s + strlen(s);
+       case 't':		/* "Fed" or "Orion" */
+	if (enemy->p_team != me->p_team)
+	{
+	  switch (enemy->p_team)
+	  {
+	   case FED:
+	    strcpy(s, "Fed");
+	    break;
+	   case ROM:
+	    strcpy(s, "Romulan");
+	    break;
+	   case KLI:
+	    strcpy(s, "Klingon");
+	    break;
+	   case ORI:
+	    strcpy(s, "Orion");
+	    break;
+	  }
+	}
+	else
+	{
+	  strcpy(s, "TRAITOR");
+	}
+	s = s + strlen(s) - 1;
+	break;
+       case 'f':
+	switch (me->p_team)
+	{
+	 case FED:
+	  strcpy(s, "Federation");
+	  break;
+	 case ROM:
+	  strcpy(s, "Romulan empire");
+	  break;
+	 case KLI:
+	  strcpy(s, "Klingon empire");
+	  break;
+	 case ORI:
+	  strcpy(s, "Orion empire");
+	  break;
+	}
+	s = s + strlen(s) - 1;
+	break;
+       case 'n':		/* name 8/2/91 TC */
+	strcpy(s, enemy->p_name);
+	s = s + strlen(s) - 1;
+	break;
+       default:
+	*s = *t;
+      }
+      break;
+     default:
+      *s = *t;
+      break;
+    }
+  }
+  *s = '\0';
+  return (tmessage);
+
+}
+
+void
+exitRobot()
+{
+  static char buf[80];
+
+  r_signal(SIGALRM, SIG_IGN);
+  if (me != NULL && me->p_team != ALLTEAM)
+  {
+    if (target >= 0)
+    {
+      strcpy(buf, "I'll be back.");
+      messAll(buf);
+    }
+    else
+    {
+      /*
+       * sprintf(buf, "%s %s (%s) leaving the game (%.16s@%.16s)",
+       * ranks[me->p_stats.st_rank].name, me->p_name, me->p_mapchars,
+       * me->p_login, me->p_monitor); messAll(buf);
+       */
+    }
+  }
+#ifdef ROBOTSTATS
+  save_robot();
+#endif
+
+  strcpy(buf, me->p_name);
+  /* something about Terminators hangs up the slot when a human */
+  /* tries to log in on that slot, so... */
+  memset(me, 0, sizeof(struct player));	/* confusion 8/5/91 TC */
+  strcpy(me->p_name, buf);
+
+  /*
+   * me->p_status = PFREE; move_player(me->p_no, -1,-1, 1);
+   */
+
+  /*
+   * all right, so zeroing out p_stats.st_tticks has undesireable side
+   * effects when the client tries to compute ratings...
+   */
+
+  me->p_stats.st_tticks = 1;	/* quick fix 3/15/92 TC */
+  exit(0);
+}
+
+void
+messAll(buf)
+  char *buf;			/* wasn't K&R before...oops 5/1/92 TC */
+{
+  static char addrbuf[20];
+
+  sprintf(addrbuf, " %s->ALL", twoletters(me));
+  pmessage2(buf, 0, MALL, addrbuf, me->p_no);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/robotII.c	Sat Dec 06 04:37:04 1997 +0000
@@ -0,0 +1,622 @@
+/*--------------------------------------------------------------------------
+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
+--------------------------------------------------------------------------*/
+
+char binary[] = "@(#)robotII";
+
+#include "config.h"
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+#ifndef ULTRIX
+#include <sys/fcntl.h>
+#endif
+#include <signal.h>
+#include <setjmp.h>
+#include <errno.h>
+#include "defs.h"
+#include "struct.h"
+#include "data.h"
+#include "shmem.h"
+
+extern void (*r_signal()) ();
+
+void config();
+
+struct itimerval udt;
+extern int redrawall;		/* maint: missing "extern" 6/22/92 TC */
+extern int lastm;		/* maint: missing "extern" 6/22/92 TC */
+
+/* This lets you specify which ships a robot is allowed to choose */
+int robotships[NUM_TYPES] = {
+  1,				/* SCOUT */
+  1,				/* DESTROYER */
+  1,				/* CRUISER */
+  1,				/* BATTLESHIP */
+  1,				/* ASSAULT */
+  0,				/* STARBASE */
+  0,				/* ATT */
+  0,				/* JUMPSHIP */
+  1,				/* FRIGATE */
+  0,				/* WARBASE */
+  1,				/* LIGHTCRUISER */
+  0,				/* CARRIER */
+  0,				/* UTILITY */
+  1				/* PATROL */
+};
+
+/* lots of neat flags */
+int hostile;
+int debug;
+int level;
+int fleet;
+int sticky;
+int berserk;
+int practice;
+int nofuel;
+
+int polymorphic;		/* match opponent's ship class 8/15/91 TC */
+int target;			/* Terminator's target 7/27/91 TC */
+int phrange;			/* phaser range 7/31/91 TC */
+int trrange;			/* tractor range 8/2/91 TC */
+
+int startplanet = -1;		/* CRD feature - MAK,  2-Jun-93 */
+
+/* velocities 8/9/91 TC */
+
+int dogslow;			/* dodge speed (hard turn) */
+int dogfast;			/* dodge speed (soft turn) */
+int runslow;			/* run speed (flat etemp) */
+int runfast;			/* run speed (gain etemp) */
+int closeslow;			/* approach speed (hard turn) */
+int closefast;			/* approach speed (soft turn) */
+
+char *rnames[6] = {"M5", "Colossus", "Guardian", "HAL", "DreadPirate Bob",
+"TERMINATOR"};
+
+#ifdef ROBOTSTATS
+void
+do_robot_login()
+{
+  int plfd, position, entries, i;
+  char *path;
+  struct statentry player;
+  struct stat buf;
+
+  path = build_path(PLAYERFILE);
+  plfd = open(path, O_RDONLY, 0);
+  if (plfd < 0)
+  {
+    fprintf(stderr, "%s: I cannot open the player file! (errno: %d)\n",
+	    argv0, errno);
+    me->p_pos = -1;
+    return;
+  }
+  position = 0;
+  while (read(plfd, (char *) &player, sizeof(struct statentry)) ==
+	 sizeof(struct statentry))
+  {
+    if (!strcmp(pseudo, player.name))
+    {
+      close(plfd);
+      me->p_pos = position;
+      memcpy(&(me->p_stats), &player.stats, sizeof(struct stats));
+      return;
+    }
+    position++;
+  }
+  /* Not in there, so create it */
+  strcpy(player.name, pseudo);
+  strcpy(player.password, "*");	/* an invalid password to prevent logins */
+  memset(&player.stats, 0, sizeof(struct stats));
+  player.stats.st_tticks = 1;
+  player.stats.st_flags = ST_INITIAL;
+
+  plfd = open(path, O_RDWR | O_CREAT, 0644);
+  if (plfd < 0)
+  {
+    fprintf(stderr, "%s: I cannot open the player file! (errno: %d)\n",
+	    argv0, errno);
+    me->p_pos = -1;
+    return;
+  }
+  else
+  {
+    fstat(plfd, &buf);
+    entries = buf.st_size / sizeof(struct statentry);
+    lseek(plfd, entries * sizeof(struct statentry), 0);
+    write(plfd, (char *) &player, sizeof(struct statentry));
+    close(plfd);
+    me->p_pos = entries;
+    memcpy(&(me->p_stats), &player.stats, sizeof(struct stats));
+  }
+}
+
+void
+save_robot()
+{
+  int fd;
+  char *path;
+
+  if (me->p_pos < 0)
+    return;
+  path = build_path(PLAYERFILE);
+  fd = open(path, O_WRONLY, 0644);
+  if (fd >= 0)
+  {
+    me->p_stats.st_lastlogin = time(NULL);
+    lseek(fd, 32 + me->p_pos * sizeof(struct statentry), 0);
+    write(fd, (char *) &me->p_stats, sizeof(struct stats));
+    close(fd);
+  }
+}
+#endif
+
+int 
+main(argc, argv)
+  int argc;
+  char **argv;
+{
+  register int i;
+  int rmove();
+  int team = -1;
+  int bteam;
+  int pno;
+  int class;			/* ship class 8/9/91 TC */
+
+  argv0 = argv[0];
+  srand48(time(NULL) + getpid());
+
+  openmem(0, 0);
+
+  for (;;)
+  {
+    class = lrand48() % NUM_TYPES;	/* pick a ship type */
+    if (robotships[class] && shipsallowed[class])
+      break;
+  }
+
+  target = -1;			/* no target 7/27/91 TC */
+  for (; argc > 1 && argv[1][0] == '-'; argc--, argv++)
+  {
+    switch (argv[1][1])
+    {
+     case 'S':
+      startplanet = atoi(&argv[1][2]);
+      if (startplanet >= configvals->numplanets)
+      {
+	printf("startplanet insane: %d\n", startplanet);
+	startplanet = -1;
+      }
+      break;
+     case 'F':
+      nofuel++;
+      break;
+     case 'P':
+      polymorphic++;
+      break;
+     case 'f':
+      fleet++;
+      break;
+     case 's':
+      sticky++;
+      break;
+     case 'd':
+      debug++;
+      break;
+     case 'h':
+      hostile++;
+      break;
+     case 'p':
+      practice++;
+      break;
+     case 'b':
+      berserk++;
+      break;
+     case 'l':
+      if (argv[1][2] != '\0')
+	level = atoi(&argv[1][2]);
+      else
+	level = 100;
+      break;
+     case 'c':			/* ship class */
+      {
+	char cstr[NUM_TYPES + 1];
+
+	for (class = 0; class <= NUM_TYPES; class++)
+	{
+	  if (class == NUM_TYPES)
+	  {
+	    cstr[NUM_TYPES] = 0;
+	    fprintf(stderr, "Unknown ship class, must be one of [%s].\n", cstr);
+	    exit(1);
+	  }
+	  if (argv[1][2] == shipvals[class].s_letter)
+	    break;
+	  cstr[class] = shipvals[class].s_letter;
+	}
+      }
+      break;
+     case 'T':			/* team */
+      switch (argv[1][2])
+      {
+       case 'f':
+	team = 0;
+	bteam = FED;
+	break;
+       case 'r':
+	team = 1;
+	bteam = ROM;
+	break;
+       case 'k':
+	team = 2;
+	bteam = KLI;
+	break;
+       case 'o':
+	team = 3;
+	bteam = ORI;
+	break;
+       case 'n':		/* change 5/10/91 TC neutral */
+       case 'i':
+	team = 4;
+	bteam = FED | ROM | KLI | ORI;	/* don't like anybody */
+	break;
+       case 't':
+	{
+	  char c;
+	  c = argv[1][3];
+
+	  team = 5;
+	  bteam = FED | ROM | KLI | ORI;	/* don't like anybody */
+	  target = -1;
+	  if (c == '\0')
+	  {
+	    fprintf(stderr, "Must specify target.  e.g. -Tt3.\n");
+	    exit(1);
+	  }
+	  if ((c >= '0') && (c <= '9'))
+	    target = c - '0';
+	  else if ((c >= 'a') && (c <= 'v'))
+	    target = c - 'a' + 10;
+	  else
+	  {
+	    fprintf(stderr, "Must specify target.  e.g. -Tt3.\n");
+	    exit(1);
+	  }
+	}			/* end case 't' */
+	break;
+       default:
+	fprintf(stderr, "Unknown team type.  Usage -Tx where x is [frko]\n");
+	exit(1);
+      }				/* end switch argv */
+      break;
+     default:
+      fprintf(stderr, "Unknown option '%c' (must be one of: bcdfpsFPT)\n", argv[1][1]);
+      exit(1);
+    }				/* end switch argv[1][1] */
+
+
+  }				/* end for */
+
+  if (team < 0 || team >= 6)
+  {				/* change 7/27/91 TC was 4 now 6 */
+    if (debug)
+      fprintf(stderr, "Choosing random team.\n");
+    team = lrand48() % 4;
+  }
+
+  pno = findrslot();		/* Robots are entitled to tester's slots. */
+  me = &players[pno];
+  me->p_no = pno;
+  myship = &me->p_ship;
+  mystats = &me->p_stats;
+  lastm = mctl->mc_current;
+
+  /*
+   * At this point we have memory set up.  If we aren't a fleet, we don't
+   * want to replace any other robots on this team, so we'll check the other
+   * players and get out if there are any on our team.
+   */
+
+  if (practice)
+  {
+    strcpy(pseudo, "Hozer");
+  }
+  else
+  {
+    strcpy(pseudo, rnames[team]);
+  }
+  strcpy(login, "Robot");
+
+  (void) strncpy(me->p_login, login, sizeof(me->p_login));
+  me->p_login[sizeof(me->p_login) - 1] = '\0';
+  (void) strncpy(me->p_monitor, "Nowhere", sizeof(me->p_monitor));
+  me->p_monitor[sizeof(me->p_monitor) - 1] = '\0';
+
+  /* repeat "Nowhere" for completeness 4/13/92 TC */
+  (void) strncpy(me->p_full_hostname, "Nowhere", sizeof(me->p_full_hostname));
+  me->p_full_hostname[sizeof(me->p_full_hostname) - 1] = '\0';
+
+  if (target >= 0)
+  {				/* hack 7/27/91 TC */
+    enter(team, target, pno, class, startplanet);
+    startplanet = -1;		/* Termies should forget about startplanet */
+  }
+  else
+    startplanet = enter(team, 0, pno, class, startplanet);
+
+#ifdef ROBOTSTATS
+  do_robot_login();
+#else
+  me->p_pos = -1;		/* So robot stats don't get saved */
+#endif
+
+  me->p_flags |= PFROBOT;	/* Mark as a robot */
+  if ((berserk) || (team == 4))	/* indeps are hostile */
+    me->p_hostile = (FED | ROM | KLI | ORI);	/* unless they are berserk */
+  else if (team == 5)
+    me->p_hostile = 0;		/* Termies declare war later */
+  else if (practice)
+    me->p_hostile = bteam;	/* or practice */
+  else
+    me->p_hostile = 0;		/* robots are peaceful */
+
+  if (practice)
+    me->p_flags |= PFPRACTR;	/* Mark as a practice robot */
+  r_signal(SIGALRM, rmove);
+
+  config();
+  if (practice)
+  {
+    udt.it_interval.tv_sec = 1;	/* Robots get to move 1/sec */
+    udt.it_interval.tv_usec = 000000;
+  }
+  else
+  {
+    udt.it_interval.tv_sec = 0;	/* Robots get to move 2/sec */
+    udt.it_interval.tv_usec = 500000;
+  }
+  udt.it_value.tv_sec = 1;
+  udt.it_value.tv_usec = 0;
+  if (setitimer(ITIMER_REAL, &udt, 0) < 0)
+  {
+    perror("setitimer");
+    me->p_status = PFREE;	/* Put robot in game */
+    move_player(me->p_no, -1, -1, 1);
+    exit(1);
+  }
+  /* allows robots to be forked by the daemon -- Evil ultrix bullshit */
+#ifndef SVR4
+  sigsetmask(0);
+#endif				/* SVR4 */
+
+  if (team == 4)
+  {
+    int count = 0;
+    for (i = 0; i < MAXPLAYER; i++)
+    {
+      if (players[i].p_status == PALIVE)
+	count++;
+    }
+    if (((count <= 1) && (!fleet)) ||
+	((count < 1) && (fleet)))
+    {				/* if one or less players, don't show */
+      if (debug)
+	fprintf(stderr, "No one to hoze.\n");
+      players[pno].p_status = PFREE;
+      move_player(me->p_no, -1, -1, 1);
+      exit(1);
+    }
+  }
+  if (!fleet)
+  {
+    for (i = 0; i < MAXPLAYER; i++)
+    {
+      if ((players[i].p_status == PALIVE) && (players[i].p_team == bteam))
+      {
+	if (debug)
+	  fprintf(stderr, "Galaxy already defended\n");
+	players[pno].p_status = PFREE;
+	move_player(me->p_no, -1, -1, 1);
+	exit(1);
+      }
+    }
+  }
+  me->p_status = PALIVE;	/* Put robot in game */
+  while (1)
+  {
+    pause();
+  }
+  return 0;
+}
+
+int 
+findrslot()
+{
+  register int i;
+
+#if 0
+  for (i = 0; i < MAXPLAYER; i++)
+#else
+  for (i = MAXPLAYER - 1; i >= 0; i--)
+#endif
+  {
+    /* reverse entry..let's be trendy 4/6/92 TC */
+    if (players[i].p_status == PFREE)
+    {				/* We have a free slot */
+      players[i].p_status = POUTFIT;	/* possible race code */
+      break;
+    }
+  }
+  if ((i == MAXPLAYER) || (i == -1))
+  {
+    if (debug)
+    {
+      fprintf(stderr, "No more room in game\n");
+    }
+    exit(0);
+  }
+  memset(&players[i].p_stats, 0, sizeof(struct stats));
+  players[i].p_stats.st_tticks = 1;
+  return (i);
+}
+
+void
+warning(mess)
+  char *mess;
+{
+  if (debug)
+    fprintf(stderr, "warning: %s\n", mess);
+}
+
+void
+config()
+{
+  /* calc class-specific stuff */
+
+  phrange = PHASEDIST * me->p_ship.s_phaser.damage / 100;
+  trrange = TRACTDIST * me->p_ship.s_tractrng;
+
+  switch (myship->s_type)
+  {
+   case SCOUT:
+    dogslow = 5;
+    dogfast = 7;
+    runslow = 8;
+    runfast = 9;
+    closeslow = 5;
+    closefast = 7;
+    break;
+   case DESTROYER:
+    dogslow = 4;
+    dogfast = 6;
+    runslow = 6;
+    runfast = 8;
+    closeslow = 4;
+    closefast = 6;
+    break;
+   case CRUISER:
+    dogslow = 4;
+    dogfast = 6;
+    runslow = 6;
+    runfast = 7;
+    closeslow = 4;
+    closefast = 6;
+    break;
+   case BATTLESHIP:
+    dogslow = 3;
+    dogfast = 5;
+    runslow = 5;
+    runfast = 6;
+    closeslow = 3;
+    closefast = 4;
+    break;
+   case FRIGATE:
+    dogslow = 3;
+    dogfast = 5;
+    runslow = 5;
+    runfast = 6;
+    closeslow = 3;
+    closefast = 4;
+    break;
+   case ASSAULT:
+    dogslow = 3;
+    dogfast = 5;
+    runslow = 6;
+    runfast = 7;
+    closeslow = 3;
+    closefast = 4;
+    break;
+   case JUMPSHIP:
+    dogslow = 2;
+    dogfast = 3;
+    runslow = 2;
+    runfast = 3;
+    closeslow = 2;
+    closefast = 3;
+    break;
+   case STARBASE:
+    dogslow = 2;
+    dogfast = 2;
+    runslow = 2;
+    runfast = 2;
+    closeslow = 2;
+    closefast = 2;
+    break;
+   case WARBASE:
+    dogslow = 2;
+    dogfast = 2;
+    runslow = 2;
+    runfast = 2;
+    closeslow = 2;
+    closefast = 2;
+    break;
+   case LIGHTCRUISER:
+    dogslow = 5;
+    dogfast = 6;
+    runslow = 6;
+    runfast = 7;
+    closeslow = 5;
+    closefast = 7;
+    break;
+   case CARRIER:
+    dogslow = 3;
+    dogfast = 4;
+    runslow = 5;
+    runfast = 6;
+    closeslow = 4;
+    closefast = 6;
+    break;
+   case UTILITY:
+    dogslow = 3;
+    dogfast = 4;
+    runslow = 5;
+    runfast = 6;
+    closeslow = 4;
+    closefast = 5;
+    break;
+   case PATROL:
+    dogslow = 7;
+    dogfast = 8;
+    runslow = 9;
+    runfast = 10;
+    closeslow = 8;
+    closefast = 9;
+    break;
+  }
+
+  if (debug)
+    printf("My phaser range: %d.\n", phrange);
+  if (debug)
+    printf("My tractor range: %d.\n", trrange);
+
+  if (!nofuel)
+  {
+    myship->s_phaser.cost = 0;
+    myship->s_torp.cost = 0;
+    myship->s_cloakcost = 0;
+  }
+  if (target >= 0)
+  {				/* 7/27/91 TC */
+    myship->s_imp.maxspeed = 20;/* was 10, so you can't run */
+    myship->s_imp.cost = 1;
+    myship->s_egncoolrate = 100;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/shipvals.c	Sat Dec 06 04:37:04 1997 +0000
@@ -0,0 +1,1794 @@
+/*--------------------------------------------------------------------------
+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 <stdio.h>
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <string.h>
+
+#include "defs.h"
+#include "struct.h"
+#include "data.h"
+#include "shmem.h"
+
+
+/* This defines the core flags for a normal ship */
+#define SFNCORE  	\
+	/*SFNCANDOCK|*/SFNCANORBIT | SFNARMYNEEDKILL|SFNCANWARP|SFNHASPHASERS|SFNARMYNEEDKILL
+
+
+
+
+
+
+/*-------------------------------INTERNAL FUNCTONS------------------------*/
+
+/*---------------------------------GETSHIPDEFAULTS------------------------*/
+/*
+ * This function loads the shipvals array with the default values for the
+ * ships.  They can later be changed with the sysdefaults.
+ */
+
+
+void
+getshipdefaults()
+{
+  int i;
+
+  for (i = 0; i < NUM_TYPES; i++)
+    shipvals[i].s_type = i;
+
+  /* comprehensive definition of SCOUT */
+  shipvals[SCOUT].s_alttype = 0;
+  strcpy(shipvals[SCOUT].s_name, "Scout");
+  shipvals[SCOUT].s_turns = 570000;
+  shipvals[SCOUT].s_imp.acc = 200;
+  shipvals[SCOUT].s_imp.dec = 300;	/* was: 270; (BG) */
+  shipvals[SCOUT].s_imp.cost = 2;
+  shipvals[SCOUT].s_imp.maxspeed = 12;
+  shipvals[SCOUT].s_imp.etemp = 1000;
+  shipvals[SCOUT].s_after.acc = 700;
+  shipvals[SCOUT].s_after.dec = 270;
+  shipvals[SCOUT].s_after.cost = 40;
+  shipvals[SCOUT].s_after.maxspeed = 14;
+  shipvals[SCOUT].s_after.etemp = 35000;
+  if (configvals->bronco_shipvals)
+  {
+    shipvals[SCOUT].s_warp.acc = 10000;
+    shipvals[SCOUT].s_warp.dec = 200;
+    shipvals[SCOUT].s_warp.cost = 14;
+    shipvals[SCOUT].s_warp.maxspeed = 19;
+    shipvals[SCOUT].s_warp.etemp = 9000;
+    shipvals[SCOUT].s_warpinitcost = 909;
+    shipvals[SCOUT].s_warpinittime = 30;
+    shipvals[SCOUT].s_warpprepspeed = 2;
+  }
+  else
+  {
+    shipvals[SCOUT].s_warp.acc = 10000;
+    shipvals[SCOUT].s_warp.dec = 200;
+    shipvals[SCOUT].s_warp.cost = 13;	/* was: 14; (BG) */
+    shipvals[SCOUT].s_warp.maxspeed = 32;	/* was: 27; (BG) */
+    shipvals[SCOUT].s_warp.etemp = 9000;
+    shipvals[SCOUT].s_warpinitcost = 909;
+    shipvals[SCOUT].s_warpinittime = 30;
+    shipvals[SCOUT].s_warpprepspeed = 3;
+  }
+  shipvals[SCOUT].s_mass = 1500;
+  shipvals[SCOUT].s_tractstr = 2000;
+  shipvals[SCOUT].s_tractrng = 0.7;
+  shipvals[SCOUT].s_tractcost = 3;
+  shipvals[SCOUT].s_tractetemp = 1000;
+  shipvals[SCOUT].s_torp.damage = 25;
+  shipvals[SCOUT].s_torp.speed = 16;
+  shipvals[SCOUT].s_torp.cost = 175;
+#ifndef OLDSHIPVALS
+  shipvals[SCOUT].s_torp.fuse = 16;
+#else
+  shipvals[SCOUT].s_torp.fuse = 15;
+#endif
+  shipvals[SCOUT].s_torp.wtemp = 7;
+  shipvals[SCOUT].s_torp.wtemp_halfarc = 32;
+  shipvals[SCOUT].s_torp.wtemp_factor = 9;
+  shipvals[SCOUT].s_torp.aux = 0;
+  shipvals[SCOUT].s_phaser.damage = 75;
+  shipvals[SCOUT].s_phaser.speed = 4500;
+  shipvals[SCOUT].s_phaser.cost = 525;
+  shipvals[SCOUT].s_phaser.fuse = 10;
+#ifndef OLDSHIPVALS
+  shipvals[SCOUT].s_phaser.wtemp = 52;
+#else
+  shipvals[SCOUT].s_phaser.wtemp = 50;
+#endif
+  shipvals[SCOUT].s_missile.damage = 0;
+  shipvals[SCOUT].s_missile.speed = 0;
+  shipvals[SCOUT].s_missile.cost = 0;
+  shipvals[SCOUT].s_missile.fuse = 0;
+  shipvals[SCOUT].s_missile.wtemp = 0;
+  shipvals[SCOUT].s_missile.count = 0;
+  shipvals[SCOUT].s_missile.aux = 0;
+  shipvals[SCOUT].s_missilestored = 0;
+  shipvals[SCOUT].s_plasma.damage = -1;
+  shipvals[SCOUT].s_plasma.speed = 0;
+  shipvals[SCOUT].s_plasma.cost = 0;
+  shipvals[SCOUT].s_plasma.fuse = 0;
+  shipvals[SCOUT].s_plasma.wtemp = 50;
+  shipvals[SCOUT].s_plasma.aux = 0;
+  shipvals[SCOUT].s_maxwpntemp = 1000;
+  shipvals[SCOUT].s_wpncoolrate = 3;
+  if (configvals->bronco_shipvals)
+    shipvals[SCOUT].s_maxegntemp = 1000;
+  else
+    shipvals[SCOUT].s_maxegntemp = 1500;
+  shipvals[SCOUT].s_egncoolrate = 8;
+  shipvals[SCOUT].s_maxfuel = 5000;
+  shipvals[SCOUT].s_recharge = 16;
+  shipvals[SCOUT].s_mingivefuel = 0;
+  shipvals[SCOUT].s_takeonfuel = 150;
+  if (configvals->fuel_explosions)
+  {
+    shipvals[SCOUT].s_expldam = 35;	/* was: 40; (BG) */
+    shipvals[SCOUT].s_fueldam = 50;	/* was: 45; (BG) */
+  }
+  else
+  {
+    shipvals[SCOUT].s_expldam = 75;
+    shipvals[SCOUT].s_fueldam = 0;
+  }
+  shipvals[SCOUT].s_armyperkill = 2;
+  shipvals[SCOUT].s_maxarmies = 2;
+  if (configvals->bronco_shipvals)
+    shipvals[SCOUT].s_bomb = 10;
+  else
+    shipvals[SCOUT].s_bomb = 0;
+  shipvals[SCOUT].s_repair = 80;
+  shipvals[SCOUT].s_maxdamage = 75;
+  shipvals[SCOUT].s_maxshield = 75;
+  shipvals[SCOUT].s_shieldcost = 2;
+  shipvals[SCOUT].s_detcost = 100;
+  shipvals[SCOUT].s_detdist = 1750;
+  if (configvals->bronco_shipvals)
+  {
+    shipvals[SCOUT].s_cloakcost = 85;
+    shipvals[SCOUT].s_scanrange = -1;
+  }
+  else
+  {
+    shipvals[SCOUT].s_cloakcost = 50;
+#ifdef LONG_SCANRANGE
+    shipvals[SCOUT].s_scanrange = 8000;
+#else
+    shipvals[SCOUT].s_scanrange = 5000;
+#endif
+  }
+  shipvals[SCOUT].s_numports = 0;
+  shipvals[SCOUT].s_letter = 's';
+  shipvals[SCOUT].s_desig1 = 'S';
+  shipvals[SCOUT].s_desig2 = 'C';
+  shipvals[SCOUT].s_bitmap = 0;
+  shipvals[SCOUT].s_width = 20;
+  shipvals[SCOUT].s_height = 20;
+  shipvals[SCOUT].s_timer = 0;
+  shipvals[SCOUT].s_maxnum = 32;
+  shipvals[SCOUT].s_rank = 0;
+  shipvals[SCOUT].s_numdefn = 0;
+  shipvals[SCOUT].s_numplan = 0;
+  if (configvals->warpdrive)
+    shipvals[SCOUT].s_nflags = SFNCANORBIT | SFNARMYNEEDKILL | SFNCANWARP | SFNHASPHASERS;
+  else
+    shipvals[SCOUT].s_nflags = SFNCANORBIT | SFNARMYNEEDKILL | SFNHASPHASERS;
+
+
+  /* comprehensive definition of DESTROYER */
+  shipvals[DESTROYER].s_alttype = 1;
+  strcpy(shipvals[DESTROYER].s_name, "Destroyer");
+  shipvals[DESTROYER].s_turns = 310000;
+  shipvals[DESTROYER].s_imp.acc = 200;
+  shipvals[DESTROYER].s_imp.dec = 300;
+  shipvals[DESTROYER].s_imp.cost = 3;
+  shipvals[DESTROYER].s_imp.maxspeed = 10;
+  shipvals[DESTROYER].s_imp.etemp = 1000;
+  shipvals[DESTROYER].s_after.acc = 700;
+  shipvals[DESTROYER].s_after.dec = 270;
+  shipvals[DESTROYER].s_after.cost = 100;
+  shipvals[DESTROYER].s_after.maxspeed = 12;
+  shipvals[DESTROYER].s_after.etemp = 40000;
+  if (configvals->bronco_shipvals)
+  {
+    shipvals[DESTROYER].s_warp.acc = 10000;
+    shipvals[DESTROYER].s_warp.dec = 300;
+    shipvals[DESTROYER].s_warp.cost = 22;
+    shipvals[DESTROYER].s_warp.maxspeed = 15;
+    shipvals[DESTROYER].s_warp.etemp = 8000;
+    shipvals[DESTROYER].s_warpinitcost = 1272;
+    shipvals[DESTROYER].s_warpinittime = 50;
+    shipvals[DESTROYER].s_warpprepspeed = 2;
+  }
+  else
+  {
+    shipvals[DESTROYER].s_warp.acc = 10000;
+    shipvals[DESTROYER].s_warp.dec = 300;
+    shipvals[DESTROYER].s_warp.cost = 21;	/* was: 22; (BG) */
+    shipvals[DESTROYER].s_warp.maxspeed = 27;	/* was: 22; (BG) */
+    shipvals[DESTROYER].s_warp.etemp = 8000;
+    shipvals[DESTROYER].s_warpinitcost = 1272;
+    shipvals[DESTROYER].s_warpinittime = 50;
+    shipvals[DESTROYER].s_warpprepspeed = 3;
+  }
+  shipvals[DESTROYER].s_mass = 1800;
+  shipvals[DESTROYER].s_tractstr = 2500;
+  shipvals[DESTROYER].s_tractrng = 0.9;
+  shipvals[DESTROYER].s_tractcost = 4;
+  shipvals[DESTROYER].s_tractetemp = 1000;
+  shipvals[DESTROYER].s_torp.damage = 30;
+  shipvals[DESTROYER].s_torp.speed = 14;
+  shipvals[DESTROYER].s_torp.cost = 210;
+  shipvals[DESTROYER].s_torp.fuse = 30;
+  shipvals[DESTROYER].s_torp.wtemp = 11;
+  shipvals[DESTROYER].s_torp.wtemp_halfarc = 32;
+  shipvals[DESTROYER].s_torp.wtemp_factor = 9;
+  shipvals[DESTROYER].s_torp.aux = 0;
+  shipvals[DESTROYER].s_phaser.damage = 85;
+  shipvals[DESTROYER].s_phaser.speed = 5100;
+  shipvals[DESTROYER].s_phaser.cost = 595;
+  shipvals[DESTROYER].s_phaser.fuse = 10;
+  shipvals[DESTROYER].s_phaser.wtemp = 59;
+  shipvals[DESTROYER].s_missile.damage = 20;
+  shipvals[DESTROYER].s_missile.speed = 8;
+  shipvals[DESTROYER].s_missile.cost = 900;
+  shipvals[DESTROYER].s_missile.fuse = 100;
+  shipvals[DESTROYER].s_missile.wtemp = 100;
+  shipvals[DESTROYER].s_missile.count = 2;
+  shipvals[DESTROYER].s_missile.aux = 2;
+  shipvals[DESTROYER].s_missilestored = 8;
+  shipvals[DESTROYER].s_plasma.damage = 75;
+  shipvals[DESTROYER].s_plasma.speed = 15;
+  shipvals[DESTROYER].s_plasma.cost = 2250;
+  shipvals[DESTROYER].s_plasma.fuse = 30;
+  shipvals[DESTROYER].s_plasma.wtemp = 217;
+  shipvals[DESTROYER].s_plasma.aux = 1;
+  shipvals[DESTROYER].s_maxwpntemp = 1000;
+  shipvals[DESTROYER].s_wpncoolrate = 2;
+  if (configvals->bronco_shipvals)
+    shipvals[DESTROYER].s_maxegntemp = 1000;
+  else
+    shipvals[DESTROYER].s_maxegntemp = 1500;
+  shipvals[DESTROYER].s_egncoolrate = 7;
+  shipvals[DESTROYER].s_maxfuel = 7000;
+  shipvals[DESTROYER].s_recharge = 22;
+  shipvals[DESTROYER].s_mingivefuel = 0;
+  shipvals[DESTROYER].s_takeonfuel = 150;
+  if (configvals->fuel_explosions)
+  {
+    shipvals[DESTROYER].s_expldam = 65;	/* was: 50; (BG) */
+    shipvals[DESTROYER].s_fueldam = 45;	/* was: 50; (BG) */
+  }
+  else
+  {
+    shipvals[DESTROYER].s_expldam = 100;
+    shipvals[DESTROYER].s_fueldam = 0;
+  }
+  shipvals[DESTROYER].s_armyperkill = 2;
+#ifndef OLDSHIPVALS
+  shipvals[DESTROYER].s_maxarmies = 4;
+#else
+  shipvals[DESTROYER].s_maxarmies = 5;
+#endif
+  if (configvals->bronco_shipvals)
+    shipvals[DESTROYER].s_bomb = 10;
+  else
+    shipvals[DESTROYER].s_bomb = 5;
+  shipvals[DESTROYER].s_repair = 100;
+  shipvals[DESTROYER].s_maxdamage = 85;
+  shipvals[DESTROYER].s_maxshield = 85;
+  shipvals[DESTROYER].s_shieldcost = 3;
+  shipvals[DESTROYER].s_detcost = 100;
+  shipvals[DESTROYER].s_detdist = 1750;
+  if (configvals->bronco_shipvals)
+  {
+    shipvals[DESTROYER].s_cloakcost = 105;
+    shipvals[DESTROYER].s_scanrange = -1;
+  }
+  else
+  {
+    shipvals[DESTROYER].s_cloakcost = 75;
+    shipvals[DESTROYER].s_scanrange = 1000;
+  }
+  shipvals[DESTROYER].s_numports = 0;
+  shipvals[DESTROYER].s_letter = 'd';
+  shipvals[DESTROYER].s_desig1 = 'D';
+  shipvals[DESTROYER].s_desig2 = 'D';
+  shipvals[DESTROYER].s_bitmap = 1;
+  shipvals[DESTROYER].s_width = 20;
+  shipvals[DESTROYER].s_height = 20;
+  shipvals[DESTROYER].s_timer = 0;
+  shipvals[DESTROYER].s_maxnum = 32;
+  shipvals[DESTROYER].s_rank = 0;
+  shipvals[DESTROYER].s_numdefn = 0;
+  shipvals[DESTROYER].s_numplan = 0;
+  if (configvals->warpdrive)
+    shipvals[DESTROYER].s_nflags = SFNCANORBIT | SFNARMYNEEDKILL | SFNCANWARP | SFNHASPHASERS;
+  else
+    shipvals[DESTROYER].s_nflags = SFNCANORBIT | SFNARMYNEEDKILL | SFNHASPHASERS;
+
+  /* comprehensive definition of CRUISER */
+  shipvals[CRUISER].s_alttype = 2;
+  strcpy(shipvals[CRUISER].s_name, "Cruiser");
+  shipvals[CRUISER].s_turns = 170000;
+  shipvals[CRUISER].s_imp.acc = 150;
+  shipvals[CRUISER].s_imp.dec = 200;
+  shipvals[CRUISER].s_imp.cost = 4;
+  shipvals[CRUISER].s_imp.maxspeed = 9;
+  shipvals[CRUISER].s_imp.etemp = 1000;
+  shipvals[CRUISER].s_after.acc = 550;
+  shipvals[CRUISER].s_after.dec = 270;
+  shipvals[CRUISER].s_after.cost = 200;
+  shipvals[CRUISER].s_after.maxspeed = 11;
+  shipvals[CRUISER].s_after.etemp = 50000;
+  if (configvals->bronco_shipvals)
+  {
+    shipvals[CRUISER].s_warp.acc = 10000;
+    shipvals[CRUISER].s_warp.dec = 500;
+    shipvals[CRUISER].s_warp.cost = 25;
+    shipvals[CRUISER].s_warp.maxspeed = 13;
+    shipvals[CRUISER].s_warp.etemp = 7000;
+    shipvals[CRUISER].s_warpinitcost = 1818;
+    shipvals[CRUISER].s_warpinittime = 60;
+    shipvals[CRUISER].s_warpprepspeed = 1;
+  }
+  else
+  {
+    shipvals[CRUISER].s_warp.acc = 10000;
+    shipvals[CRUISER].s_warp.dec = 500;
+    shipvals[CRUISER].s_warp.cost = 24;	/* was: 25; (BG) */
+    shipvals[CRUISER].s_warp.maxspeed = 24;	/* was: 19; (BG) */
+    shipvals[CRUISER].s_warp.etemp = 7000;
+    shipvals[CRUISER].s_warpinitcost = 1818;
+    shipvals[CRUISER].s_warpinittime = 60;
+    shipvals[CRUISER].s_warpprepspeed = 2;
+  }
+  shipvals[CRUISER].s_mass = 2000;
+  shipvals[CRUISER].s_tractstr = 3000;
+  shipvals[CRUISER].s_tractrng = 1.0;
+  shipvals[CRUISER].s_tractcost = 4;
+  shipvals[CRUISER].s_tractetemp = 1000;
+  shipvals[CRUISER].s_torp.damage = 40;
+  shipvals[CRUISER].s_torp.speed = 12;
+  shipvals[CRUISER].s_torp.cost = 280;
+  shipvals[CRUISER].s_torp.fuse = 40;
+  shipvals[CRUISER].s_torp.wtemp = 18;
+  shipvals[CRUISER].s_torp.wtemp_halfarc = 32;
+  shipvals[CRUISER].s_torp.wtemp_factor = 9;
+  shipvals[CRUISER].s_torp.aux = 0;
+  shipvals[CRUISER].s_phaser.damage = 100;
+#ifndef OLDSHIPVALS
+  shipvals[CRUISER].s_phaser.speed = 6000;
+#else
+  shipvals[CRUISER].s_phaser.speed = 5500;
+#endif
+  shipvals[CRUISER].s_phaser.cost = 700;
+  shipvals[CRUISER].s_phaser.fuse = 10;
+  shipvals[CRUISER].s_phaser.wtemp = 70;
+  shipvals[CRUISER].s_missile.damage = 25;
+  shipvals[CRUISER].s_missile.speed = 7;
+  shipvals[CRUISER].s_missile.cost = 900;
+  shipvals[CRUISER].s_missile.fuse = 100;
+  shipvals[CRUISER].s_missile.wtemp = 105;
+  shipvals[CRUISER].s_missile.count = 3;
+  shipvals[CRUISER].s_missile.aux = 2;
+  shipvals[CRUISER].s_missilestored = 10;
+  shipvals[CRUISER].s_plasma.damage = 100;
+  shipvals[CRUISER].s_plasma.speed = 15;
+  shipvals[CRUISER].s_plasma.cost = 3000;
+  shipvals[CRUISER].s_plasma.fuse = 35;
+  shipvals[CRUISER].s_plasma.wtemp = 292;
+  shipvals[CRUISER].s_plasma.aux = 1;
+  shipvals[CRUISER].s_maxwpntemp = 1000;
+  shipvals[CRUISER].s_wpncoolrate = 2;
+  if (configvals->bronco_shipvals)
+    shipvals[CRUISER].s_maxegntemp = 1000;
+  else
+    shipvals[CRUISER].s_maxegntemp = 1500;
+  shipvals[CRUISER].s_egncoolrate = 6;
+  shipvals[CRUISER].s_maxfuel = 10000;
+  shipvals[CRUISER].s_recharge = 24;
+  shipvals[CRUISER].s_mingivefuel = 0;
+  shipvals[CRUISER].s_takeonfuel = 150;
+  if (configvals->fuel_explosions)
+  {
+    shipvals[CRUISER].s_expldam = 75;	/* was: 50; (BG) */
+    shipvals[CRUISER].s_fueldam = 40;	/* was: 65; (BG) */
+  }
+  else
+  {
+    shipvals[CRUISER].s_expldam = 100;
+    shipvals[CRUISER].s_fueldam = 0;
+  }
+  shipvals[CRUISER].s_armyperkill = 2;
+#ifndef OLDSHIPVALS
+  shipvals[CRUISER].s_maxarmies = 6;
+#else
+  shipvals[CRUISER].s_maxarmies = 10;
+#endif
+  shipvals[CRUISER].s_bomb = 10;
+  shipvals[CRUISER].s_repair = 110;
+  shipvals[CRUISER].s_maxdamage = 100;
+  shipvals[CRUISER].s_maxshield = 100;
+  shipvals[CRUISER].s_shieldcost = 4;
+  shipvals[CRUISER].s_detcost = 100;
+  shipvals[CRUISER].s_detdist = 1750;
+  if (configvals->bronco_shipvals)
+    shipvals[CRUISER].s_cloakcost = 130;
+  else
+    shipvals[CRUISER].s_cloakcost = 100;
+#ifdef LONG_SCANRANGE
+  shipvals[CRUISER].s_scanrange = 1000;
+#else
+  shipvals[CRUISER].s_scanrange = -1;
+#endif
+  shipvals[CRUISER].s_numports = 0;
+  shipvals[CRUISER].s_letter = 'c';
+  shipvals[CRUISER].s_desig1 = 'C';
+  shipvals[CRUISER].s_desig2 = 'A';
+  shipvals[CRUISER].s_bitmap = 2;
+  shipvals[CRUISER].s_width = 20;
+  shipvals[CRUISER].s_height = 20;
+  shipvals[CRUISER].s_timer = 0;
+  shipvals[CRUISER].s_maxnum = 32;
+  shipvals[CRUISER].s_rank = 0;
+  shipvals[CRUISER].s_numdefn = 0;
+  shipvals[CRUISER].s_numplan = 0;
+  if (configvals->warpdrive)
+    shipvals[CRUISER].s_nflags = SFNCANORBIT | SFNARMYNEEDKILL | SFNCANWARP | SFNHASPHASERS;
+  else
+    shipvals[CRUISER].s_nflags = SFNCANORBIT | SFNARMYNEEDKILL | SFNHASPHASERS;
+
+  /* comprehensive definition of BATTLESHIP */
+  shipvals[BATTLESHIP].s_alttype = 3;
+  strcpy(shipvals[BATTLESHIP].s_name, "Battleship");
+  shipvals[BATTLESHIP].s_turns = 75000;
+  shipvals[BATTLESHIP].s_imp.acc = 80;
+  shipvals[BATTLESHIP].s_imp.dec = 180;
+  shipvals[BATTLESHIP].s_imp.cost = 6;
+  shipvals[BATTLESHIP].s_imp.maxspeed = 8;
+  shipvals[BATTLESHIP].s_imp.etemp = 1000;
+  shipvals[BATTLESHIP].s_after.acc = 500;
+  shipvals[BATTLESHIP].s_after.dec = 270;
+  shipvals[BATTLESHIP].s_after.cost = 100;
+  shipvals[BATTLESHIP].s_after.maxspeed = 10;
+  shipvals[BATTLESHIP].s_after.etemp = 50000;
+  if (configvals->bronco_shipvals)
+  {
+    shipvals[BATTLESHIP].s_warp.acc = 10000;
+    shipvals[BATTLESHIP].s_warp.dec = 500;
+    shipvals[BATTLESHIP].s_warp.cost = 37;
+    shipvals[BATTLESHIP].s_warp.maxspeed = 11;
+    shipvals[BATTLESHIP].s_warp.etemp = 7000;
+    shipvals[BATTLESHIP].s_warpinitcost = 2545;
+    shipvals[BATTLESHIP].s_warpinittime = 70;
+    shipvals[BATTLESHIP].s_warpprepspeed = 0;
+  }
+  else
+  {
+    shipvals[BATTLESHIP].s_warp.acc = 10000;
+    shipvals[BATTLESHIP].s_warp.dec = 500;
+    shipvals[BATTLESHIP].s_warp.cost = 35;	/* was: 37; (BG) */
+    shipvals[BATTLESHIP].s_warp.maxspeed = 21;	/* was: 16; (BG) */
+    shipvals[BATTLESHIP].s_warp.etemp = 7000;
+    shipvals[BATTLESHIP].s_warpinitcost = 2545;
+    shipvals[BATTLESHIP].s_warpinittime = 70;
+    shipvals[BATTLESHIP].s_warpprepspeed = 1;
+  }
+  shipvals[BATTLESHIP].s_mass = 2300;
+  shipvals[BATTLESHIP].s_tractstr = 3700;
+  shipvals[BATTLESHIP].s_tractrng = 1.2;
+  shipvals[BATTLESHIP].s_tractcost = 4;
+  shipvals[BATTLESHIP].s_tractetemp = 1000;
+  shipvals[BATTLESHIP].s_torp.damage = 40;
+  shipvals[BATTLESHIP].s_torp.speed = 12;
+  shipvals[BATTLESHIP].s_torp.cost = 300;
+  shipvals[BATTLESHIP].s_torp.fuse = 40;
+  shipvals[BATTLESHIP].s_torp.wtemp = 20;
+  shipvals[BATTLESHIP].s_torp.wtemp_halfarc = 32;
+  shipvals[BATTLESHIP].s_torp.wtemp_factor = 9;
+  shipvals[BATTLESHIP].s_torp.aux = 0;
+  shipvals[BATTLESHIP].s_phaser.damage = 105;
+#ifndef OLDSHIPVALS
+  shipvals[BATTLESHIP].s_phaser.speed = 6300;
+  shipvals[BATTLESHIP].s_phaser.cost = 945;
+#else
+  shipvals[BATTLESHIP].s_phaser.speed = 6000;
+  shipvals[BATTLESHIP].s_phaser.cost = 900;
+#endif
+  shipvals[BATTLESHIP].s_phaser.fuse = 10;
+  shipvals[BATTLESHIP].s_phaser.wtemp = 94;
+  shipvals[BATTLESHIP].s_missile.damage = 30;
+  shipvals[BATTLESHIP].s_missile.speed = 5;
+  shipvals[BATTLESHIP].s_missile.cost = 900;
+  shipvals[BATTLESHIP].s_missile.fuse = 100;
+  shipvals[BATTLESHIP].s_missile.wtemp = 100;
+  shipvals[BATTLESHIP].s_missile.count = 4;
+  shipvals[BATTLESHIP].s_missile.aux = 3;
+  shipvals[BATTLESHIP].s_missilestored = 12;
+  shipvals[BATTLESHIP].s_plasma.damage = 130;
+  shipvals[BATTLESHIP].s_plasma.speed = 15;
+  shipvals[BATTLESHIP].s_plasma.cost = 3900;
+  shipvals[BATTLESHIP].s_plasma.fuse = 35;
+  shipvals[BATTLESHIP].s_plasma.wtemp = 382;
+  shipvals[BATTLESHIP].s_plasma.aux = 1;
+  shipvals[BATTLESHIP].s_maxwpntemp = 1000;
+  shipvals[BATTLESHIP].s_wpncoolrate = 3;
+  if (configvals->bronco_shipvals)
+    shipvals[BATTLESHIP].s_maxegntemp = 1000;
+  else
+    shipvals[BATTLESHIP].s_maxegntemp = 1500;
+  shipvals[BATTLESHIP].s_egncoolrate = 6;
+  shipvals[BATTLESHIP].s_maxfuel = 14000;
+  shipvals[BATTLESHIP].s_recharge = 28;
+  shipvals[BATTLESHIP].s_mingivefuel = 0;
+  shipvals[BATTLESHIP].s_takeonfuel = 150;
+  if (configvals->fuel_explosions)
+  {
+    shipvals[BATTLESHIP].s_expldam = 85;	/* was: 50; (BG) */
+    shipvals[BATTLESHIP].s_fueldam = 35;	/* was: 85; (BG) */
+  }
+  else
+  {
+    shipvals[BATTLESHIP].s_expldam = 10;
+    shipvals[BATTLESHIP].s_fueldam = 0;
+  }
+  shipvals[BATTLESHIP].s_armyperkill = 2;
+  shipvals[BATTLESHIP].s_maxarmies = 6;
+  shipvals[BATTLESHIP].s_bomb = 20;
+  shipvals[BATTLESHIP].s_repair = 125;
+  shipvals[BATTLESHIP].s_maxdamage = 130;
+  shipvals[BATTLESHIP].s_maxshield = 130;
+  shipvals[BATTLESHIP].s_shieldcost = 5;
+  shipvals[BATTLESHIP].s_detcost = 100;
+  shipvals[BATTLESHIP].s_detdist = 1750;
+  shipvals[BATTLESHIP].s_cloakcost = 150;
+#ifdef LONG_SCANRANGE
+  shipvals[BATTLESHIP].s_scanrange = 1000;
+#else
+  shipvals[BATTLESHIP].s_scanrange = -1;
+#endif
+  shipvals[BATTLESHIP].s_numports = 0;
+  shipvals[BATTLESHIP].s_letter = 'b';
+  shipvals[BATTLESHIP].s_desig1 = 'B';
+  shipvals[BATTLESHIP].s_desig2 = 'B';
+  shipvals[BATTLESHIP].s_bitmap = 3;
+  shipvals[BATTLESHIP].s_width = 20;
+  shipvals[BATTLESHIP].s_height = 20;
+  shipvals[BATTLESHIP].s_timer = 0;
+  shipvals[BATTLESHIP].s_maxnum = 32;
+  shipvals[BATTLESHIP].s_rank = 0;
+  shipvals[BATTLESHIP].s_numdefn = 0;
+  shipvals[BATTLESHIP].s_numplan = 0;
+  shipvals[BATTLESHIP].s_nflags = SFNCANORBIT | SFNARMYNEEDKILL | SFNCANWARP | SFNHASPHASERS;
+
+  /* comprehensive definition of ASSAULT */
+  shipvals[ASSAULT].s_alttype = 4;
+  strcpy(shipvals[ASSAULT].s_name, "Assault");
+  shipvals[ASSAULT].s_turns = 120000;
+  shipvals[ASSAULT].s_imp.acc = 100;
+  shipvals[ASSAULT].s_imp.dec = 200;
+  if (configvals->bronco_shipvals)
+    shipvals[ASSAULT].s_imp.cost = 3;
+  else
+    shipvals[ASSAULT].s_imp.cost = 4;
+  shipvals[ASSAULT].s_imp.maxspeed = 8;
+  shipvals[ASSAULT].s_imp.etemp = 1000;
+  shipvals[ASSAULT].s_after.acc = 550;
+  shipvals[ASSAULT].s_after.dec = 270;
+  shipvals[ASSAULT].s_after.cost = 25;
+  shipvals[ASSAULT].s_after.maxspeed = 10;
+  shipvals[ASSAULT].s_after.etemp = 50000;
+  if (configvals->bronco_shipvals)
+  {
+    shipvals[ASSAULT].s_warp.acc = 10000;
+    shipvals[ASSAULT].s_warp.dec = 5000;
+    shipvals[ASSAULT].s_warp.cost = 20;
+    shipvals[ASSAULT].s_warp.maxspeed = 12;
+    shipvals[ASSAULT].s_warp.etemp = 6500;
+    shipvals[ASSAULT].s_warpinitcost = 1000;
+    shipvals[ASSAULT].s_warpinittime = 80;
+    shipvals[ASSAULT].s_warpprepspeed = 0;
+  }
+  else
+  {
+    shipvals[ASSAULT].s_warp.acc = 10000;
+    shipvals[ASSAULT].s_warp.dec = 5000;
+    shipvals[ASSAULT].s_warp.cost = 20;
+    shipvals[ASSAULT].s_warp.maxspeed = 23;	/* was: 18; (BG) */
+    shipvals[ASSAULT].s_warp.etemp = 6500;
+    shipvals[ASSAULT].s_warpinitcost = 1000;
+    shipvals[ASSAULT].s_warpinittime = 80;
+    shipvals[ASSAULT].s_warpprepspeed = 1;
+  }
+  shipvals[ASSAULT].s_mass = 2300;
+  shipvals[ASSAULT].s_tractstr = 2500;
+  shipvals[ASSAULT].s_tractrng = 0.7;
+  shipvals[ASSAULT].s_tractcost = 3;
+  shipvals[ASSAULT].s_tractetemp = 1000;
+  shipvals[ASSAULT].s_torp.damage = 30;
+  shipvals[ASSAULT].s_torp.speed = 16;
+  shipvals[ASSAULT].s_torp.cost = 270;
+  shipvals[ASSAULT].s_torp.fuse = 30;
+  shipvals[ASSAULT].s_torp.wtemp = 17;
+  shipvals[ASSAULT].s_torp.wtemp_halfarc = 32;
+  shipvals[ASSAULT].s_torp.wtemp_factor = 9;
+  shipvals[ASSAULT].s_torp.aux = 0;
+  shipvals[ASSAULT].s_phaser.damage = 80;
+  shipvals[ASSAULT].s_phaser.speed = 4800;
+  shipvals[ASSAULT].s_phaser.cost = 560;
+  shipvals[ASSAULT].s_phaser.fuse = 10;
+  shipvals[ASSAULT].s_phaser.wtemp = 56;
+  shipvals[ASSAULT].s_missile.damage = 0;
+  shipvals[ASSAULT].s_missile.speed = 0;
+  shipvals[ASSAULT].s_missile.cost = 0;
+  shipvals[ASSAULT].s_missile.fuse = 0;
+  shipvals[ASSAULT].s_missile.wtemp = 0;
+  shipvals[ASSAULT].s_missile.count = 0;
+  shipvals[ASSAULT].s_missile.aux = 0;
+  shipvals[ASSAULT].s_missilestored = 0;
+  shipvals[ASSAULT].s_plasma.damage = -1;
+  shipvals[ASSAULT].s_plasma.speed = 0;
+  shipvals[ASSAULT].s_plasma.cost = 0;
+  shipvals[ASSAULT].s_plasma.fuse = 0;
+  shipvals[ASSAULT].s_plasma.wtemp = 5;
+  shipvals[ASSAULT].s_plasma.aux = 0;
+  shipvals[ASSAULT].s_maxwpntemp = 1000;
+  shipvals[ASSAULT].s_wpncoolrate = 2;
+  if (configvals->bronco_shipvals)
+    shipvals[ASSAULT].s_maxegntemp = 1000;
+  else
+    shipvals[ASSAULT].s_maxegntemp = 1700;
+  shipvals[ASSAULT].s_egncoolrate = 6;
+  shipvals[ASSAULT].s_maxfuel = 6000;
+  if (configvals->bronco_shipvals)
+    shipvals[ASSAULT].s_recharge = 20;
+  else
+    shipvals[ASSAULT].s_recharge = 24;
+  shipvals[ASSAULT].s_mingivefuel = 0;
+  shipvals[ASSAULT].s_takeonfuel = 150;
+  if (configvals->fuel_explosions)
+  {
+    shipvals[ASSAULT].s_expldam = 70;	/* was: 50; (BG) */
+    shipvals[ASSAULT].s_fueldam = 40;	/* was: 45; (BG) */
+  }
+  else
+  {
+    shipvals[ASSAULT].s_expldam = 100;
+    shipvals[ASSAULT].s_fueldam = 0;
+  }
+  shipvals[ASSAULT].s_armyperkill = 3;
+  shipvals[ASSAULT].s_maxarmies = 20;
+  if (configvals->bronco_shipvals)
+    shipvals[ASSAULT].s_bomb = 25;
+  else
+    shipvals[ASSAULT].s_bomb = 50;
+  shipvals[ASSAULT].s_repair = 120;
+  shipvals[ASSAULT].s_maxdamage = 200;
+  shipvals[ASSAULT].s_maxshield = 80;
+  shipvals[ASSAULT].s_shieldcost = 3;
+  shipvals[ASSAULT].s_detcost = 100;
+  shipvals[ASSAULT].s_detdist = 1750;
+  if (configvals->bronco_shipvals)
+    shipvals[ASSAULT].s_cloakcost = 85;
+  else
+    shipvals[ASSAULT].s_cloakcost = 80;
+#ifdef LONG_SCANRANGE
+  shipvals[ASSAULT].s_scanrange = 1000;
+#else
+  shipvals[ASSAULT].s_scanrange = -1;
+#endif
+  shipvals[ASSAULT].s_numports = 0;
+  shipvals[ASSAULT].s_letter = 'a';
+  shipvals[ASSAULT].s_desig1 = 'A';
+  shipvals[ASSAULT].s_desig2 = 'S';
+  shipvals[ASSAULT].s_bitmap = 4;
+  shipvals[ASSAULT].s_width = 20;
+  shipvals[ASSAULT].s_height = 20;
+  shipvals[ASSAULT].s_timer = 0;
+  shipvals[ASSAULT].s_maxnum = 32;
+  shipvals[ASSAULT].s_rank = 0;
+  shipvals[ASSAULT].s_numdefn = 0;
+  shipvals[ASSAULT].s_numplan = 0;
+  if (configvals->warpdrive)
+    shipvals[ASSAULT].s_nflags = SFNCANORBIT | SFNARMYNEEDKILL | SFNCANWARP | SFNHASPHASERS;
+  else
+    shipvals[ASSAULT].s_nflags = SFNCANORBIT | SFNARMYNEEDKILL | SFNHASPHASERS;
+
+  /* comprehensive definition of STARBASE */
+  shipvals[STARBASE].s_alttype = 5;
+  strcpy(shipvals[STARBASE].s_name, "Starbase");
+  shipvals[STARBASE].s_turns = 50000;
+  shipvals[STARBASE].s_imp.acc = 100;
+  shipvals[STARBASE].s_imp.dec = 200;
+  if (configvals->bronco_shipvals)
+    shipvals[STARBASE].s_imp.cost = 10;
+  else
+    shipvals[STARBASE].s_imp.cost = 4;
+#ifdef BEEFY_BASES
+  shipvals[STARBASE].s_imp.maxspeed = 3;
+#else
+  shipvals[STARBASE].s_imp.maxspeed = 2;
+#endif
+  shipvals[STARBASE].s_imp.etemp = 1000;
+  shipvals[STARBASE].s_after.acc = 100;
+  shipvals[STARBASE].s_after.dec = 100;
+  shipvals[STARBASE].s_after.cost = 40;
+  shipvals[STARBASE].s_after.maxspeed = 5;
+  shipvals[STARBASE].s_after.etemp = 30000;
+  if (configvals->bronco_shipvals)
+  {
+    shipvals[STARBASE].s_warp.acc = 100;
+    shipvals[STARBASE].s_warp.dec = 100;
+    shipvals[STARBASE].s_warp.cost = 20;
+    shipvals[STARBASE].s_warp.maxspeed = 4;
+    shipvals[STARBASE].s_warp.etemp = 1500;
+    shipvals[STARBASE].s_warpinitcost = 10909;
+    shipvals[STARBASE].s_warpinittime = 100;
+    shipvals[STARBASE].s_warpprepspeed = 1;
+  }
+  else
+  {
+    shipvals[STARBASE].s_warp.acc = 100;
+    shipvals[STARBASE].s_warp.dec = 100;
+    shipvals[STARBASE].s_warp.cost = 20;
+    shipvals[STARBASE].s_warp.maxspeed = 6;
+    shipvals[STARBASE].s_warp.etemp = 1500;
+    shipvals[STARBASE].s_warpinitcost = 10909;
+    shipvals[STARBASE].s_warpinittime = 100;
+    shipvals[STARBASE].s_warpprepspeed = 2;
+  }
+  shipvals[STARBASE].s_mass = 5000;
+  shipvals[STARBASE].s_tractstr = 8000;
+  shipvals[STARBASE].s_tractrng = 1.5;
+  shipvals[STARBASE].s_tractcost = 10;
+  shipvals[STARBASE].s_tractetemp = 3000;
+  shipvals[STARBASE].s_torp.damage = 30;
+  shipvals[STARBASE].s_torp.speed = 14;
+  shipvals[STARBASE].s_torp.cost = 300;
+  if (configvals->bronco_shipvals)
+    shipvals[STARBASE].s_torp.fuse = 30;
+  else
+    shipvals[STARBASE].s_torp.fuse = 45;
+  shipvals[STARBASE].s_torp.wtemp = 20;
+  shipvals[STARBASE].s_torp.wtemp_halfarc = 0;
+  shipvals[STARBASE].s_torp.wtemp_factor = 0;
+  shipvals[STARBASE].s_torp.aux = 0;
+  shipvals[STARBASE].s_phaser.damage = 120;
+#ifndef OLDSHIPVALS
+  shipvals[STARBASE].s_phaser.speed = 7200;
+  shipvals[STARBASE].s_phaser.wtemp = 96;
+#else
+  shipvals[STARBASE].s_phaser.speed = 6500;
+  shipvals[STARBASE].s_phaser.wtemp = 66;
+#endif
+  shipvals[STARBASE].s_phaser.cost = 960;
+  shipvals[STARBASE].s_phaser.fuse = 4;
+  shipvals[STARBASE].s_missile.damage = 40;
+  shipvals[STARBASE].s_missile.speed = 14;
+  shipvals[STARBASE].s_missile.cost = 2000;
+  shipvals[STARBASE].s_missile.fuse = 100;
+  shipvals[STARBASE].s_missile.wtemp = 120;
+  shipvals[STARBASE].s_missile.count = 4;
+  shipvals[STARBASE].s_missile.aux = 2;
+  shipvals[STARBASE].s_missilestored = -1;
+  shipvals[STARBASE].s_plasma.damage = 150;
+  shipvals[STARBASE].s_plasma.speed = 15;
+  shipvals[STARBASE].s_plasma.cost = 3750;
+  if (configvals->bronco_shipvals)
+    shipvals[STARBASE].s_plasma.fuse = 25;
+  else
+    shipvals[STARBASE].s_plasma.fuse = 40;
+  shipvals[STARBASE].s_plasma.wtemp = 367;
+  shipvals[STARBASE].s_plasma.aux = 1;
+  shipvals[STARBASE].s_maxwpntemp = 1300;
+#ifdef BEEFY_BASES
+  shipvals[STARBASE].s_wpncoolrate = 7;
+#else
+  shipvals[STARBASE].s_wpncoolrate = 4;
+#endif
+  if (configvals->bronco_shipvals)
+    shipvals[STARBASE].s_maxegntemp = 1000;
+  else
+    shipvals[STARBASE].s_maxegntemp = 1300;
+  shipvals[STARBASE].s_egncoolrate = 10;
+  shipvals[STARBASE].s_maxfuel = 60000;
+#ifdef BEEFY_BASES
+  shipvals[STARBASE].s_recharge = 90;
+#else
+  shipvals[STARBASE].s_recharge = 70;
+#endif
+  shipvals[STARBASE].s_mingivefuel = 10000;
+  shipvals[STARBASE].s_takeonfuel = 150;
+  if (configvals->fuel_explosions)
+  {
+    shipvals[STARBASE].s_expldam = 150;	/* was: 100; (BG) */
+    shipvals[STARBASE].s_fueldam = 100;
+  }
+  else
+  {
+    shipvals[STARBASE].s_expldam = 200;
+    shipvals[STARBASE].s_fueldam = 0;
+  }
+  shipvals[STARBASE].s_armyperkill = 5;
+  shipvals[STARBASE].s_maxarmies = 25;
+  shipvals[STARBASE].s_bomb = 50;
+  shipvals[STARBASE].s_repair = 170;	/* was: 140; (BG) */
+  shipvals[STARBASE].s_maxdamage = 600;
+  shipvals[STARBASE].s_maxshield = 500;
+  shipvals[STARBASE].s_shieldcost = 10;
+  shipvals[STARBASE].s_detcost = 100;
+  shipvals[STARBASE].s_detdist = 1800;
+  if (configvals->bronco_shipvals)
+  {
+    shipvals[STARBASE].s_cloakcost = 375;
+    shipvals[STARBASE].s_scanrange = -1;
+    shipvals[STARBASE].s_numports = 4;
+  }
+  else
+  {
+    shipvals[STARBASE].s_cloakcost = 750;
+#ifdef LONG_SCANRANGE
+    shipvals[STARBASE].s_scanrange = 10000;
+#else
+    shipvals[STARBASE].s_scanrange = 5000;
+#endif
+    shipvals[STARBASE].s_numports = 6;
+  }
+  shipvals[STARBASE].s_letter = 'o';
+  shipvals[STARBASE].s_desig1 = 'S';
+  shipvals[STARBASE].s_desig2 = 'B';
+  shipvals[STARBASE].s_bitmap = 5;
+  shipvals[STARBASE].s_width = 20;
+  shipvals[STARBASE].s_height = 20;
+  shipvals[STARBASE].s_timer = 30;
+  shipvals[STARBASE].s_maxnum = 1;
+  shipvals[STARBASE].s_rank = 4;
+  shipvals[STARBASE].s_numdefn = 4;
+  if (configvals->bronco_shipvals)
+    shipvals[STARBASE].s_numplan = 5;
+  else
+    shipvals[STARBASE].s_numplan = 7;
+  if (configvals->warpdrive)
+    shipvals[STARBASE].s_nflags = SFNCANWARP | SFNCANFUEL | SFNCANREPAIR | SFNCANREFIT | SFNHASPHASERS | SFNPLASMASTYLE | SFNPLASMAARMED | SFNHASMISSILE;
+  else
+    shipvals[STARBASE].s_nflags = SFNCANFUEL | SFNCANREPAIR | SFNCANREFIT | SFNHASPHASERS | SFNPLASMASTYLE | SFNPLASMAARMED | SFNHASMISSILE;
+  /* comprehensive definition of ATT */
+  shipvals[ATT].s_alttype = 6;
+  strcpy(shipvals[ATT].s_name, "AT&T");
+  shipvals[ATT].s_turns = 1000000;
+  shipvals[ATT].s_imp.acc = 10000;
+  shipvals[ATT].s_imp.dec = 9000;
+  shipvals[ATT].s_imp.cost = 1;
+  shipvals[ATT].s_imp.maxspeed = 90;
+  shipvals[ATT].s_imp.etemp = 0;
+  shipvals[ATT].s_after.acc = 550;
+  shipvals[ATT].s_after.dec = 270;
+  shipvals[ATT].s_after.cost = 1;
+  shipvals[ATT].s_after.maxspeed = 99;
+  shipvals[ATT].s_after.etemp = 5;
+  shipvals[ATT].s_warp.acc = 32000;
+  shipvals[ATT].s_warp.dec = 32000;
+  shipvals[ATT].s_warp.cost = 1;
+  shipvals[ATT].s_warp.maxspeed = 99;
+  shipvals[ATT].s_warp.etemp = 1;
+  shipvals[ATT].s_warpinitcost = 1;
+  shipvals[ATT].s_warpinittime = 1;
+  shipvals[ATT].s_warpprepspeed = 0;
+  shipvals[ATT].s_mass = 6000;
+  shipvals[ATT].s_tractstr = 32000;
+  shipvals[ATT].s_tractrng = 3;
+  shipvals[ATT].s_tractcost = 1;
+  shipvals[ATT].s_tractetemp = 3;
+  shipvals[ATT].s_torp.damage = 40;
+  shipvals[ATT].s_torp.speed = 20;
+  shipvals[ATT].s_torp.cost = 1;
+  shipvals[ATT].s_torp.fuse = 20;
+  shipvals[ATT].s_torp.wtemp = 1;
+  shipvals[ATT].s_torp.wtemp_halfarc = 0;
+  shipvals[ATT].s_torp.wtemp_factor = 0;
+  shipvals[ATT].s_torp.aux = 1;
+  shipvals[ATT].s_phaser.damage = 110;
+  shipvals[ATT].s_phaser.speed = 32000;
+  shipvals[ATT].s_phaser.cost = 1;
+  shipvals[ATT].s_phaser.fuse = 5;
+  shipvals[ATT].s_phaser.wtemp = 5;
+  shipvals[ATT].s_missile.damage = 0;
+  shipvals[ATT].s_missile.speed = 0;
+  shipvals[ATT].s_missile.cost = 0;
+  shipvals[ATT].s_missile.fuse = 0;
+  shipvals[ATT].s_missile.wtemp = 0;
+  shipvals[ATT].s_missile.count = 0;
+  shipvals[ATT].s_missile.aux = 0;
+  shipvals[ATT].s_missilestored = 0;
+  shipvals[ATT].s_plasma.damage = 150;
+  shipvals[ATT].s_plasma.speed = 15;
+  shipvals[ATT].s_plasma.cost = 1;
+  shipvals[ATT].s_plasma.fuse = 20;
+  shipvals[ATT].s_plasma.wtemp = 5;
+  shipvals[ATT].s_plasma.aux = 2;
+  shipvals[ATT].s_maxwpntemp = 10000;
+  shipvals[ATT].s_wpncoolrate = 100;
+  shipvals[ATT].s_maxegntemp = 10000;
+  shipvals[ATT].s_egncoolrate = 100;
+  shipvals[ATT].s_maxfuel = 60000;
+  shipvals[ATT].s_recharge = 1000;
+  shipvals[ATT].s_mingivefuel = 0;
+  shipvals[ATT].s_takeonfuel = 150;
+  shipvals[ATT].s_expldam = 500;
+  shipvals[ATT].s_fueldam = 500;
+  shipvals[ATT].s_armyperkill = 1.5;
+  shipvals[ATT].s_maxarmies = 1000;
+  shipvals[ATT].s_bomb = -2100;
+  shipvals[ATT].s_repair = 30000;
+  shipvals[ATT].s_maxdamage = 30000;
+  shipvals[ATT].s_maxshield = 30000;
+  shipvals[ATT].s_shieldcost = 1;
+  shipvals[ATT].s_detcost = 1;
+  shipvals[ATT].s_detdist = 3000;
+  shipvals[ATT].s_cloakcost = 1;
+  shipvals[ATT].s_scanrange = 10000;
+  shipvals[ATT].s_numports = 0;
+  shipvals[ATT].s_letter = '.';
+  shipvals[ATT].s_desig1 = 'A';
+  shipvals[ATT].s_desig2 = 'T';
+  shipvals[ATT].s_bitmap = 6;
+  shipvals[ATT].s_width = 28;
+  shipvals[ATT].s_height = 28;
+  shipvals[ATT].s_timer = 5;
+  shipvals[ATT].s_maxnum = 32;
+  shipvals[ATT].s_rank = 0;
+  shipvals[ATT].s_numdefn = 0;
+  shipvals[ATT].s_numplan = 0;
+  shipvals[ATT].s_nflags = SFNCANORBIT | SFNARMYNEEDKILL | SFNCANWARP | SFNHASPHASERS | SFNPLASMASTYLE | SFNPLASMAARMED;
+
+  /* comprehensive definition of JUMPSHIP */
+  shipvals[JUMPSHIP].s_alttype = 5;
+  strcpy(shipvals[JUMPSHIP].s_name, "Jumpship");
+  shipvals[JUMPSHIP].s_turns = 700000;
+  if (configvals->bronco_shipvals)
+  {
+    shipvals[JUMPSHIP].s_imp.acc = 1000;
+    shipvals[JUMPSHIP].s_imp.dec = 500;
+  }
+  else
+  {
+    shipvals[JUMPSHIP].s_imp.acc = 2000;
+    shipvals[JUMPSHIP].s_imp.dec = 1000;
+  }
+  shipvals[JUMPSHIP].s_imp.cost = 1;
+  shipvals[JUMPSHIP].s_imp.maxspeed = 20;
+  shipvals[JUMPSHIP].s_imp.etemp = 1000;
+  shipvals[JUMPSHIP].s_after.acc = 2000;
+  shipvals[JUMPSHIP].s_after.dec = 2000;
+#ifndef OLDSHIPVALS
+  shipvals[JUMPSHIP].s_after.maxspeed = 30;
+  shipvals[JUMPSHIP].s_after.etemp = 200000;
+  shipvals[JUMPSHIP].s_after.cost = 1000;
+  shipvals[JUMPSHIP].s_warp.cost = 200;
+#else
+  shipvals[JUMPSHIP].s_after.maxspeed = 60;
+  shipvals[JUMPSHIP].s_after.etemp = 90000;
+  shipvals[JUMPSHIP].s_after.cost = 15;
+  shipvals[JUMPSHIP].s_warp.cost = 2;
+#endif
+  shipvals[JUMPSHIP].s_warp.acc = 2000;
+  shipvals[JUMPSHIP].s_warp.dec = 3000;
+  if (configvals->bronco_shipvals)
+    shipvals[JUMPSHIP].s_warp.maxspeed = 32;
+  else
+    shipvals[JUMPSHIP].s_warp.maxspeed = 45;
+  shipvals[JUMPSHIP].s_warp.etemp = 500;
+  shipvals[JUMPSHIP].s_warpinitcost = 1;
+  shipvals[JUMPSHIP].s_warpinittime = 7;
+  shipvals[JUMPSHIP].s_warpprepspeed = 2;
+  shipvals[JUMPSHIP].s_mass = 10000;
+  shipvals[JUMPSHIP].s_tractstr = 5000;
+  shipvals[JUMPSHIP].s_tractrng = 1.5;
+#ifndef OLDSHIPVALS
+  shipvals[JUMPSHIP].s_tractcost = 8;
+#else
+  shipvals[JUMPSHIP].s_tractcost = 3;
+#endif
+  shipvals[JUMPSHIP].s_tractetemp = 5000;
+  shipvals[JUMPSHIP].s_torp.damage = 5;
+  shipvals[JUMPSHIP].s_torp.speed = 18;
+  shipvals[JUMPSHIP].s_torp.cost = 1000;
+  shipvals[JUMPSHIP].s_torp.fuse = 10;
+  shipvals[JUMPSHIP].s_torp.wtemp = 99;
+  shipvals[JUMPSHIP].s_torp.wtemp_halfarc = 32;
+  shipvals[JUMPSHIP].s_torp.wtemp_factor = 9;
+  shipvals[JUMPSHIP].s_torp.aux = 0;
+  shipvals[JUMPSHIP].s_phaser.damage = 25;
+  shipvals[JUMPSHIP].s_phaser.speed = 3000;
+  shipvals[JUMPSHIP].s_phaser.cost = 500;
+  shipvals[JUMPSHIP].s_phaser.fuse = 4;
+  shipvals[JUMPSHIP].s_phaser.wtemp = 5;
+  shipvals[JUMPSHIP].s_missile.damage = 0;
+  shipvals[JUMPSHIP].s_missile.speed = 0;
+  shipvals[JUMPSHIP].s_missile.cost = 0;
+  shipvals[JUMPSHIP].s_missile.fuse = 0;
+  shipvals[JUMPSHIP].s_missile.wtemp = 0;
+  shipvals[JUMPSHIP].s_missile.count = 0;
+  shipvals[JUMPSHIP].s_missile.aux = 0;
+  shipvals[JUMPSHIP].s_missilestored = 0;
+  shipvals[JUMPSHIP].s_plasma.damage = -1;
+  shipvals[JUMPSHIP].s_plasma.speed = 15;
+  shipvals[JUMPSHIP].s_plasma.cost = 0;
+  shipvals[JUMPSHIP].s_plasma.fuse = 25;
+  shipvals[JUMPSHIP].s_plasma.wtemp = 5;
+  shipvals[JUMPSHIP].s_plasma.aux = 1;
+  shipvals[JUMPSHIP].s_maxwpntemp = 1300;
+  shipvals[JUMPSHIP].s_wpncoolrate = 4;
+  shipvals[JUMPSHIP].s_maxegntemp = 5000;
+  shipvals[JUMPSHIP].s_egncoolrate = 34;
+  shipvals[JUMPSHIP].s_maxfuel = 50000;
+  shipvals[JUMPSHIP].s_recharge = 200;
+  shipvals[JUMPSHIP].s_mingivefuel = 10000;
+  shipvals[JUMPSHIP].s_takeonfuel = 150;
+  if (configvals->fuel_explosions)
+  {
+    shipvals[JUMPSHIP].s_expldam = 25;	/* was: 30; */
+    shipvals[JUMPSHIP].s_fueldam = 175;	/* was: 160; */
+  }
+  else
+  {
+    shipvals[JUMPSHIP].s_expldam = 150;
+    shipvals[JUMPSHIP].s_fueldam = 0;
+  }
+  shipvals[JUMPSHIP].s_armyperkill = 0;
+  shipvals[JUMPSHIP].s_maxarmies = 0;
+  shipvals[JUMPSHIP].s_bomb = 30;
+  shipvals[JUMPSHIP].s_repair = 200;
+  shipvals[JUMPSHIP].s_maxdamage = 60;
+  shipvals[JUMPSHIP].s_maxshield = 5;
+  shipvals[JUMPSHIP].s_shieldcost = 5;
+  shipvals[JUMPSHIP].s_detcost = 100;
+  shipvals[JUMPSHIP].s_detdist = 1750;
+  shipvals[JUMPSHIP].s_cloakcost = 1000;
+  shipvals[JUMPSHIP].s_scanrange = -1;
+  shipvals[JUMPSHIP].s_numports = 4;
+  shipvals[JUMPSHIP].s_letter = 'j';
+  shipvals[JUMPSHIP].s_desig1 = 'J';
+  shipvals[JUMPSHIP].s_desig2 = 'S';
+  shipvals[JUMPSHIP].s_bitmap = 7;
+  shipvals[JUMPSHIP].s_width = 20;
+  shipvals[JUMPSHIP].s_height = 20;
+  shipvals[JUMPSHIP].s_timer = 5;
+  shipvals[JUMPSHIP].s_maxnum = 1;
+  shipvals[JUMPSHIP].s_rank = 3;
+  shipvals[JUMPSHIP].s_numdefn = 3;
+  shipvals[JUMPSHIP].s_numplan = 0;
+  /* UFL says jumpships shouldn't refit. */
+  if (configvals->warpdrive)
+    shipvals[JUMPSHIP].s_nflags = SFNCANWARP | SFNCANFUEL | SFNHASPHASERS | SFNCANREFIT;
+  else
+    shipvals[JUMPSHIP].s_nflags = SFNCANFUEL | SFNHASPHASERS | SFNCANREFIT;
+
+  /* comprehensive definition of FRIGATE */
+  shipvals[FRIGATE].s_alttype = 4;
+  strcpy(shipvals[FRIGATE].s_name, "Frigate");
+  shipvals[FRIGATE].s_turns = 122500;
+  shipvals[FRIGATE].s_imp.acc = 115;
+  shipvals[FRIGATE].s_imp.dec = 190;
+  shipvals[FRIGATE].s_imp.cost = 5;
+  shipvals[FRIGATE].s_imp.maxspeed = 9;
+  shipvals[FRIGATE].s_imp.etemp = 1000;
+  shipvals[FRIGATE].s_after.acc = 525;
+  shipvals[FRIGATE].s_after.dec = 270;
+  shipvals[FRIGATE].s_after.cost = 150;
+  shipvals[FRIGATE].s_after.maxspeed = 10;
+  shipvals[FRIGATE].s_after.etemp = 50000;
+  shipvals[FRIGATE].s_warp.acc = 10000;
+  shipvals[FRIGATE].s_warp.dec = 500;
+  shipvals[FRIGATE].s_warp.cost = 30;
+  if (configvals->bronco_shipvals)
+    shipvals[FRIGATE].s_warp.maxspeed = 12;
+  else
+    shipvals[FRIGATE].s_warp.maxspeed = 23;
+  shipvals[FRIGATE].s_warp.etemp = 7000;
+  shipvals[FRIGATE].s_warpinitcost = 2272;
+  shipvals[FRIGATE].s_warpinittime = 65;
+  if (configvals->bronco_shipvals)
+    shipvals[FRIGATE].s_warpprepspeed = 1;
+  else
+    shipvals[FRIGATE].s_warpprepspeed = 2;
+  shipvals[FRIGATE].s_mass = 2150;
+  shipvals[FRIGATE].s_tractstr = 3400;
+  shipvals[FRIGATE].s_tractrng = 1.1;
+  shipvals[FRIGATE].s_tractcost = 4;
+  shipvals[FRIGATE].s_tractetemp = 1000;
+  shipvals[FRIGATE].s_torp.damage = 40;
+  shipvals[FRIGATE].s_torp.speed = 12;
+  shipvals[FRIGATE].s_torp.cost = 290;
+  shipvals[FRIGATE].s_torp.fuse = 40;
+  shipvals[FRIGATE].s_torp.wtemp = 19;
+  shipvals[FRIGATE].s_torp.wtemp_halfarc = 32;
+  shipvals[FRIGATE].s_torp.wtemp_factor = 9;
+  shipvals[FRIGATE].s_torp.aux = 0;
+#ifndef OLDSHIPVALS
+  shipvals[FRIGATE].s_phaser.damage = 102;
+  shipvals[FRIGATE].s_phaser.speed = 6150;
+  shipvals[FRIGATE].s_phaser.cost = 816;
+#else
+  shipvals[FRIGATE].s_phaser.damage = 100;
+  shipvals[FRIGATE].s_phaser.speed = 5750;
+  shipvals[FRIGATE].s_phaser.cost = 800;
+#endif
+  shipvals[FRIGATE].s_phaser.fuse = 10;
+  shipvals[FRIGATE].s_phaser.wtemp = 80;
+  shipvals[FRIGATE].s_missile.damage = 23;
+  shipvals[FRIGATE].s_missile.speed = 6;
+  shipvals[FRIGATE].s_missile.cost = 850;
+  shipvals[FRIGATE].s_missile.fuse = 100;
+  shipvals[FRIGATE].s_missile.wtemp = 100;
+  shipvals[FRIGATE].s_missile.count = 3;
+  shipvals[FRIGATE].s_missile.aux = 2;
+  shipvals[FRIGATE].s_missilestored = 11;
+  shipvals[FRIGATE].s_plasma.damage = 115;
+  shipvals[FRIGATE].s_plasma.speed = 15;
+  shipvals[FRIGATE].s_plasma.cost = 3450;
+  shipvals[FRIGATE].s_plasma.fuse = 35;
+  shipvals[FRIGATE].s_plasma.wtemp = 337;
+  shipvals[FRIGATE].s_plasma.aux = 1;
+  shipvals[FRIGATE].s_maxwpntemp = 1000;
+  shipvals[FRIGATE].s_wpncoolrate = 3;
+  shipvals[FRIGATE].s_maxegntemp = 1500;
+  shipvals[FRIGATE].s_egncoolrate = 6;
+  shipvals[FRIGATE].s_maxfuel = 12500;
+  shipvals[FRIGATE].s_recharge = 26;
+  shipvals[FRIGATE].s_mingivefuel = 0;
+  shipvals[FRIGATE].s_takeonfuel = 150;
+  if (configvals->fuel_explosions)
+  {
+    shipvals[FRIGATE].s_expldam = 77;	/* was: 50; (BG) */
+    shipvals[FRIGATE].s_fueldam = 40;	/* was: 72; (BG) */
+  }
+  else
+  {
+    shipvals[FRIGATE].s_expldam = 100;
+    shipvals[FRIGATE].s_fueldam = 0;
+  }
+  shipvals[FRIGATE].s_armyperkill = 2;
+#ifndef OLDSHIPVALS
+  shipvals[FRIGATE].s_maxarmies = 6;
+#else
+  shipvals[FRIGATE].s_maxarmies = 8;
+#endif
+  shipvals[FRIGATE].s_bomb = 15;
+  shipvals[FRIGATE].s_repair = 118;
+  shipvals[FRIGATE].s_maxdamage = 115;
+  shipvals[FRIGATE].s_maxshield = 115;
+  shipvals[FRIGATE].s_shieldcost = 5;
+  shipvals[FRIGATE].s_detcost = 100;
+  shipvals[FRIGATE].s_detdist = 1750;
+  if (configvals->bronco_shipvals)
+    shipvals[FRIGATE].s_cloakcost = 140;
+  else
+    shipvals[FRIGATE].s_cloakcost = 125;
+#ifdef LONG_SCANRANGE
+  shipvals[FRIGATE].s_scanrange = 1000;
+#else
+  shipvals[FRIGATE].s_scanrange = -1;
+#endif
+  shipvals[FRIGATE].s_numports = 0;
+  shipvals[FRIGATE].s_letter = 'f';
+  shipvals[FRIGATE].s_desig1 = 'F';
+  shipvals[FRIGATE].s_desig2 = 'R';
+  shipvals[FRIGATE].s_bitmap = 8;
+  shipvals[FRIGATE].s_width = 20;
+  shipvals[FRIGATE].s_height = 20;
+  shipvals[FRIGATE].s_timer = 0;
+  shipvals[FRIGATE].s_maxnum = 32;
+  shipvals[FRIGATE].s_rank = 0;
+  shipvals[FRIGATE].s_numdefn = 0;
+  shipvals[FRIGATE].s_numplan = 0;
+  if (configvals->warpdrive)
+    shipvals[FRIGATE].s_nflags = SFNCANORBIT | SFNARMYNEEDKILL | SFNCANWARP | SFNHASPHASERS;
+  else
+    shipvals[FRIGATE].s_nflags = SFNCANORBIT | SFNARMYNEEDKILL | SFNHASPHASERS;
+
+  /* comprehensive definition of WARBASE */
+  shipvals[WARBASE].s_alttype = 5;
+  strcpy(shipvals[WARBASE].s_name, "Warbase");
+  shipvals[WARBASE].s_turns = 90000;
+  shipvals[WARBASE].s_imp.acc = 100;
+  shipvals[WARBASE].s_imp.dec = 200;
+  shipvals[WARBASE].s_imp.cost = 4;
+#ifdef BEEFY_BASES
+  shipvals[WARBASE].s_imp.maxspeed = 3;
+#else
+  shipvals[WARBASE].s_imp.maxspeed = 2;
+#endif
+  shipvals[WARBASE].s_imp.etemp = 1000;
+  shipvals[WARBASE].s_after.acc = 250;
+  shipvals[WARBASE].s_after.dec = 100;
+  shipvals[WARBASE].s_after.cost = 40;
+  shipvals[WARBASE].s_after.maxspeed = 5;
+  shipvals[WARBASE].s_after.etemp = 30000;
+  shipvals[WARBASE].s_warp.acc = 80;
+  shipvals[WARBASE].s_warp.dec = 80;
+  shipvals[WARBASE].s_warp.cost = 6;
+  if (configvals->bronco_shipvals)
+  {
+    shipvals[WARBASE].s_warp.maxspeed = 4;
+    shipvals[WARBASE].s_warpprepspeed = 1;
+  }
+  else
+  {
+    shipvals[WARBASE].s_warp.maxspeed = 6;
+    shipvals[WARBASE].s_warpprepspeed = 2;
+  }
+  shipvals[WARBASE].s_warp.etemp = 1500;
+  shipvals[WARBASE].s_warpinitcost = 9090;
+  shipvals[WARBASE].s_warpinittime = 100;
+  shipvals[WARBASE].s_mass = 4000;
+  shipvals[WARBASE].s_tractstr = 8000;
+  shipvals[WARBASE].s_tractrng = 1.5;
+  shipvals[WARBASE].s_tractcost = 10;
+  shipvals[WARBASE].s_tractetemp = 3000;
+  shipvals[WARBASE].s_torp.damage = 45;
+  shipvals[WARBASE].s_torp.speed = 15;
+  shipvals[WARBASE].s_torp.cost = 450;
+#ifndef OLDSHIPVALS
+  shipvals[WARBASE].s_torp.fuse = 20;
+#else
+  shipvals[WARBASE].s_torp.fuse = 18;
+#endif
+  shipvals[WARBASE].s_torp.wtemp = 35;
+  shipvals[WARBASE].s_torp.wtemp_halfarc = 32;
+  shipvals[WARBASE].s_torp.wtemp_factor = 9;
+  shipvals[WARBASE].s_torp.aux = 0;
+#ifndef OLDSHIPVALS
+  shipvals[WARBASE].s_phaser.damage = 125;
+  shipvals[WARBASE].s_phaser.speed = 7500;
+  shipvals[WARBASE].s_phaser.cost = 1000;
+#else
+  shipvals[WARBASE].s_phaser.damage = 135;
+  shipvals[WARBASE].s_phaser.speed = 6000;
+  shipvals[WARBASE].s_phaser.cost = 1150;
+#endif
+  shipvals[WARBASE].s_phaser.fuse = 5;
+  shipvals[WARBASE].s_phaser.wtemp = 90;
+  shipvals[WARBASE].s_missile.damage = 40;
+  shipvals[WARBASE].s_missile.speed = 14;
+  shipvals[WARBASE].s_missile.cost = 2000;
+  shipvals[WARBASE].s_missile.fuse = 100;
+  shipvals[WARBASE].s_missile.wtemp = 120;
+  shipvals[WARBASE].s_missile.count = 3;
+  shipvals[WARBASE].s_missile.aux = 2;
+  shipvals[WARBASE].s_missilestored = -1;
+  shipvals[WARBASE].s_plasma.damage = 150;
+  shipvals[WARBASE].s_plasma.speed = 15;
+  shipvals[WARBASE].s_plasma.cost = 3750;
+  shipvals[WARBASE].s_plasma.fuse = 40;
+  shipvals[WARBASE].s_plasma.wtemp = 360;
+  shipvals[WARBASE].s_plasma.aux = 1;
+  shipvals[WARBASE].s_maxwpntemp = 1500;
+  shipvals[WARBASE].s_wpncoolrate = 5;
+  shipvals[WARBASE].s_maxegntemp = 1000;
+  shipvals[WARBASE].s_egncoolrate = 10;
+  shipvals[WARBASE].s_maxfuel = 50000;
+  if (configvals->bronco_shipvals)
+    shipvals[WARBASE].s_recharge = 70;
+  else
+    shipvals[WARBASE].s_recharge = 80;
+  shipvals[WARBASE].s_mingivefuel = 10000;
+  shipvals[WARBASE].s_takeonfuel = 150;
+  shipvals[WARBASE].s_expldam = 100;
+  shipvals[WARBASE].s_fueldam = 100;
+  shipvals[WARBASE].s_armyperkill = 0;
+  shipvals[WARBASE].s_maxarmies = 0;
+  shipvals[WARBASE].s_bomb = 90;
+  shipvals[WARBASE].s_repair = 170;	/* was: 150; (BG) */
+  shipvals[WARBASE].s_maxdamage = 500;
+  shipvals[WARBASE].s_maxshield = 250;
+  shipvals[WARBASE].s_shieldcost = 10;
+  shipvals[WARBASE].s_detcost = 100;
+  shipvals[WARBASE].s_detdist = 1800;
+  shipvals[WARBASE].s_cloakcost = 1000;
+  shipvals[WARBASE].s_scanrange = 5000;
+  shipvals[WARBASE].s_numports = 2;
+  shipvals[WARBASE].s_letter = 'w';
+  shipvals[WARBASE].s_desig1 = 'W';
+  shipvals[WARBASE].s_desig2 = 'B';
+  shipvals[WARBASE].s_bitmap = 9;
+  shipvals[WARBASE].s_width = 20;
+  shipvals[WARBASE].s_height = 20;
+  shipvals[WARBASE].s_timer = 15;
+  shipvals[WARBASE].s_maxnum = 1;
+  shipvals[WARBASE].s_rank = 3;
+  shipvals[WARBASE].s_numdefn = 3;
+  shipvals[WARBASE].s_numplan = 3;
+  if (configvals->warpdrive)
+    shipvals[WARBASE].s_nflags = SFNCANORBIT | SFNARMYNEEDKILL | SFNCANWARP | SFNCANFUEL | SFNCANREPAIR | SFNHASPHASERS | SFNPLASMASTYLE | SFNPLASMAARMED | SFNHASMISSILE;
+  else
+    shipvals[WARBASE].s_nflags = SFNCANORBIT | SFNARMYNEEDKILL | SFNCANFUEL | SFNCANREPAIR | SFNHASPHASERS | SFNPLASMASTYLE | SFNPLASMAARMED | SFNHASMISSILE;
+
+  /* comprehensive definition of LIGHTCRUISER */
+  shipvals[LIGHTCRUISER].s_alttype = 2;
+  strcpy(shipvals[LIGHTCRUISER].s_name, "Light");
+  shipvals[LIGHTCRUISER].s_turns = 220000;	/* was 225000 */
+  shipvals[LIGHTCRUISER].s_imp.acc = 190;
+  shipvals[LIGHTCRUISER].s_imp.dec = 250;
+  shipvals[LIGHTCRUISER].s_imp.cost = 3;
+  shipvals[LIGHTCRUISER].s_imp.maxspeed = 10;
+  shipvals[LIGHTCRUISER].s_imp.etemp = 1000;
+  shipvals[LIGHTCRUISER].s_after.acc = 720;
+  shipvals[LIGHTCRUISER].s_after.dec = 280;
+  shipvals[LIGHTCRUISER].s_after.cost = 80;
+  shipvals[LIGHTCRUISER].s_after.maxspeed = 12;
+  shipvals[LIGHTCRUISER].s_after.etemp = 35000;
+  shipvals[LIGHTCRUISER].s_warp.acc = 10000;
+  shipvals[LIGHTCRUISER].s_warp.dec = 400;
+  shipvals[LIGHTCRUISER].s_warp.cost = 24;
+  if (configvals->bronco_shipvals)
+  {
+    shipvals[LIGHTCRUISER].s_warp.maxspeed = 16;
+    shipvals[LIGHTCRUISER].s_warpprepspeed = 1;
+  }
+  else
+  {
+    shipvals[LIGHTCRUISER].s_warp.maxspeed = 27;	/* was: 24; (BG) */
+    shipvals[LIGHTCRUISER].s_warpprepspeed = 2;
+  }
+  shipvals[LIGHTCRUISER].s_warp.etemp = 7000;
+  shipvals[LIGHTCRUISER].s_warpinitcost = 1550;
+  shipvals[LIGHTCRUISER].s_warpinittime = 45;
+  shipvals[LIGHTCRUISER].s_mass = 1900;
+  shipvals[LIGHTCRUISER].s_tractstr = 2700;
+  shipvals[LIGHTCRUISER].s_tractrng = 0.9;
+  shipvals[LIGHTCRUISER].s_tractcost = 3;
+  shipvals[LIGHTCRUISER].s_tractetemp = 1000;
+  shipvals[LIGHTCRUISER].s_torp.damage = 35;
+  shipvals[LIGHTCRUISER].s_torp.speed = 13;
+#ifndef OLDSHIPVALS
+  shipvals[LIGHTCRUISER].s_torp.cost = 245;
+#else
+  shipvals[LIGHTCRUISER].s_torp.cost = 240;
+#endif
+  shipvals[LIGHTCRUISER].s_torp.fuse = 35;
+  shipvals[LIGHTCRUISER].s_torp.wtemp = 16;
+  shipvals[LIGHTCRUISER].s_torp.wtemp_halfarc = 32;
+  shipvals[LIGHTCRUISER].s_torp.wtemp_factor = 9;
+  shipvals[LIGHTCRUISER].s_torp.aux = 0;
+  shipvals[LIGHTCRUISER].s_phaser.damage = 90;
+#ifndef OLDSHIPVALS
+  shipvals[LIGHTCRUISER].s_phaser.speed = 5400;
+  shipvals[LIGHTCRUISER].s_phaser.cost = 630;
+#else
+  shipvals[LIGHTCRUISER].s_phaser.speed = 5000;
+  shipvals[LIGHTCRUISER].s_phaser.cost = 600;
+#endif
+  shipvals[LIGHTCRUISER].s_phaser.fuse = 10;
+  shipvals[LIGHTCRUISER].s_phaser.wtemp = 60;
+  shipvals[LIGHTCRUISER].s_missile.damage = 22;
+  shipvals[LIGHTCRUISER].s_missile.speed = 7;
+  shipvals[LIGHTCRUISER].s_missile.cost = 800;
+  shipvals[LIGHTCRUISER].s_missile.fuse = 100;
+  shipvals[LIGHTCRUISER].s_missile.wtemp = 100;
+  shipvals[LIGHTCRUISER].s_missile.count = 3;
+  shipvals[LIGHTCRUISER].s_missile.aux = 2;
+  shipvals[LIGHTCRUISER].s_missilestored = 9;
+  shipvals[LIGHTCRUISER].s_plasma.damage = 90;
+  shipvals[LIGHTCRUISER].s_plasma.speed = 15;
+  shipvals[LIGHTCRUISER].s_plasma.cost = 2500;
+  shipvals[LIGHTCRUISER].s_plasma.fuse = 30;
+  shipvals[LIGHTCRUISER].s_plasma.wtemp = 242;
+  shipvals[LIGHTCRUISER].s_plasma.aux = 1;
+  shipvals[LIGHTCRUISER].s_maxwpntemp = 1000;
+  shipvals[LIGHTCRUISER].s_wpncoolrate = 3;
+  shipvals[LIGHTCRUISER].s_maxegntemp = 1500;
+  shipvals[LIGHTCRUISER].s_egncoolrate = 6;
+  shipvals[LIGHTCRUISER].s_maxfuel = 8500;
+  shipvals[LIGHTCRUISER].s_recharge = 23;
+  shipvals[LIGHTCRUISER].s_mingivefuel = 0;
+  shipvals[LIGHTCRUISER].s_takeonfuel = 150;
+  if (configvals->fuel_explosions)
+  {
+    shipvals[LIGHTCRUISER].s_expldam = 67;	/* was: 50; (BG) */
+    shipvals[LIGHTCRUISER].s_fueldam = 45;	/* was: 58; (BG) */
+  }
+  else
+  {
+    shipvals[LIGHTCRUISER].s_expldam = 100;
+    shipvals[LIGHTCRUISER].s_fueldam = 0;
+  }
+  shipvals[LIGHTCRUISER].s_armyperkill = 2;
+  shipvals[LIGHTCRUISER].s_maxarmies = 3;	/* was 4 */
+  shipvals[LIGHTCRUISER].s_bomb = 6;
+  shipvals[LIGHTCRUISER].s_repair = 80;	/* was 90 */
+  shipvals[LIGHTCRUISER].s_maxdamage = 90;
+  shipvals[LIGHTCRUISER].s_maxshield = 95;
+  shipvals[LIGHTCRUISER].s_shieldcost = 4;
+  shipvals[LIGHTCRUISER].s_detcost = 100;
+  shipvals[LIGHTCRUISER].s_detdist = 1750;
+  if (configvals->bronco_shipvals)
+    shipvals[LIGHTCRUISER].s_cloakcost = 115;
+  else
+    shipvals[LIGHTCRUISER].s_cloakcost = 75;
+#ifdef LONG_SCANRANGE
+  shipvals[LIGHTCRUISER].s_scanrange = 1000;
+#else
+  shipvals[LIGHTCRUISER].s_scanrange = 500;
+#endif
+  shipvals[LIGHTCRUISER].s_numports = 0;
+  shipvals[LIGHTCRUISER].s_letter = 'l';
+  shipvals[LIGHTCRUISER].s_desig1 = 'C';
+  shipvals[LIGHTCRUISER].s_desig2 = 'L';
+  shipvals[LIGHTCRUISER].s_bitmap = 10;
+  shipvals[LIGHTCRUISER].s_width = 20;
+  shipvals[LIGHTCRUISER].s_height = 20;
+  shipvals[LIGHTCRUISER].s_timer = 0;
+  shipvals[LIGHTCRUISER].s_maxnum = 32;
+  shipvals[LIGHTCRUISER].s_rank = 0;
+  shipvals[LIGHTCRUISER].s_numdefn = 0;
+  shipvals[LIGHTCRUISER].s_numplan = 0;
+  if (configvals->warpdrive)
+    shipvals[LIGHTCRUISER].s_nflags = SFNCANORBIT | SFNARMYNEEDKILL | SFNCANWARP | SFNHASPHASERS;
+  else
+    shipvals[LIGHTCRUISER].s_nflags = SFNCANORBIT | SFNARMYNEEDKILL | SFNHASPHASERS;
+
+  /* comprehensive definition of CARRIER */
+  shipvals[CARRIER].s_alttype = 3;
+  strcpy(shipvals[CARRIER].s_name, "Carrier");
+  shipvals[CARRIER].s_turns = 60000;
+  shipvals[CARRIER].s_imp.acc = 100;
+  shipvals[CARRIER].s_imp.dec = 200;
+  shipvals[CARRIER].s_imp.cost = 4;
+  shipvals[CARRIER].s_imp.maxspeed = 9;
+  shipvals[CARRIER].s_imp.etemp = 1000;
+  shipvals[CARRIER].s_after.acc = 500;
+  shipvals[CARRIER].s_after.dec = 250;
+  shipvals[CARRIER].s_after.cost = 100;
+  shipvals[CARRIER].s_after.maxspeed = 11;
+  shipvals[CARRIER].s_after.etemp = 50000;
+  shipvals[CARRIER].s_warp.acc = 10000;
+  shipvals[CARRIER].s_warp.dec = 300;
+  shipvals[CARRIER].s_warp.cost = 28;
+  if (configvals->bronco_shipvals)
+  {
+    shipvals[CARRIER].s_warp.maxspeed = 14;
+    shipvals[CARRIER].s_warpprepspeed = 0;
+  }
+  else
+  {
+    shipvals[CARRIER].s_warp.maxspeed = 25;	/* was: 20; (BG) */
+    shipvals[CARRIER].s_warpprepspeed = 1;
+  }
+  shipvals[CARRIER].s_warp.etemp = 7000;
+  shipvals[CARRIER].s_warpinitcost = 2800;
+  shipvals[CARRIER].s_warpinittime = 75;
+  shipvals[CARRIER].s_mass = 2500;
+  shipvals[CARRIER].s_tractstr = 4000;	/* was 3200 (MDM) */
+  shipvals[CARRIER].s_tractrng = 1.3;	/* was 1.1  (MDM) */
+  shipvals[CARRIER].s_tractcost = 5;
+  shipvals[CARRIER].s_tractetemp = 1000;
+  shipvals[CARRIER].s_torp.damage = 30;	/* these are the CVs own torps */
+  shipvals[CARRIER].s_torp.speed = 13;	/* fighter-torps are now constant */
+  shipvals[CARRIER].s_torp.cost = 210;	/* still used when fighters fire! */
+  shipvals[CARRIER].s_torp.fuse = 35;
+  shipvals[CARRIER].s_torp.wtemp = 20;	/* still used when fighters fire! */
+  shipvals[CARRIER].s_torp.wtemp_halfarc = 32;
+  shipvals[CARRIER].s_torp.wtemp_factor = 9;
+  shipvals[CARRIER].s_torp.aux = 0;
+  shipvals[CARRIER].s_phaser.damage = 95;
+  shipvals[CARRIER].s_phaser.speed = 6500;
+  shipvals[CARRIER].s_phaser.cost = 570;
+  shipvals[CARRIER].s_phaser.fuse = 6;
+  shipvals[CARRIER].s_phaser.wtemp = 45;
+  shipvals[CARRIER].s_missile.damage = 20;
+  shipvals[CARRIER].s_missile.speed = 14;
+  shipvals[CARRIER].s_missile.cost = 380;	/* no longer includes
+						 * torpcost */
+  shipvals[CARRIER].s_missile.fuse = 300;
+  shipvals[CARRIER].s_missile.wtemp = 35;	/* no longer includes torp
+						 * wtemp */
+  shipvals[CARRIER].s_missile.count = 8;
+  shipvals[CARRIER].s_missile.aux = 3;
+  shipvals[CARRIER].s_missilestored = 0;
+  shipvals[CARRIER].s_plasma.damage = 80;
+  shipvals[CARRIER].s_plasma.speed = 15;
+  shipvals[CARRIER].s_plasma.cost = 3000;
+  shipvals[CARRIER].s_plasma.fuse = 35;
+  shipvals[CARRIER].s_plasma.wtemp = 270;
+  shipvals[CARRIER].s_plasma.aux = 2;
+  shipvals[CARRIER].s_maxwpntemp = 1000;
+  shipvals[CARRIER].s_wpncoolrate = 2;
+  shipvals[CARRIER].s_maxegntemp = 1500;
+  shipvals[CARRIER].s_egncoolrate = 5;
+  shipvals[CARRIER].s_maxfuel = 15000;
+  shipvals[CARRIER].s_recharge = 25;
+  shipvals[CARRIER].s_mingivefuel = 0;
+  shipvals[CARRIER].s_takeonfuel = 150;
+  if (configvals->fuel_explosions)
+  {
+    shipvals[CARRIER].s_expldam = 80;	/* was: 55; (BG) */
+    shipvals[CARRIER].s_fueldam = 70;	/* was: 80; (BG) */
+  }
+  else
+  {
+    shipvals[CARRIER].s_expldam = 100;
+    shipvals[CARRIER].s_fueldam = 0;
+  }
+  shipvals[CARRIER].s_armyperkill = 25;
+  shipvals[CARRIER].s_maxarmies = 3;
+  shipvals[CARRIER].s_bomb = 20;
+  shipvals[CARRIER].s_repair = 105;
+  shipvals[CARRIER].s_maxdamage = 150;
+  shipvals[CARRIER].s_maxshield = 120;
+  shipvals[CARRIER].s_shieldcost = 5;
+  shipvals[CARRIER].s_detcost = 50;
+  shipvals[CARRIER].s_detdist = 1900;
+  if (configvals->bronco_shipvals)
+    shipvals[CARRIER].s_cloakcost = 135;
+  else
+    shipvals[CARRIER].s_cloakcost = 100;
+#ifdef LONG_SCANRANGE
+  shipvals[CARRIER].s_scanrange = 1000;
+#else
+  shipvals[CARRIER].s_scanrange = -1;
+#endif
+  shipvals[CARRIER].s_numports = 0;
+  shipvals[CARRIER].s_letter = 'v';
+  shipvals[CARRIER].s_desig1 = 'C';
+  shipvals[CARRIER].s_desig2 = 'V';
+  shipvals[CARRIER].s_bitmap = 11;
+  shipvals[CARRIER].s_width = 20;
+  shipvals[CARRIER].s_height = 20;
+  shipvals[CARRIER].s_timer = 12;
+  shipvals[CARRIER].s_maxnum = 1;
+  shipvals[CARRIER].s_rank = 3;
+  shipvals[CARRIER].s_numdefn = 5;
+  shipvals[CARRIER].s_numplan = 3;
+  if (configvals->warpdrive)
+    shipvals[CARRIER].s_nflags = SFNCANWARP | SFNHASPHASERS | SFNHASMISSILE | SFNHASFIGHTERS;
+  else
+    shipvals[CARRIER].s_nflags = SFNHASPHASERS | SFNHASMISSILE | SFNHASFIGHTERS;
+
+  /* comprehensive definition of UTILITY */
+  shipvals[UTILITY].s_alttype = 4;
+  strcpy(shipvals[UTILITY].s_name, "Utility");
+  shipvals[UTILITY].s_turns = 80000;
+  shipvals[UTILITY].s_imp.acc = 100;
+  shipvals[UTILITY].s_imp.dec = 200;
+  shipvals[UTILITY].s_imp.cost = 4;
+  shipvals[UTILITY].s_imp.maxspeed = 7;
+  shipvals[UTILITY].s_imp.etemp = 1000;
+  shipvals[UTILITY].s_after.acc = 500;
+  shipvals[UTILITY].s_after.dec = 250;
+  shipvals[UTILITY].s_after.cost = 40;
+  shipvals[UTILITY].s_after.maxspeed = 8;
+  shipvals[UTILITY].s_after.etemp = 40000;
+  shipvals[UTILITY].s_warp.acc = 10000;
+  shipvals[UTILITY].s_warp.dec = 5000;
+  shipvals[UTILITY].s_warp.cost = 20;
+  if (configvals->bronco_shipvals)
+  {
+    shipvals[UTILITY].s_warp.maxspeed = 10;
+    shipvals[UTILITY].s_warpprepspeed = 0;
+  }
+  else
+  {
+    shipvals[UTILITY].s_warp.maxspeed = 20;	/* was: 15; (BG) */
+    shipvals[UTILITY].s_warpprepspeed = 1;
+  }
+  shipvals[UTILITY].s_warp.etemp = 5500;
+  shipvals[UTILITY].s_warpinitcost = 1200;
+  shipvals[UTILITY].s_warpinittime = 50;
+  shipvals[UTILITY].s_mass = 2400;
+  shipvals[UTILITY].s_tractstr = 3500;
+  shipvals[UTILITY].s_tractrng = 1.1;
+  shipvals[UTILITY].s_tractcost = 4;
+  shipvals[UTILITY].s_tractetemp = 1000;
+  shipvals[UTILITY].s_torp.damage = 20;
+  shipvals[UTILITY].s_torp.speed = 15;
+  shipvals[UTILITY].s_torp.cost = 250;
+  shipvals[UTILITY].s_torp.fuse = 25;
+  shipvals[UTILITY].s_torp.wtemp = 18;
+  shipvals[UTILITY].s_torp.wtemp_halfarc = 16;
+  shipvals[UTILITY].s_torp.wtemp_factor = 4;
+  shipvals[UTILITY].s_torp.aux = 0;
+  shipvals[UTILITY].s_phaser.damage = 80;
+  shipvals[UTILITY].s_phaser.speed = 5600;
+  shipvals[UTILITY].s_phaser.cost = 640;
+  shipvals[UTILITY].s_phaser.fuse = 8;
+  shipvals[UTILITY].s_phaser.wtemp = 85;
+  shipvals[UTILITY].s_missile.damage = 30;
+  shipvals[UTILITY].s_missile.speed = 8;
+  shipvals[UTILITY].s_missile.cost = 800;
+  shipvals[UTILITY].s_missile.fuse = 80;
+  shipvals[UTILITY].s_missile.wtemp = 60;
+  shipvals[UTILITY].s_missile.count = 3;
+  shipvals[UTILITY].s_missile.aux = 2;
+  shipvals[UTILITY].s_missilestored = 18;
+  shipvals[UTILITY].s_plasma.damage = -1;
+  shipvals[UTILITY].s_plasma.speed = 0;
+  shipvals[UTILITY].s_plasma.cost = 0;
+  shipvals[UTILITY].s_plasma.fuse = 0;
+  shipvals[UTILITY].s_plasma.wtemp = 0;
+  shipvals[UTILITY].s_plasma.aux = 0;
+  shipvals[UTILITY].s_maxwpntemp = 1000;
+  shipvals[UTILITY].s_wpncoolrate = 2;
+  shipvals[UTILITY].s_maxegntemp = 1800;
+  shipvals[UTILITY].s_egncoolrate = 5;
+  shipvals[UTILITY].s_maxfuel = 16000;
+  shipvals[UTILITY].s_recharge = 38;
+  shipvals[UTILITY].s_mingivefuel = 4000;
+  shipvals[UTILITY].s_takeonfuel = 150;
+  if (configvals->fuel_explosions)
+  {
+    shipvals[UTILITY].s_expldam = 60;
+    shipvals[UTILITY].s_fueldam = 80;
+  }
+  else
+  {
+    shipvals[UTILITY].s_expldam = 100;
+    shipvals[UTILITY].s_fueldam = 0;
+  }
+  shipvals[UTILITY].s_armyperkill = 12;
+  shipvals[UTILITY].s_maxarmies = 12;
+  shipvals[UTILITY].s_bomb = 0;
+  shipvals[UTILITY].s_repair = 120;
+  shipvals[UTILITY].s_maxdamage = 220;
+  shipvals[UTILITY].s_maxshield = 120;
+  shipvals[UTILITY].s_shieldcost = 4;
+  shipvals[UTILITY].s_detcost = 50;
+  shipvals[UTILITY].s_detdist = 1900;
+  if (configvals->bronco_shipvals)
+    shipvals[UTILITY].s_cloakcost = 180;
+  else
+    shipvals[UTILITY].s_cloakcost = 130;	/* was 90 (MDM) */
+  shipvals[UTILITY].s_scanrange = 2000;
+  shipvals[UTILITY].s_numports = 2;
+  shipvals[UTILITY].s_letter = 'u';
+  shipvals[UTILITY].s_desig1 = 'U';
+  shipvals[UTILITY].s_desig2 = 'T';
+  shipvals[UTILITY].s_bitmap = 12;
+  shipvals[UTILITY].s_width = 20;
+  shipvals[UTILITY].s_height = 20;
+  shipvals[UTILITY].s_timer = 7;
+  shipvals[UTILITY].s_maxnum = 1;
+  shipvals[UTILITY].s_rank = 2;
+  shipvals[UTILITY].s_numdefn = 2;
+  shipvals[UTILITY].s_numplan = 1;
+  if (configvals->warpdrive)
+    shipvals[UTILITY].s_nflags = SFNCANWARP | SFNHASPHASERS | SFNCANREPAIR | SFNCANFUEL;
+  else
+    shipvals[UTILITY].s_nflags = SFNHASPHASERS | SFNCANREPAIR | SFNCANFUEL;
+
+  /* Comprehensive definition of Gunboat */
+  shipvals[PATROL].s_alttype = 0;
+  strcpy(shipvals[PATROL].s_name, "Patrol Ship");
+  shipvals[PATROL].s_turns = 1500000;
+  shipvals[PATROL].s_imp.acc = 350;
+  shipvals[PATROL].s_imp.dec = 400;
+  shipvals[PATROL].s_imp.cost = 1;
+  shipvals[PATROL].s_imp.maxspeed = 13;
+  shipvals[PATROL].s_imp.etemp = 1000;
+  shipvals[PATROL].s_after.acc = 800;
+  shipvals[PATROL].s_after.dec = 350;
+  shipvals[PATROL].s_after.cost = 18;
+  shipvals[PATROL].s_after.maxspeed = 15;
+  shipvals[PATROL].s_after.etemp = 30000;
+  shipvals[PATROL].s_warp.acc = 10000;
+  shipvals[PATROL].s_warp.dec = 500;
+  if (configvals->bronco_shipvals)
+  {
+    shipvals[PATROL].s_warp.maxspeed = 21;
+    shipvals[PATROL].s_warpprepspeed = 2;
+  }
+  else
+  {
+    shipvals[PATROL].s_warp.maxspeed = 35;	/* was: 30; (BG) */
+    shipvals[PATROL].s_warpprepspeed = 3;
+  }
+  shipvals[PATROL].s_warp.cost = 22;
+  shipvals[PATROL].s_warp.etemp = 35000;
+  shipvals[PATROL].s_warpinitcost = 800;
+  shipvals[PATROL].s_warpinittime = 20;
+  shipvals[PATROL].s_mass = 1000;
+  shipvals[PATROL].s_tractstr = 1500;
+  shipvals[PATROL].s_tractrng = 0.75;
+  shipvals[PATROL].s_tractcost = 2;
+  shipvals[PATROL].s_tractetemp = 1000;
+  shipvals[PATROL].s_torp.damage = 30;
+  shipvals[PATROL].s_torp.speed = 15;
+  shipvals[PATROL].s_torp.cost = 180;
+  shipvals[PATROL].s_torp.fuse = 18;
+  shipvals[PATROL].s_torp.wtemp = 10;
+  shipvals[PATROL].s_torp.wtemp_halfarc = 32;
+  shipvals[PATROL].s_torp.wtemp_factor = 9;
+  shipvals[PATROL].s_torp.aux = 0;
+  shipvals[PATROL].s_phaser.damage = 50;
+  shipvals[PATROL].s_phaser.speed = 5000;
+  shipvals[PATROL].s_phaser.cost = 300;
+  shipvals[PATROL].s_phaser.fuse = 8;
+  shipvals[PATROL].s_phaser.wtemp = 45;
+  shipvals[PATROL].s_missile.damage = 50;
+  shipvals[PATROL].s_missile.speed = 17;
+  shipvals[PATROL].s_missile.cost = 450;
+  shipvals[PATROL].s_missile.fuse = 50;
+  shipvals[PATROL].s_missile.wtemp = 50;
+  shipvals[PATROL].s_missile.count = 6;
+  shipvals[PATROL].s_missile.aux = 1;
+  shipvals[PATROL].s_missilestored = 6;
+  shipvals[PATROL].s_plasma.damage = -1;
+  shipvals[PATROL].s_plasma.speed = 0;
+  shipvals[PATROL].s_plasma.cost = 0;
+  shipvals[PATROL].s_plasma.fuse = 0;
+  shipvals[PATROL].s_plasma.wtemp = 0;
+  shipvals[PATROL].s_plasma.aux = 0;
+  shipvals[PATROL].s_maxwpntemp = 1000;
+  shipvals[PATROL].s_wpncoolrate = 3;
+  shipvals[PATROL].s_maxegntemp = 1500;
+  shipvals[PATROL].s_egncoolrate = 8;
+  shipvals[PATROL].s_maxfuel = 4000;
+  shipvals[PATROL].s_recharge = 10;
+  shipvals[PATROL].s_mingivefuel = 0;
+  shipvals[PATROL].s_takeonfuel = 120;
+  if (configvals->fuel_explosions)
+  {
+    shipvals[PATROL].s_expldam = 35;
+    shipvals[PATROL].s_fueldam = 30;
+  }
+  else
+  {
+    shipvals[PATROL].s_expldam = 60;
+    shipvals[PATROL].s_fueldam = 0;
+  }
+  shipvals[PATROL].s_armyperkill = 1;
+  shipvals[PATROL].s_maxarmies = 1;
+  shipvals[PATROL].s_bomb = 0;
+  shipvals[PATROL].s_repair = 50;
+  shipvals[PATROL].s_maxdamage = 40;
+  shipvals[PATROL].s_maxshield = 50;
+  shipvals[PATROL].s_shieldcost = 2;
+  shipvals[PATROL].s_detcost = 100;
+  shipvals[PATROL].s_detdist = 1750;
+  if (configvals->bronco_shipvals)
+    shipvals[PATROL].s_cloakcost = 40;
+  else
+    shipvals[PATROL].s_cloakcost = 30;
+  shipvals[PATROL].s_scanrange = -1;
+  shipvals[PATROL].s_numports = 0;
+  shipvals[PATROL].s_letter = 'p';
+  shipvals[PATROL].s_desig1 = 'P';
+  shipvals[PATROL].s_desig2 = 'T';
+  shipvals[PATROL].s_bitmap = 13;
+  shipvals[PATROL].s_width = 20;
+  shipvals[PATROL].s_height = 20;
+  shipvals[PATROL].s_timer = 0;
+  shipvals[PATROL].s_maxnum = 32;
+  shipvals[PATROL].s_rank = 0;
+  shipvals[PATROL].s_numdefn = 0;
+  shipvals[PATROL].s_numplan = 0;	/* 1; was 1 but everybody bitched
+					 * (BG) */
+  if (configvals->warpdrive)
+    shipvals[PATROL].s_nflags = SFNCANORBIT | SFNARMYNEEDKILL | SFNHASPHASERS | SFNHASMISSILE | SFNMASSPRODUCED | SFNCANWARP;
+  else
+    shipvals[PATROL].s_nflags = SFNCANORBIT | SFNARMYNEEDKILL | SFNHASPHASERS | SFNHASMISSILE | SFNMASSPRODUCED;
+}
+
+/*----------END OF FILE-----*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/shmem.c	Sat Dec 06 04:37:04 1997 +0000
@@ -0,0 +1,286 @@
+/*--------------------------------------------------------------------------
+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 <stdio.h>
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <errno.h>
+#include <signal.h>
+
+#include "shmem.h"
+#include "path.h"
+#include "data.h"
+
+/*---------------------------SHARED MEMORY STRUCTURE----------------------*/
+
+#include "shmemP.h"
+
+/*-------------------------------------------------------------------------*/
+
+struct player *players;
+struct torp *torps;
+struct missile *missiles;
+struct thingy *thingies;
+struct plasmatorp *plasmatorps;
+struct status *status;
+struct status2 *status2;
+struct planet *planets;
+struct t_unit *terrain_grid;
+struct phaser *phasers;
+int *stars;
+struct mctl *mctl;
+struct message *messages;
+struct team *teams;
+
+struct ship *shipvals;
+struct configuration *configvals;
+int *shipsallowed;		/* points inside configvals */
+int *weaponsallowed;		/* ditto */
+int *sun_effect;
+int *ast_effect;
+int *neb_effect;
+int *wh_effect;
+int *num_nebula;
+int *nebula_density;
+int *nebula_subclouds;
+int *num_asteroid;
+float *asteroid_thickness;
+int *asteroid_density;
+int *asteroid_radius;
+float *asteroid_thick_variance;
+int *asteroid_dens_variance;
+int *asteroid_rad_variance;
+int *improved_tracking;
+int *tstart;
+int *newgalaxy;
+int *nontteamlock;
+char *cluephrase_storage;
+
+static int PKEY = 128;
+
+/*------------------------------STARTDAEMON---------------------------------*/
+/*
+ * This function starts the daemon.  It get the path to where the daemon
+ * resides, then tries to start it up.
+ */
+
+
+#ifndef SYSV			/* HP/UX hates this */
+extern int fprintf();
+#endif
+extern pid_t fork();
+extern int execl();
+extern void perror();
+extern int shmget();
+#ifndef IRIX
+extern int shmctl();
+#endif
+extern unsigned int sleep();
+extern uid_t geteuid();
+
+void
+startdaemon(leagueflag, restart)
+  int leagueflag, restart;
+{
+  int i;			/* temp var */
+  char *hell;			/* to hold path to daemon */
+
+  if (restart)
+  {
+    fprintf(stderr, "RE-");
+    kill(status->nukegame, SIGKILL);	/* daemon is killed without giving it
+					 * a chance to blast the shmem */
+    sleep(2);
+  }
+  fprintf(stderr, "Starting daemon...\n");	/* record that deaemon is */
+  i = fork();			/* starting */
+  if (i == 0)
+  {				/* if successful */
+    char *nargv[10];
+    int argc = 0;
+    hell = build_path(DAEMON);
+    nargv[argc++] = "daemon";
+    if (leagueflag)
+      nargv[argc++] = "-l";
+    if (restart)
+      nargv[argc++] = "-a";
+    nargv[argc] = 0;
+    execv(hell, nargv);
+
+    perror(hell);		/* did it work */
+    fprintf(stderr, "Couldn't start daemon!!!\n");
+    _exit(1);			/* let's get out of here */
+  }
+}
+
+
+
+static int shmid = -1;		/* ID number of shared mem */
+
+
+/*--------------------------------OPENMEM----------------------------------*/
+/*
+ * if code is 0, openmem will exit(1) upon finding the memory gone. if code
+ * is 1, openmem will fork a netrek daemon and retry. if code is 2, openmem
+ * will blast any already existing shared memory.
+ */
+
+void
+openmem(code, leagueflag)
+  int code;
+  int leagueflag;		/* only used if code==1 */
+{
+  extern int errno;		/* to get error number */
+  key_t shmemKey = PKEY;	/* shared memory's key */
+  struct memory *sharedMemory;	/* to point to shared memory */
+  char *k;
+
+  k = getenv("TREKSHMKEY");	/* grab shared mem id environment variable */
+  if (k)
+  {				/* if it's set... */
+    int i;
+    if (sscanf(k, "%d", &i) > 0 && i > 0)	/* ...grab its value... */
+      shmemKey = i;		/* ...and use it */
+  }
+
+  errno = 0;			/* clear error number */
+  shmid = shmget(shmemKey, 0, 0);	/* get id of shared mem */
+  if (code == 2)
+  {
+    if (shmid >= 0)
+    {
+      /* If we're in daemon mode and we opened the memory */
+      /* "There can be only one". */
+      fprintf(stderr, "Killing existing segment\n");
+      shmctl(shmid, IPC_RMID, (struct shmid_ds *) 0);
+      /* create a new one */
+    }
+    shmid = shmget(shmemKey, sizeof(struct memory), IPC_CREAT | 0666);
+  }
+  if (shmid < 0)
+  {				/* if shared mem does not exist */
+    switch (code)
+    {
+     case 0:
+      if (errno != ENOENT)
+      {				/* catastrophic, sell all your stock */
+	perror("shmget");	/* and leave the country type of */
+	exit(1);		/* error--suicide */
+      }
+      fprintf(stderr, "Daemon not running (err:%d)\n", errno);
+      exit(1);
+     case 1:
+      if (errno != ENOENT)
+      {				/* catastrophic, sell all your stock */
+	perror("shmget");	/* and leave the country type of */
+	exit(1);		/* error--suicide */
+      }
+      startdaemon(leagueflag, 0);	/* try to start the daemon */
+      sleep(2);			/* wait for a sec for deamon to start */
+      shmid = shmget(shmemKey, 0, 0);	/* try again to get shared mem */
+      if (shmid < 0)
+      {				/* failure again then get out of here */
+	fprintf(stderr, "Daemon not running (err:%d)\n", errno);
+	exit(1);
+      }
+      break;
+     case 2:
+      perror("daemon: can't open shared memory");
+      exit(1);
+    }
+  }
+  if (code == 2)
+  {
+    struct shmid_ds smbuf;
+
+    shmctl(shmid, IPC_STAT, &smbuf);	/* Hose Ed's robots */
+    smbuf.shm_perm.uid = geteuid();
+    smbuf.shm_perm.mode = 0666;
+    shmctl(shmid, IPC_SET, &smbuf);
+  }
+  sharedMemory = (struct memory *) shmat(shmid, (char *) 0, 0);
+  if (sharedMemory == (struct memory *) - 1)
+  {
+    perror("shared memory");
+    exit(1);
+  }
+  if (code == 2)
+  {
+    /* set the magic number */
+    sharedMemory->shmem_size = sizeof(struct memory);
+  }
+  else
+  {
+    if (sharedMemory->shmem_size != sizeof(struct memory))
+    {
+      fprintf(stderr, "shared memory segment magic number mismatch!\
+ (%d != %ld)\n  aborting to prevent corruption of game data\n",
+	      sharedMemory->shmem_size, (long) sizeof(struct memory));
+      exit(1);
+    }
+  }
+  players = sharedMemory->players;	/* set pointer to fields */
+  torps = sharedMemory->torps;	/* in shared memory structure */
+  missiles = sharedMemory->missiles;	/* for easy access */
+  thingies = sharedMemory->thingies;
+  plasmatorps = sharedMemory->plasmatorps;
+  status = &sharedMemory->status;
+  status2 = &sharedMemory->status2;
+  planets = sharedMemory->planets;
+  terrain_grid = sharedMemory->terrain_grid;
+  phasers = sharedMemory->phasers;
+  stars = sharedMemory->stars;
+  mctl = &sharedMemory->mctl;
+  messages = sharedMemory->messages;
+  teams = sharedMemory->teams;
+  shipvals = sharedMemory->shipvals;
+  configvals = &sharedMemory->configvals;
+  galaxyValid = &sharedMemory->galaxyValid;
+  /* configvals->gwidth = 200000; *//* pick up from galaxy generator later */
+  /* configvals->numplanets = 60; *//* this too */
+
+  shipsallowed = configvals->shipsallowed;
+  weaponsallowed = configvals->weaponsallowed;
+  sun_effect = configvals->sun_effect;
+  ast_effect = configvals->ast_effect;
+  neb_effect = configvals->neb_effect;
+  wh_effect = configvals->wh_effect;
+  num_nebula = &(configvals->num_nebula);
+  nebula_density = &(configvals->nebula_density);
+  nebula_subclouds = &(configvals->nebula_subclouds);
+  num_asteroid = &(configvals->num_asteroid);
+  asteroid_thickness = &(configvals->asteroid_thickness);
+  asteroid_density = &(configvals->asteroid_density);
+  asteroid_radius = &(configvals->asteroid_radius);
+  asteroid_thick_variance = &(configvals->asteroid_thick_variance);
+  asteroid_dens_variance = &(configvals->asteroid_dens_variance);
+  asteroid_rad_variance = &(configvals->asteroid_rad_variance);
+  improved_tracking = configvals->improved_tracking;
+
+  cluephrase_storage = sharedMemory->cluephrase_storage;
+
+  stars[1] = -1;
+}
+
+void
+blast_shmem()
+{
+  shmctl(shmid, IPC_RMID, (struct shmid_ds *) 0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/shmem.h	Sat Dec 06 04:37:04 1997 +0000
@@ -0,0 +1,244 @@
+/*--------------------------------------------------------------------------
+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
+--------------------------------------------------------------------------*/
+
+#ifndef shmem_h_
+#define shmem_h_
+
+#include "struct.h"
+
+enum spec_weapons_e
+{
+  WP_PLASMA,
+  WP_TRACTOR,
+  WP_MISSILE,
+  WP_FIGHTER,
+  WP_MAX
+};
+
+enum ships_systems
+{
+  /* Terrain could, I suppose, affect any of these */
+  /* I may have forgotten a couple, feel free to add.. */
+  SS_PLASMA,
+  SS_TRACTOR,
+  SS_MISSILE,
+  SS_FIGHTER,
+  SS_PHOTON,
+  SS_PHASER,
+  SS_SHIELD,
+  SS_REPAIR,
+  SS_CLOAK,
+  SS_SCANNER,
+  SS_SENSOR,
+  SS_WARP,
+  SS_IMPULSE,
+  SS_DOCK,
+  SS_NAVIGATION,
+  SS_COMMUNICATION,
+  SHIPS_SYSTEMS
+};
+
+struct configuration
+{
+  int tournplayers;		/* how many players necessary for T-mode */
+  int ntesters;			/* number of slots reserved for robots */
+
+  char binconfirm;		/* binary confirmation */
+  float maxload;		/* maximum load */
+  char udpAllowed;		/* is UDP allowed */
+  int min_upd_delay;		/* minimum update delay */
+  int min_observer_upd_delay;	/* minimum observer update delay */
+
+  /* planet things */
+  int galaxygenerator;		/* which method to generate the galaxy with */
+  int numplanets;		/* number of planets */
+  float planupdspd;		/* planet movement speed */
+  char resource_bombing;	/* have growable and bombable resources? */
+  char revolts;			/* are revolts allowed? */
+  unsigned char popscheme;	/* individual planet popping scheme */
+  unsigned char popchoice;	/* how to choose a planet for popping */
+  int popspeed;			/* 100 is normal speed */
+  char evacuation;		/* allow beaming up below 5 armies? */
+  char new_army_growth;		/* base army growth on current pop? */
+  int planetsinplay;		/* Max # of planets in play */
+  int planetlimittype;		/* how planet taking is limited */
+  char beamlastarmies;		/* if you can, or cannot beam up the last
+				 * armies. */
+  char justify_galaxy;		/* Do we want to ensure that the galaxy is
+				 * "fair"? */
+  int num_wormpairs;		/* The number of wormhole pairs -- DON'T SET
+				 * ABOVE (NUMPLANETS/2) */
+  int num_nebula;		/* the number of nebulas in the galaxy. */
+  int nebula_density;		/* not yet used. Will be used for
+				 * funky-shaped nebs */
+  int nebula_subclouds;		/* the number of nebulous subclouds */
+  int num_asteroid;		/* number of asteroid belts in the galaxy */
+  float asteroid_thickness;	/* the thickness of an asteroid belt. */
+  int asteroid_density;		/* the density (% chance) of an asteroid
+				 * field */
+  int asteroid_radius;		/* distance of a belt from its star */
+  float asteroid_thick_variance;/* float value -- useful range 0.0 - 10.0 or
+				 * so */
+  int asteroid_dens_variance;	/* int value -- useful range 0 - 200 */
+  int asteroid_rad_variance;	/* int value -- useful range 0 - 255 */
+
+  float plkills;		/* how many kills to allow plasmas */
+  float mskills;		/* how many kills to allow missiles */
+  float erosion;		/* hull erosion factor */
+  float penetration;		/* shield penetration factor */
+  int newturn;			/* TC's new style turns */
+  int hiddenenemy;		/* enemies hidden in T-mode */
+  int gwidth;			/* galactic width */
+  char bronco_shipvals;		/* use bronco ship values? */
+  char afterburners;		/* can people use afterburners? */
+  char warpdrive;		/* is warping allowed? */
+  char fuel_explosions;		/* are explosions based on gas? */
+  char newcloak;		/* use new cloaking? */
+  char bronco_ranks;		/* use bronco ranking? NYI, kinda */
+
+  char warpdecel;		/* non-instant deceleration from warp */
+  char affect_shiptimers_outside_T;	/* should ship destruction outside of
+					 * T-mode affect the team ship
+					 * timers? */
+  /* NYTested */
+  char durablescouting;		/* if 0, then you have to keep scouting
+				 * planets to get up-to-date info.  If 1,
+				 * then you only need to scout it once. */
+
+  /* NYI */
+  char facilitygrowth;		/* if 0, then you can't bomb or grow
+				 * facilities.  if 1, then you can. */
+  char fireduringwarpprep;	/* can you fire during warp prep? */
+  char fireduringwarp;		/* can you fire while warping? */
+  char firewhiledocked;		/* can you fire while docked? */
+
+#define WPS_NOTRACT	0	/* tractors do not affect warp prep */
+#define WPS_TABORT	1	/* tractors cause an abort at the end */
+#define WPS_TPREVENT	2	/* tractors prevent entering warp  */
+#define WPS_TABORTNOW	3	/* tractors immediately abort warp prep  */
+#define WPS_TSUSPEND	4	/* tractors suspend countdown */
+  char warpprepstyle;
+
+  char baserankstyle;		/* if nobody on the team has enough rank */
+  /* to get a special ship; and this is set */
+  /* to 1, then the player with the highest */
+  /* rank on the team may get the spec. ship */
+
+  char cloakduringwarpprep;
+  char cloakwhilewarping;
+  char tractabortwarp;		/* this many tractors will abort warp */
+
+  float orbitdirprob;		/* probability that the player will orbit
+				 * clockwise */
+  char neworbits;		/* New, incremental planet distances from the
+				 * parent star -- important for games with
+				 * terrain. */
+
+  int sun_effect[SHIPS_SYSTEMS];/* suns affect these systems */
+  int ast_effect[SHIPS_SYSTEMS];/* asteroids affect these systems */
+  int neb_effect[SHIPS_SYSTEMS];/* a nebula affects these */
+  int wh_effect[SHIPS_SYSTEMS];	/* wormhole effects */
+  int improved_tracking[SHIPS_SYSTEMS];	/* which weapons use IT */
+  int shipsallowed[NUM_TYPES];	/* which ships are allowed */
+  int weaponsallowed[WP_MAX];	/* which special weapons are allowed */
+#ifdef LEAGUE_SUPPORT
+  /* league configuration stuff */
+  int timeouts;			/* timeouts per team in league play */
+  int regulation_minutes;	/* minutes in regulation play */
+  int overtime_minutes;		/* minutes in overtime play */
+  int playersperteam;		/* maximum number of players per team */
+#endif
+  /* ping stuff */
+  int ping_period;		/* ping period in seconds */
+  int ping_iloss_interval;	/* in terms of ping_period */
+  int ping_allow_ghostbust;	/* allow ghostbust detection from
+				 * ping_ghostbust (cheating possible) */
+  int ping_ghostbust_interval;	/* in terms of ping_period, when to ghostbust
+				 * (if allowed) */
+
+  char cluecheck;		/* should we check clue? */
+  int cluedelay;		/* maximum time between clue checks */
+  int cluetime;			/* time player has to respond to a clue check */
+  int cluesource;		/* source of clue phrase */
+#define	CC_COMPILED_IN_PHRASE_LIST	0
+#define	CC_MOTD				1
+#define	CC_PHRASE_LIST_FILE		2
+
+  int variable_warp;		/* allow variable warp or not [BDyess] */
+  int warpprep_suspendable;	/* allow warp prep to be suspended [BDyess] */
+  int warpzone;			/* radius of warp zone [BDyess] */
+
+  /* tmode stuff */
+  int nopregamebeamup;		/* whether to disallow beamup before a game */
+  int gamestartnuke;		/* whether everyone is nuked at game start */
+  int nottimeout;		/* # minutes after loss of tmode before */
+  /* galaxy resets (0 disables) */
+
+  /* put planet growth timer constants here */
+  struct plgrow_
+  {
+    int fuel, agri, repair, shipyard;
+  }   plgrow;
+  int helpfulplanets;		/* planets help fuel/etmep */
+};
+
+extern struct player *players;
+extern struct torp *torps;
+extern struct missile *missiles;
+extern struct thingy *thingies;
+extern struct plasmatorp *plasmatorps;
+extern struct status *status;
+extern struct status2 *status2;
+extern struct planet *planets;
+extern struct t_unit *terrain_grid;
+extern struct phaser *phasers;
+extern int *stars;
+extern struct mctl *mctl;
+extern struct message *messages;
+extern struct team *teams;
+
+#define NUMPLANETS configvals->numplanets
+#define GWIDTH configvals->gwidth
+#define WORMPAIRS configvals->num_wormpairs
+
+extern struct ship *shipvals;
+extern struct configuration *configvals;
+extern int *shipsallowed;	/* points inside configvals */
+extern int *weaponsallowed;	/* ditto */
+extern int *sun_effect;		/* how do suns affect ship systems? */
+extern int *ast_effect;		/* asteroids */
+extern int *neb_effect;		/* nebulae */
+extern int *wh_effect;		/* wormholes */
+extern int *num_nebula;		/* number of nebulae */
+extern int *nebula_density;	/* funkyness of nebulae -- NYI */
+extern int *nebula_subclouds;	/* number of subclouds per nebula */
+extern int *num_asteroid;	/* number of asteroid fields */
+extern float *asteroid_thickness;	/* thickness of an asteroid belt */
+extern int *asteroid_density;	/* density of asteroid belts */
+extern int *asteroid_radius;	/* distance from owning star */
+extern float *asteroid_thick_variance;
+extern int *asteroid_dens_variance;
+extern int *asteroid_rad_variance;
+extern int *improved_tracking;	/* smarter tracking algorithm */
+extern char *galaxyValid;	/* does galaxy go invalid?  0 if so */
+#define CLUEPHRASE_SIZE	1024
+extern char *cluephrase_storage;
+void openmem( /* 0=or die, 1=fork daemon, 2=are daemon */ );
+void blast_shmem();
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/shmemP.h	Sat Dec 06 04:37:04 1997 +0000
@@ -0,0 +1,51 @@
+/*--------------------------------------------------------------------------
+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
+--------------------------------------------------------------------------*/
+
+
+#ifndef _shmemP_h
+#define _shmemP_h
+
+struct memory
+{
+  int shmem_size;		/* sizeof(struct memory) sort of a magic
+				 * number so that we don't connect an
+				 * obsolete program to the shmem. */
+  struct player players[MAXPLAYER];
+  struct torp torps[MAXPLAYER * MAXTORP];
+  struct missile missiles[MAXPLAYER * NPTHINGIES];
+  struct thingy thingies[NGTHINGIES];
+  struct plasmatorp plasmatorps[MAXPLAYER * MAXPLASMA];
+  struct status status;
+  struct status2 status2;
+  struct planet planets[MAXPLANETS];
+  struct t_unit terrain_grid[(MAX_GWIDTH / TGRID_GRANULARITY) *
+			         (MAX_GWIDTH / TGRID_GRANULARITY)];
+  struct phaser phasers[MAXPLAYER];
+  int stars[MAXPLANETS + 1];	/* indices of the stars in the game, indexed
+				 * on system number */
+  struct mctl mctl;
+  struct message messages[MAXMESSAGE];
+  struct team teams[MAXTEAM + 1];
+
+  struct ship shipvals[NUM_TYPES];
+  struct configuration configvals;
+  char cluephrase_storage[CLUEPHRASE_SIZE];
+  char galaxyValid[MAXPLAYER];
+};
+
+#endif				/* _shmemP_h */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/sintab.c	Sat Dec 06 04:37:04 1997 +0000
@@ -0,0 +1,546 @@
+/*--------------------------------------------------------------------------
+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
+--------------------------------------------------------------------------*/
+
+/*---------------------------------DATA------------------------------------*/
+/* The sine table so we do not have to calculate this on the fly.  */
+
+double Sin[] = {
+  -1.0000,
+  -0.9997,
+  -0.9988,
+  -0.9973,
+  -0.9952,
+  -0.9925,
+  -0.9892,
+  -0.9853,
+  -0.9808,
+  -0.9757,
+  -0.9701,
+  -0.9638,
+  -0.9570,
+  -0.9496,
+  -0.9416,
+  -0.9330,
+  -0.9239,
+  -0.9143,
+  -0.9040,
+  -0.8933,
+  -0.8820,
+  -0.8701,
+  -0.8578,
+  -0.8449,
+  -0.8315,
+  -0.8176,
+  -0.8033,
+  -0.7884,
+  -0.7731,
+  -0.7573,
+  -0.7410,
+  -0.7243,
+  -0.7072,
+  -0.6896,
+  -0.6716,
+  -0.6533,
+  -0.6345,
+  -0.6153,
+  -0.5958,
+  -0.5759,
+  -0.5557,
+  -0.5351,
+  -0.5142,
+  -0.4930,
+  -0.4715,
+  -0.4497,
+  -0.4277,
+  -0.4054,
+  -0.3828,
+  -0.3600,
+  -0.3370,
+  -0.3138,
+  -0.2904,
+  -0.2668,
+  -0.2431,
+  -0.2192,
+  -0.1952,
+  -0.1711,
+  -0.1469,
+  -0.1225,
+  -0.0982,
+  -0.0737,
+  -0.0492,
+  -0.0247,
+  -0.0001,
+  0.0244,
+  0.0489,
+  0.0734,
+  0.0979,
+  0.1223,
+  0.1466,
+  0.1708,
+  0.1949,
+  0.2190,
+  0.2428,
+  0.2666,
+  0.2901,
+  0.3135,
+  0.3367,
+  0.3598,
+  0.3825,
+  0.4051,
+  0.4274,
+  0.4495,
+  0.4713,
+  0.4928,
+  0.5140,
+  0.5349,
+  0.5554,
+  0.5757,
+  0.5956,
+  0.6151,
+  0.6343,
+  0.6531,
+  0.6714,
+  0.6894,
+  0.7070,
+  0.7241,
+  0.7408,
+  0.7571,
+  0.7729,
+  0.7882,
+  0.8031,
+  0.8175,
+  0.8314,
+  0.8448,
+  0.8576,
+  0.8700,
+  0.8818,
+  0.8931,
+  0.9039,
+  0.9141,
+  0.9238,
+  0.9329,
+  0.9415,
+  0.9495,
+  0.9569,
+  0.9637,
+  0.9700,
+  0.9757,
+  0.9808,
+  0.9852,
+  0.9891,
+  0.9925,
+  0.9952,
+  0.9973,
+  0.9988,
+  0.9997,
+  1.0000,
+  0.9997,
+  0.9988,
+  0.9973,
+  0.9952,
+  0.9925,
+  0.9892,
+  0.9853,
+  0.9808,
+  0.9757,
+  0.9700,
+  0.9638,
+  0.9569,
+  0.9495,
+  0.9415,
+  0.9330,
+  0.9239,
+  0.9142,
+  0.9040,
+  0.8932,
+  0.8819,
+  0.8701,
+  0.8577,
+  0.8449,
+  0.8315,
+  0.8176,
+  0.8032,
+  0.7884,
+  0.7730,
+  0.7572,
+  0.7410,
+  0.7243,
+  0.7071,
+  0.6896,
+  0.6716,
+  0.6532,
+  0.6344,
+  0.6153,
+  0.5957,
+  0.5758,
+  0.5556,
+  0.5350,
+  0.5141,
+  0.4929,
+  0.4714,
+  0.4496,
+  0.4276,
+  0.4053,
+  0.3827,
+  0.3599,
+  0.3369,
+  0.3137,
+  0.2903,
+  0.2667,
+  0.2430,
+  0.2191,
+  0.1951,
+  0.1710,
+  0.1468,
+  0.1225,
+  0.0981,
+  0.0736,
+  0.0491,
+  0.0246,
+  0.0000,
+  -0.0245,
+  -0.0490,
+  -0.0735,
+  -0.0980,
+  -0.1224,
+  -0.1467,
+  -0.1709,
+  -0.1950,
+  -0.2190,
+  -0.2429,
+  -0.2667,
+  -0.2902,
+  -0.3136,
+  -0.3368,
+  -0.3598,
+  -0.3826,
+  -0.4052,
+  -0.4275,
+  -0.4496,
+  -0.4713,
+  -0.4928,
+  -0.5140,
+  -0.5349,
+  -0.5555,
+  -0.5758,
+  -0.5956,
+  -0.6152,
+  -0.6343,
+  -0.6531,
+  -0.6715,
+  -0.6895,
+  -0.7071,
+  -0.7242,
+  -0.7409,
+  -0.7572,
+  -0.7730,
+  -0.7883,
+  -0.8032,
+  -0.8175,
+  -0.8314,
+  -0.8448,
+  -0.8577,
+  -0.8700,
+  -0.8819,
+  -0.8932,
+  -0.9040,
+  -0.9142,
+  -0.9238,
+  -0.9330,
+  -0.9415,
+  -0.9495,
+  -0.9569,
+  -0.9638,
+  -0.9700,
+  -0.9757,
+  -0.9808,
+  -0.9853,
+  -0.9892,
+  -0.9925,
+  -0.9952,
+  -0.9973,
+  -0.9988,
+  -0.9997
+};
+double Cos[] = {
+  0.0000,
+  0.0245,
+  0.0491,
+  0.0736,
+  0.0980,
+  0.1224,
+  0.1467,
+  0.1710,
+  0.1951,
+  0.2191,
+  0.2430,
+  0.2667,
+  0.2903,
+  0.3137,
+  0.3369,
+  0.3599,
+  0.3827,
+  0.4052,
+  0.4275,
+  0.4496,
+  0.4714,
+  0.4929,
+  0.5141,
+  0.5350,
+  0.5556,
+  0.5758,
+  0.5957,
+  0.6152,
+  0.6344,
+  0.6532,
+  0.6715,
+  0.6895,
+  0.7071,
+  0.7242,
+  0.7409,
+  0.7572,
+  0.7730,
+  0.7883,
+  0.8032,
+  0.8176,
+  0.8315,
+  0.8448,
+  0.8577,
+  0.8701,
+  0.8819,
+  0.8932,
+  0.9040,
+  0.9142,
+  0.9239,
+  0.9330,
+  0.9415,
+  0.9495,
+  0.9569,
+  0.9638,
+  0.9700,
+  0.9757,
+  0.9808,
+  0.9853,
+  0.9892,
+  0.9925,
+  0.9952,
+  0.9973,
+  0.9988,
+  0.9997,
+  1.0000,
+  0.9997,
+  0.9988,
+  0.9973,
+  0.9952,
+  0.9925,
+  0.9892,
+  0.9853,
+  0.9808,
+  0.9757,
+  0.9700,
+  0.9638,
+  0.9570,
+  0.9495,
+  0.9416,
+  0.9330,
+  0.9239,
+  0.9142,
+  0.9040,
+  0.8933,
+  0.8819,
+  0.8701,
+  0.8578,
+  0.8449,
+  0.8315,
+  0.8176,
+  0.8032,
+  0.7884,
+  0.7731,
+  0.7573,
+  0.7410,
+  0.7243,
+  0.7072,
+  0.6896,
+  0.6716,
+  0.6532,
+  0.6344,
+  0.6153,
+  0.5958,
+  0.5759,
+  0.5556,
+  0.5351,
+  0.5142,
+  0.4930,
+  0.4715,
+  0.4497,
+  0.4276,
+  0.4053,
+  0.3828,
+  0.3600,
+  0.3370,
+  0.3138,
+  0.2904,
+  0.2668,
+  0.2431,
+  0.2192,
+  0.1952,
+  0.1710,
+  0.1468,
+  0.1225,
+  0.0981,
+  0.0737,
+  0.0492,
+  0.0246,
+  0.0001,
+  -0.0244,
+  -0.0490,
+  -0.0735,
+  -0.0979,
+  -0.1223,
+  -0.1466,
+  -0.1709,
+  -0.1950,
+  -0.2190,
+  -0.2429,
+  -0.2666,
+  -0.2902,
+  -0.3136,
+  -0.3368,
+  -0.3598,
+  -0.3826,
+  -0.4051,
+  -0.4275,
+  -0.4495,
+  -0.4713,
+  -0.4928,
+  -0.5140,
+  -0.5349,
+  -0.5555,
+  -0.5757,
+  -0.5956,
+  -0.6151,
+  -0.6343,
+  -0.6531,
+  -0.6715,
+  -0.6895,
+  -0.7070,
+  -0.7242,
+  -0.7409,
+  -0.7571,
+  -0.7729,
+  -0.7883,
+  -0.8031,
+  -0.8175,
+  -0.8314,
+  -0.8448,
+  -0.8577,
+  -0.8700,
+  -0.8819,
+  -0.8932,
+  -0.9039,
+  -0.9142,
+  -0.9238,
+  -0.9329,
+  -0.9415,
+  -0.9495,
+  -0.9569,
+  -0.9637,
+  -0.9700,
+  -0.9757,
+  -0.9808,
+  -0.9853,
+  -0.9892,
+  -0.9925,
+  -0.9952,
+  -0.9973,
+  -0.9988,
+  -0.9997,
+  -1.0000,
+  -0.9997,
+  -0.9988,
+  -0.9973,
+  -0.9952,
+  -0.9925,
+  -0.9892,
+  -0.9853,
+  -0.9808,
+  -0.9757,
+  -0.9701,
+  -0.9638,
+  -0.9570,
+  -0.9496,
+  -0.9416,
+  -0.9330,
+  -0.9239,
+  -0.9143,
+  -0.9041,
+  -0.8933,
+  -0.8820,
+  -0.8702,
+  -0.8578,
+  -0.8449,
+  -0.8316,
+  -0.8177,
+  -0.8033,
+  -0.7884,
+  -0.7731,
+  -0.7573,
+  -0.7411,
+  -0.7244,
+  -0.7072,
+  -0.6897,
+  -0.6717,
+  -0.6533,
+  -0.6345,
+  -0.6154,
+  -0.5958,
+  -0.5759,
+  -0.5557,
+  -0.5351,
+  -0.5142,
+  -0.4930,
+  -0.4715,
+  -0.4498,
+  -0.4277,
+  -0.4054,
+  -0.3828,
+  -0.3601,
+  -0.3371,
+  -0.3138,
+  -0.2905,
+  -0.2669,
+  -0.2432,
+  -0.2193,
+  -0.1953,
+  -0.1711,
+  -0.1469,
+  -0.1226,
+  -0.0982,
+  -0.0737,
+  -0.0493,
+  -0.0247
+};
+
+/*-------------------------------------------------------------------------*/
+
+
+
+
+
+
+/*-------END OF FILE--------*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/smessage.c	Sat Dec 06 04:37:04 1997 +0000
@@ -0,0 +1,95 @@
+/*--------------------------------------------------------------------------
+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 <stdio.h>
+#include <math.h>
+#include <signal.h>
+#include <ctype.h>
+#include "defs.h"
+#include "struct.h"
+#include "data.h"
+#include "shmem.h"
+
+/* int parse_control_mess(); */
+
+
+/*-----------------------------VISIBLE FUNCTIONS--------------------------*/
+
+/*---------------------------------PMESSAGE-------------------------------*/
+/*
+ * This function sends a message.  It marks a message as being sent from God.
+ */
+
+
+void pmessage2();
+
+void
+pmessage(str, recip, group, address)
+  char *str;			/* the message */
+  int recip;			/* who will receive it */
+  int group;			/* the group (type of recipient) */
+  char *address;		/* attached to front of message */
+{
+  pmessage2(str, recip, group, address, 255);
+}
+
+
+
+
+/*--------------------------------PMESSAGE2--------------------------------*/
+/*
+ * This function sends a message.  It places the message in the array of
+ * messages.
+ */
+
+void
+pmessage2(str, recip, group, address, from)
+  char *str;			/* the message */
+  int recip;			/* who will receive it */
+  int group;			/* the group (type of recipient) */
+  char *address;		/* attached to front of message */
+  unsigned char from;		/* who the message is from */
+{
+  struct message *cur;		/* to point to where to put message */
+  int mesgnum;			/* to hold index number in message array */
+
+  if ((mesgnum = ++(mctl->mc_current)) >= MAXMESSAGE)
+  {
+    mctl->mc_current = 0;	/* get index of where to put the message */
+    mesgnum = 0;		/* roll it index number over if need be */
+  }
+  cur = &messages[mesgnum];	/* get address of message structure in array */
+  cur->m_no = mesgnum;		/* set the message number */
+  cur->m_flags = group;		/* set group or type of recipient */
+  cur->m_recpt = recip;		/* set the recipient */
+  cur->m_from = from;		/* set who it was from */
+  (void) sprintf(cur->m_data, "%-9s ", address);
+  strncat(cur->m_data, str, sizeof(cur->m_data) - strlen(cur->m_data));
+  cur->m_flags |= MVALID;	/* set messages status as valid */
+}
+
+/*-------------------------------------------------------------------------*/
+
+
+
+/*----------------------------INVISIBLE FUNCTIONS-------------------------*/
+
+
+/*-------END OF FILE--------*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/snake.c	Sat Dec 06 04:37:04 1997 +0000
@@ -0,0 +1,395 @@
+/*--------------------------------------------------------------------------
+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
+--------------------------------------------------------------------------*/
+
+
+char binary[] = "@(#)snake";
+
+#include "config.h"
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+#include <sys/time.h>
+#include <signal.h>
+#include <setjmp.h>
+#include "defs.h"
+#include "struct.h"
+#include "data.h"
+#include "shmem.h"
+
+#ifndef linux
+double atof();
+#endif
+extern void (*r_signal()) ();
+
+struct player *perfs[2];
+int printsnakeUsage();
+int num_perfs = 2;
+int debug = 0;
+int target = -1;
+int berserk = 0;
+int patrol = 0;
+int noSmush = 0;
+int plan_guard = 0;		/* KAO */
+int planet1, planet2;		/* KAO */
+int team1 = 0, team2 = 0;
+int length = MAXTORP;		/* how many pairs of torps in the snake */
+
+struct itimerval udt;		/* derived from frequency RF */
+int lastm;
+int tno = 0;
+
+int
+choose_team(team)
+{
+  if (tno < 0)
+    tno = team;
+  if (!team1)
+    team1 = 1 << team;
+  else if (!team2)
+    team2 = 1 << team;
+}
+
+main(argc, argv)
+  int argc;
+  char **argv;
+{
+  register int i;
+  int snakemove(), exitSnake();
+  int pno;
+  char str[80], tlet;
+  int pc = 0;
+  int usage = 0;
+  double frequency = 10;	/* default of 10 updates per second */
+
+  argv0 = argv[0];
+  tno = -1;
+
+  srand48(getpid() + time((time_t *) 0));
+  memset(perfs, 0, sizeof(perfs));
+
+  for (; argc > 1 && argv[1][0] == '-'; argc--, argv++)
+  {
+    switch (argv[1][1])
+    {
+     case 'p':
+      patrol++;
+      break;
+     case 'n':
+      noSmush = 1;
+      break;
+     case 's':
+      noSmush = -1;
+      break;
+     case 'g':			/* KAO */
+      plan_guard++;		/* KAO */
+      argv++;			/* KAO */
+      argc--;
+      planet1 = atoi(argv[1]);	/* KAO */
+      argc--;
+      argv++;			/* KAO */
+      planet2 = atoi(argv[1]);	/* KAO */
+      break;			/* KAO */
+     case 'b':
+      berserk++;
+      break;
+     case 'd':
+      debug++;
+      break;
+     case 't':
+      {				/* target */
+	char c;
+	c = argv[1][2];
+	target = -1;
+	if (c == '\0')
+	{
+	  fprintf(stderr, "Must specify target.  e.g. -t3.\n");
+	  exit(1);
+	}
+	if ((c >= '0') && (c <= '9'))
+	  target = c - '0';
+	else if ((c >= 'a') && (c <= 'z'))
+	  target = c - 'a' + 10;
+	else
+	{
+	  fprintf(stderr, "Must specify target.  e.g. -t3.\n");
+	  exit(1);
+	}
+      }
+      break;
+
+     case 'T':			/* team */
+      tlet = argv[1][2];
+      if (isupper(tlet))
+	tlet = tolower(tlet);
+      switch (tlet)
+      {
+       case 'f':
+	choose_team(0);
+	break;
+       case 'r':
+	choose_team(1);
+	break;
+       case 'k':
+	choose_team(2);
+	break;
+       case 'o':
+	choose_team(3);
+	break;
+       case 'i':
+	tno = 4;
+	break;
+       default:
+	fprintf(stderr, "Unknown team type.  Usage -Tx where x is [frkoi]\n");
+	exit(1);
+      }				/* end switch argv */
+      break;
+
+     case 'l':
+      length = atoi(argv[1] + 2);
+      if (length < 1)
+      {
+	length = 1;
+      }
+      else if (length > MAXTORP)
+      {
+	length = MAXTORP;
+      }
+      break;
+     case 'f':
+      frequency = atof(argv[1] + 2);
+      if (frequency < 0)
+      {
+	frequency = 1;
+      }
+      break;
+     default:
+      fprintf(stderr, "Unknown option '%c'\n", argv[1][1]);
+      usage++;
+      exit(1);
+    }				/* end switch argv[1][1] */
+  }				/* end for */
+
+  if (usage)
+  {
+    printsnakeUsage();
+    exit(1);
+  }
+
+  /* if -T wasn't specified default to FED */
+  if (tno < 0)
+    tno = lrand48() % 4;
+
+  /* XX -- teams imply patrol */
+  if (team1 && team2)
+    patrol++;
+
+#ifdef nodef
+  /* debug */
+  if (patrol)
+  {
+    printf("snake (%s): patrolling %s,%s\n", teamshort[1 << tno],
+	   teamshort[team1],
+	   teamshort[team2]);
+  }
+  fflush(stdout);
+#endif
+
+  /* readsysdefaults(); */
+
+  (void) r_signal(SIGHUP, exitSnake);
+  (void) r_signal(SIGINT, exitSnake);
+  (void) r_signal(SIGBUS, exitSnake);
+  (void) r_signal(SIGSEGV, exitSnake);
+  openmem(0, 0);
+
+  lastm = mctl->mc_current;
+
+  for (i = 0; i < 2; i++)
+  {				/* two players per snake */
+    pno = findrslot();
+    if (pno < 0)
+    {
+      fprintf(stderr, "snake: no room in game\n");
+      if (i > 0)
+	perfs[0]->p_status = PFREE;
+      exit(1);
+    }
+    me = &players[pno];
+
+    perfs[i] = me;
+
+    me->p_no = pno;
+    myship = &me->p_ship;
+    mystats = &me->p_stats;
+
+    strcpy(pseudo, "The Snake");
+    strcpy(login, "SnkeChrmr");
+
+    strcpy(me->p_name, pseudo);
+    me->p_name[sizeof(me->p_name) - 1] = '\0';
+
+    (void) strncpy(me->p_login, login, sizeof(me->p_login));
+    me->p_login[sizeof(me->p_login) - 1] = '\0';
+    (void) strncpy(me->p_monitor, "Server", sizeof(me->p_monitor));
+    me->p_monitor[sizeof(me->p_monitor) - 1] = '\0';
+    /* enter(tno, 0, pno, class, -1); */
+
+    me->p_team = (tno < 4) ? (1 << tno) : 0;
+    config();
+
+    me->p_pos = -1;
+    me->p_flags |= PFROBOT;	/* Mark as a robot */
+    me->p_flags |= PFSNAKE;	/* Mark as snake */
+    if (berserk)
+      me->p_hostile = FED | ROM | ORI | KLI;
+  }
+
+  r_signal(SIGALRM, snakemove);
+
+  {
+    double period = 1 / frequency;
+    udt.it_interval.tv_sec = period;	/* get the whole part */
+    period -= udt.it_interval.tv_sec;	/* get the fractional part */
+    udt.it_interval.tv_usec = 1e6 * period;
+    udt.it_value.tv_sec = 1;
+    udt.it_value.tv_usec = 0;
+  }
+
+  if (setitimer(ITIMER_REAL, &udt, 0) < 0)
+  {
+    perror("setitimer");
+    for (i = 0; i < num_perfs; i++)
+    {
+      if (perfs[i])
+	perfs[i]->p_status = PFREE;
+    }
+    exit(1);
+  }
+#ifndef SVR4
+  /* allows robots to be forked by the daemon -- Evil ultrix bullshit */
+  sigsetmask(0);
+#endif				/* SVR4 */
+
+  /* NOTE: snakes do not become alive. */
+
+  while (1)
+  {
+    pause();
+  }
+}
+
+findtestslot()
+{
+  register int i;
+
+  for (i = MAXPLAYER - configvals->ntesters; i < MAXPLAYER; i++)
+  {
+    if (players[i].p_status == PFREE)
+    {				/* We have a free slot */
+      players[i].p_status = POUTFIT;	/* possible race code */
+      break;
+    }
+  }
+  if (i == MAXPLAYER)
+  {
+    return -1;			/* no room in tester slots */
+  }
+  memset(&players[i].p_stats, 0, sizeof(struct stats));
+  players[i].p_stats.st_tticks = 1;
+  return (i);
+}
+
+findrslot()
+{
+  register int i;
+
+  /* look for tester slot first */
+  i = findtestslot();
+  if (i > -1)
+    return i;
+
+  for (i = 0; i < MAXPLAYER; i++)
+  {
+    if (players[i].p_status == PFREE)
+    {				/* We have a free slot */
+      players[i].p_status = POUTFIT;	/* possible race code */
+      break;
+    }
+  }
+  if ((i == MAXPLAYER) || (i == -1))
+  {
+    if (debug)
+    {
+      fprintf(stderr, "No more room in game\n");
+    }
+    return -1;
+  }
+  memset(&players[i].p_stats, 0, sizeof(struct stats));
+  players[i].p_stats.st_tticks = 1;
+  return (i);
+}
+
+void
+warning(mess)
+  char *mess;
+{
+  if (debug)
+    fprintf(stderr, "warning: %s\n", mess);
+}
+
+config()
+{
+  /* mostly not used */
+#if 0
+  /* what the heck is this procedure for ? */
+  myship->s_phasercost = 0;
+  myship->s_torpcost = 0;
+  myship->s_cloakcost = 0;
+  myship->s_torpfuse = 1000000;
+  myship->s_torpdamage = 10;
+  myship->s_plasmadamage = 50;
+  myship->s_plasmacost = 0;
+  myship->s_plasmaturns = 0;
+  myship->s_plasmaspeed = 10;
+  myship->s_plasmafuse = 1000000;
+  myship->s_wpncoolrate = 100;
+  myship->s_egncoolrate = 100;
+#endif
+}
+
+/*---------------------[ prints the usage of snake ]---------------------*/
+
+printsnakeUsage()
+{
+  printf("Usage: snake [options]\n");
+  printf("Options:\n\
+  -u -- this usage message\n\
+  -p -- patrol\n\
+  -s -- noSmush (?)\n\
+  -b -- berserk\n\
+  -d -- debug\n\
+  -t -- target <player number>\n\
+  -T -- team [frkoi]\n\
+  -l -- length (in torps)\n\
+  -f -- frequency\n\
+  -g -- guardian:  -g <planet1> <planet2> (must be 2 planets listed,\n\
+                      by number).\n");
+}
+
+/*--------------------------[ printsnakeUsage ]--------------------------*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/snakemove.c	Sat Dec 06 04:37:04 1997 +0000
@@ -0,0 +1,1080 @@
+/*--------------------------------------------------------------------------
+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 <stdio.h>
+#include <signal.h>
+
+#ifdef apollo
+#include <limits.h>
+#define MAXINT INT_MAX
+#else
+#include <values.h>
+#endif
+
+#include <math.h>
+#include <time.h>
+#include "defs.h"
+#include "struct.h"
+#include "data.h"
+#include "planets.h"
+#include "shmem.h"
+
+#define SYSWIDTH      (GWIDTH/5)/* width of a system */
+
+/* distance on either side of center */
+#define EYEWIDTH		100	/* 100 */
+/* which torp the eyes are positioned alongside */
+#define EYETORP			0	/* 0 */
+/* angle from EYETORP */
+#define EYEANGLE		64	/* 64 */
+#define TORPSEP			WARP1*12
+#define PLANRAD  900
+#define PLANRATE 16
+
+/* threshold to avoid galactic boundaries */
+#define MD		4500
+/* overlap threshold on team boundaries */
+#define TMD		2250
+
+/* how often to check for bombers in cyles (1/10th second) */
+#define BOMBCHECK	20
+
+/* how often to check for players in the game in cyles (1/10th second) */
+#define PLAYERCHECK	100
+
+#define WARHOSTILE(p)		((((p)->p_swar | (p)->p_hostile)& \
+				perfs[0]->p_team) || ((perfs[0]->p_swar | \
+				perfs[0]->p_hostile) & (p)->p_team))
+
+#define SNAKETORPDAMAGE		30
+#define SNAKEPLASMADAMAGE	100
+
+static struct torp *thead, *eyet, *eyetp;
+static int lx, ly;
+static struct plasmatorp *fl, *fr;
+static int explode, explodetorps, tfuse;
+
+extern struct player *perfs[2];
+extern int num_perfs;
+extern int debug;
+extern int lastm;
+extern int tno;
+extern int target;
+extern int berserk;
+extern int patrol;
+extern int noSmush;
+extern int plan_guard;		/* KAO */
+extern int planet1, planet2;	/* KAO */
+extern int team1, team2;
+extern int length;
+
+static int plan_count = 0;
+static int s_clock;
+static _move();
+static int defenders[ALLTEAM];
+
+struct player *whokilledme();
+struct planet *homeworld = 0;
+struct planet *homestar = 0;
+
+unsigned char getacourse();
+extern void (*r_signal()) ();
+
+
+struct planet *
+star_of(pl)
+  struct planet *pl;
+{
+  int i;
+  if (pl->pl_system < 1)
+    return 0;
+
+  for (i = 0; i < NUMPLANETS; i++)
+  {
+    if (!(planets[i].pl_flags & PLSTAR))
+      continue;
+    if (planets[i].pl_system == pl->pl_system)
+      return &planets[i];
+  }
+
+  return 0;
+}
+
+
+
+snakemove()
+{
+  s_clock++;
+
+  _move();
+}
+
+static
+_move()
+{
+  if (!perfs[0] || !perfs[1])
+    exitSnake();
+
+  /* keep ghostbuster away */
+  perfs[0]->p_ghostbuster = 0;
+  perfs[1]->p_ghostbuster = 0;
+
+  if (s_clock == 5)
+    startsnake();
+  else if (s_clock > 5)
+  {
+    check_explode();
+    if (!explode)
+    {
+      movesnake();
+    }
+    else if ((perfs[0]->p_ntorp == 0 && perfs[1]->p_ntorp == 0 &&
+	    perfs[0]->p_nplasmatorp == 0 && perfs[1]->p_nplasmatorp == 0) ||
+      /* xx -- sometimes above doesn't work? */
+	     s_clock - explode > 56)
+      exitSnake();
+  }
+  return 1;
+}
+
+startsnake()
+{
+  register i, l;
+  register struct player *j;
+  register struct torp *k;
+  struct player *p1 = perfs[0], *p2 = perfs[1];
+  int first = 1;
+  int px, py;
+
+  for (i = 0; i < NUMPLANETS; i++)
+  {
+    if (planets[i].pl_flags & PLHOME && planets[i].pl_owner == 1 << tno)
+    {
+      homeworld = &planets[i];
+      break;
+    }
+    if (!homeworld && planets[i].pl_owner == 1 << tno)
+      homeworld = &planets[i];
+  }
+
+  if (!homeworld)
+  {
+    /* ouch */
+    homeworld = &planets[lrand48() % NUMPLANETS];
+    fprintf(stderr, "snake: My race (%d) has no planets.  Picking one at random: %s\n", tno, homeworld->pl_name);
+  }
+  homestar = star_of(homeworld);
+  if (!homestar)
+    homestar = homeworld;
+
+  px = (lrand48() % 10000) - 5000;
+  py = (lrand48() % 10000) - 5000;
+
+  p1->p_ntorp = p2->p_ntorp = 0;
+  p1->p_nplasmatorp = p2->p_nplasmatorp = 0;
+
+  /* body */
+
+  for (j = perfs[0]; j; j = (j == perfs[1] ? NULL : perfs[1]))
+  {
+
+    for (l = 0, i = j->p_no * MAXTORP, k = &torps[i];
+	 i < j->p_no * MAXTORP + length; i++, k++, l++)
+    {
+
+      if (l == EYETORP && j == perfs[0])
+      {
+	/* eye location */
+	eyet = k;
+      }
+      if (l == ((EYETORP == 0) ? 1 : (EYETORP - 1)) && j == perfs[0])
+      {
+	/* perpendicular torp offset */
+	eyetp = k;
+      }
+      /* torps are free here */
+      snake_torp(k, i, j);
+      /* note: have to be same team for this to work */
+      k->t_x = homeworld->pl_x + px;
+      k->t_y = homeworld->pl_y + py - (l + (j == perfs[1] ? length : 0)) * TORPSEP;
+      /*
+       * if(debug) fprintf(stderr, "k->t_x %d, k->t_y %d\n", k->t_x, k->t_y);
+       */
+      if (first)
+      {
+	thead = k;
+	first = 0;
+      }
+    }
+  }
+
+  /* eyes */
+  fl = &plasmatorps[perfs[0]->p_no * MAXPLASMA];
+  fl->pt_no = perfs[0]->p_no * MAXPLASMA;
+  fl->pt_status = PTMOVE;
+  fl->pt_owner = perfs[0]->p_no;
+  fl->pt_team = perfs[0]->p_team;
+  fl->pt_x = eyet->t_x - EYEWIDTH;
+  fl->pt_y = eyet->t_y;
+  if (plan_guard == 0)
+    fl->pt_damage = SNAKEPLASMADAMAGE;
+  else
+    fl->pt_damage = SNAKEPLASMADAMAGE * 10;
+  fl->pt_speed = 0;
+  fl->pt_war = 0;
+  fl->pt_fuse = MAXINT;
+  fl->pt_turns = 0;
+
+  perfs[0]->p_nplasmatorp++;
+
+  fr = &plasmatorps[perfs[1]->p_no * MAXPLASMA];
+  fr->pt_no = perfs[1]->p_no * MAXPLASMA;
+  fr->pt_status = PTMOVE;
+  fr->pt_owner = perfs[1]->p_no;
+  fr->pt_team = perfs[1]->p_team;	/* doesn't work */
+  fr->pt_x = eyet->t_x + EYEWIDTH;
+  fr->pt_y = eyet->t_y;
+  fr->pt_damage = SNAKEPLASMADAMAGE;
+  fr->pt_speed = 0;
+  fr->pt_war = 0;
+  fr->pt_fuse = MAXINT;
+  fr->pt_turns = 0;
+
+  perfs[1]->p_nplasmatorp++;
+
+  if (debug)
+    fprintf(stderr, "started\n");
+}
+
+restore_eye()
+{
+  if (fl->pt_status != PTMOVE)
+  {
+    /* eyes */
+    fl = &plasmatorps[perfs[0]->p_no * MAXPLASMA];
+    fl->pt_no = perfs[0]->p_no * MAXPLASMA;
+    fl->pt_status = PTMOVE;
+    fl->pt_owner = perfs[0]->p_no;
+    fl->pt_team = perfs[0]->p_team;
+    fl->pt_x = eyet->t_x - EYEWIDTH;
+    fl->pt_y = eyet->t_y;
+    if (plan_guard == 0)
+      fl->pt_damage = SNAKEPLASMADAMAGE;
+    else
+      fl->pt_damage = SNAKEPLASMADAMAGE * 10;
+    fl->pt_speed = 0;
+    fl->pt_war = 0;
+    fl->pt_fuse = MAXINT;
+    fl->pt_turns = 0;
+    perfs[0]->p_nplasmatorp++;
+  }
+  if (fr->pt_status != PTMOVE)
+  {
+    fr = &plasmatorps[perfs[1]->p_no * MAXPLASMA];
+    fr->pt_no = perfs[1]->p_no * MAXPLASMA;
+    fr->pt_status = PTMOVE;
+    fr->pt_owner = perfs[1]->p_no;
+    fr->pt_team = perfs[1]->p_team;	/* doesn't work */
+    fr->pt_x = eyet->t_x + EYEWIDTH;
+    fr->pt_y = eyet->t_y;
+    fr->pt_damage = SNAKEPLASMADAMAGE;
+    fr->pt_speed = 0;
+    fr->pt_war = 0;
+    fr->pt_fuse = MAXINT;
+    fr->pt_turns = 0;
+    perfs[1]->p_nplasmatorp++;
+  }
+}
+
+movesnake()
+{
+  register i, px, py;
+  register struct player *j;
+  register struct torp *k /* , *prev = thead */ ;
+  unsigned char tc;
+  struct player *tr;
+  static
+  int dir = 8;
+  int ok;
+
+  if ((s_clock % PLAYERCHECK) == 0)
+  {
+    /* every x seconds make sure there's people in the game */
+    ok = 0;
+    defenders[FED] = defenders[ROM] = defenders[KLI] = defenders[ORI] = 0;
+    for (i = 0, j = players; i < MAXPLAYER; i++, j++)
+    {
+      if ((j->p_status != PFREE) && !(j->p_flags & PFROBOT))
+      {
+	ok = 1;
+	defenders[j->p_team]++;
+      }
+    }
+    if (!ok)
+      exitSnake();
+  }
+  if (patrol && (target == -1) && (s_clock % BOMBCHECK) == 0)
+  {
+    target = bombcheck(team1, team2);
+  }
+  if ((s_clock % (4 + (lrand48() % 4))) == 0)
+    dir = -dir;
+
+  thead->t_dir += dir + rrnd(8);
+
+  if (target > -1)
+  {
+    tr = &players[target];
+    if (tr->p_status == PALIVE)
+    {
+      int nd, td;
+      tc = getacourse(tr->p_x, tr->p_y, thead->t_x, thead->t_y);
+      nd = angdist(thead->t_dir, tc);
+      if (nd > 8)
+      {
+	td = tc + nd;
+	if (td == thead->t_dir)
+	  thead->t_dir -= 8;
+	else
+	  thead->t_dir += 8;
+      }
+    }
+  }
+  if (target == -1)
+  {
+    if (!patrol)
+      check_tboundary(ALLTEAM, &thead->t_dir, 8, thead->t_x, thead->t_y);
+    else
+      check_tboundary(team1 | team2, &thead->t_dir, 8, thead->t_x, thead->t_y);
+  }
+  lx = thead->t_x;
+  ly = thead->t_y;
+
+  if (!plan_guard)
+  {
+    /* NOTE: we aren't letting the daemon move the torp head */
+    thead->t_x += (double) TORPSEP *Cos[thead->t_dir];
+    thead->t_y += (double) TORPSEP *Sin[thead->t_dir];
+  }
+  for (j = perfs[0]; j; j = (j == perfs[1] ? NULL : perfs[1]))
+  {
+    if (plan_guard)
+    {
+      int temp;
+      thead = &torps[j->p_no * MAXTORP];
+      if (j == perfs[0])
+	temp = planet1;
+      else
+	temp = planet2;
+      lx = thead->t_x;
+      ly = thead->t_y;
+      thead->t_x = planets[temp].pl_x + Cos[255 - plan_count] * PLANRAD;
+      thead->t_y = planets[temp].pl_y + Sin[255 - plan_count] * PLANRAD;
+    }
+    for (i = j->p_no * MAXTORP, k = &torps[i];
+	 i < j->p_no * MAXTORP + length; i++, k++)
+    {
+
+      if (k->t_status == TFREE)
+	/* got exploded.  x & y location will remain however */
+	snake_torp(k, i, j);
+
+      if (k == thead)
+	continue;
+
+      px = k->t_x;
+      py = k->t_y;
+
+      k->t_x = lx;
+      k->t_y = ly;
+
+      lx = px;
+      ly = py;
+    }
+  }
+  if (plan_guard)
+  {
+    thead = &torps[perfs[0]->p_no * MAXTORP];
+    plan_count = (plan_count + PLANRATE) % 256;
+  }
+  lx = thead->t_x;
+  ly = thead->t_y;
+  doeyes();
+}
+
+check_explode()
+{
+  register int i, l;
+  register struct player *j;
+  register struct torp *k;
+  static struct player *killer;
+
+  if (fl->pt_status == PTDET || fr->pt_status == PTDET ||
+      fl->pt_status == PTEXPLODE || fr->pt_status == PTEXPLODE || explode)
+  {
+    if (plan_guard)
+    {
+      restore_eye();
+      return;
+    }				/* KAO */
+    if (debug)
+      fprintf(stderr, "snake exploding\n");
+    if (!explode)
+    {
+      /* do once */
+      explode = s_clock;
+      tfuse = 0;
+      if (fl->pt_status == PTDET || fl->pt_status == PTEXPLODE)
+      {
+	killer = whokilledme(fl);
+	if (killer)
+	  award(killer);
+      }
+      if (fr->pt_status == PTDET || fr->pt_status == PTEXPLODE)
+      {
+	killer = whokilledme(fr);
+	if (killer)
+	  award(killer);
+      }
+    }
+    if (fl->pt_status != PTFREE && fl->pt_status != PTEXPLODE)
+    {
+      fl->pt_war = FED | ROM | KLI | ORI;	/* make sure its at war when
+						 * it explodes */
+      fl->pt_status = PTEXPLODE;
+      fl->pt_fuse = 10;
+    }
+    if (fl->pt_status != PTFREE && fr->pt_status != PTEXPLODE)
+    {
+      fl->pt_war = FED | ROM | KLI | ORI;
+      fr->pt_status = PTEXPLODE;
+      fr->pt_fuse = 10;
+    }
+    /*
+     * now for some fancy stuff. If killer is our target and is hostile or at
+     * war with our team then snake torp head makes a beeline for him.  This
+     * lasts until killer dies or torps have been chasing killer for 40
+     * cycles
+     */
+
+    if (killer && WARHOSTILE(killer) && (noSmush < 1) && (killer->p_status == PALIVE) &&
+	tfuse < 40 && (killer->p_no == target || noSmush < 0))
+    {
+      crash_killer(killer);
+    }
+    else
+    {
+      /* explode all torps in sequence, 1 per cycle until all gone */
+      for (j = perfs[0]; j; j = (j == perfs[1] ? NULL : perfs[1]))
+      {
+	for (l = (j == perfs[0]) ? 0 : length, i = j->p_no * MAXTORP, k = &torps[i];
+	     i < j->p_no * MAXTORP + length; i++, k++, l++)
+	{
+	  if (l == explodetorps && k->t_status != TEXPLODE &&
+	      k->t_status != TFREE)
+	  {
+	    k->t_status = TEXPLODE;
+	    k->t_fuse = 10;
+	    explodetorps++;
+	    return;
+	  }
+	  else if (l == explodetorps)
+	    explodetorps++;
+	}
+      }
+    }
+  }
+}
+
+crash_killer(p)
+  struct player *p;
+{
+  register int i, px, py;
+  register struct player *j;
+  register struct torp *k;
+  unsigned char tc;
+  int active = 0;
+
+  tfuse++;
+
+  tc = getacourse(p->p_x, p->p_y, thead->t_x, thead->t_y);
+  thead->t_dir = tc;
+
+  lx = thead->t_x;
+  ly = thead->t_y;
+
+  thead->t_x += (double) (12 * WARP1) * Cos[thead->t_dir];
+  thead->t_y += (double) (12 * WARP1) * Sin[thead->t_dir];
+
+  for (j = perfs[0]; j; j = (j == perfs[1] ? NULL : perfs[1]))
+  {
+    for (i = j->p_no * MAXTORP, k = &torps[i];
+	 i < j->p_no * MAXTORP + length; i++, k++)
+    {
+
+      /* move the head up if it exploded */
+      if (k != thead && thead->t_status == TFREE)
+	thead = k;
+      else if (k == thead)
+	continue;
+
+      if (k->t_status != TFREE)
+	active++;
+
+      px = k->t_x;
+      py = k->t_y;
+
+      k->t_x = lx;
+      k->t_y = ly;
+
+      lx = px;
+      ly = py;
+    }
+  }
+  return active;
+}
+
+
+doeyes()
+{
+  unsigned char c = getacourse(eyetp->t_x, eyetp->t_y, eyet->t_x,
+			       eyet->t_y);
+  int ew = EYEWIDTH, war_ok;
+
+  /* c + 64 -- fl c - 64 -- fr */
+
+  if (plan_guard)
+  {
+    fl->pt_x = planets[planet1].pl_x + Cos[255 - plan_count] * PLANRAD;
+    fl->pt_y = planets[planet1].pl_y + Sin[255 - plan_count] * PLANRAD;
+    fr->pt_x = planets[planet2].pl_x + Cos[255 - plan_count] * PLANRAD;
+    fr->pt_y = planets[planet2].pl_y + Sin[255 - plan_count] * PLANRAD;
+    return;
+  }
+  if (fl->pt_war)
+    ew += 15;
+
+  fl->pt_x = eyet->t_x + (double) (ew) * Cos[(unsigned char) (c - EYEANGLE)];
+  fl->pt_y = eyet->t_y + (double) (ew) * Sin[(unsigned char) (c - EYEANGLE)];
+
+#ifdef nodef
+  if (fl->pt_x < 0)
+    fl->pt_x = 0;
+  else if (fl->pt_x > GWIDTH)
+    fl->pt_x = GWIDTH;
+
+  if (fl->pt_y < 0)
+    fl->pt_y = 0;
+  else if (fl->pt_y > GWIDTH)
+    fl->pt_y = GWIDTH;
+#endif
+
+  if (fr->pt_war)
+    ew += 15;
+
+  fr->pt_x = eyet->t_x + (double) (ew) * Cos[(unsigned char) (c + EYEANGLE)];
+  fr->pt_y = eyet->t_y + (double) (ew) * Sin[(unsigned char) (c + EYEANGLE)];
+
+#ifdef nodef
+  if (fr->pt_x < 0)
+    fr->pt_x = 0;
+  else if (fl->pt_x > GWIDTH)
+    fr->pt_x = GWIDTH;
+
+  if (fr->pt_y < 0)
+    fr->pt_y = 0;
+  else if (fl->pt_y > GWIDTH)
+    fr->pt_y = GWIDTH;
+#endif
+
+  /* toggle war */
+  if ((s_clock % 6) == 0)
+  {
+    /*
+     * your home planet and shipyards are always safe from your own snake
+     * unless you are a target.
+     */
+    war_ok = !sp_area(thead->t_x, thead->t_y);
+
+    if (!fr->pt_war && war_ok)
+      fr->pt_war = (FED | ROM | KLI | ORI) & ~(war_ok ? 0 : (1 << tno));
+    else
+      fr->pt_war = 0;
+
+    if (!fl->pt_war && war_ok)
+      fl->pt_war = (FED | ROM | KLI | ORI) & ~(war_ok ? 0 : (1 << tno));
+    else
+      fl->pt_war = 0;
+  }
+}
+
+exitSnake(sig)
+  int sig;
+{
+  register int i;
+  register struct player *j;
+  register struct torp *k;
+  register struct plasmatorp *f;
+
+  r_signal(SIGALRM, SIG_DFL);
+
+  if (debug)
+    fprintf(stderr, "snake exiting\n");
+
+  for (j = perfs[0]; j; j = (j == perfs[1] ? NULL : perfs[1]))
+  {
+    for (i = j->p_no * MAXTORP, k = &torps[i];
+	 i < j->p_no * MAXTORP + length; i++, k++)
+    {
+      /* torps are free here */
+      if (k->t_status != TFREE)
+	k->t_status = TOFF;
+    }
+    f = &plasmatorps[j->p_no * MAXPLASMA];
+    f->pt_status = PTFREE;
+    /* plasma */
+  }
+
+  memset(perfs[0], 0, sizeof(struct player));
+  memset(perfs[1], 0, sizeof(struct player));
+  perfs[0]->p_stats.st_tticks = 1;
+  perfs[1]->p_stats.st_tticks = 1;
+
+  /*
+   * note: if we had a segmentation violation or bus error we want a core
+   * file to debug
+   */
+  if (sig == SIGBUS || sig == SIGSEGV)
+    abort();
+  else
+    exit(0);
+}
+
+pmessage(str, recip, group, address)
+  char *str;
+  int recip;
+  int group;
+  char *address;
+{
+  pmessage2(str, recip, group, address, 255);
+}
+
+pmessage2(str, recip, group, address, from)
+  char *str;
+  int recip;
+  int group;
+  char *address;
+  unsigned char from;
+{
+  struct message *cur;
+  int mesgnum;
+
+  if ((mesgnum = ++(mctl->mc_current)) >= MAXMESSAGE)
+  {
+    mctl->mc_current = 0;
+    mesgnum = 0;
+  }
+  cur = &messages[mesgnum];
+  cur->m_no = mesgnum;
+  cur->m_flags = group;
+  cur->m_recpt = recip;
+  cur->m_from = from;
+  (void) sprintf(cur->m_data, "%-9s %s", address, str);
+  cur->m_flags |= MVALID;
+}
+
+/* get course from (mx,my) to (x,y) */
+unsigned char
+getacourse(x, y, mx, my)
+  int x, y, mx, my;
+{
+  if (x == mx && y == my)
+    return 0;
+
+  return (unsigned char) (int) (atan2((double) (x - mx),
+				      (double) (my - y)) / 3.14159 * 128.);
+}
+
+/*
+ * FED 1 ROM 2 KLI 4 ORI 8
+ */
+
+/*
+ * 256/0 192  +   64 128 */
+
+check_tboundary(teams, mycrs, range, x, y)
+  int teams;
+  int x, y;
+  unsigned char *mycrs;
+  int range;
+{
+  int lx = homestar->pl_x - SYSWIDTH / 2, rx = homestar->pl_x + SYSWIDTH / 2,
+      ty = homestar->pl_y - SYSWIDTH / 2, by = homestar->pl_y + SYSWIDTH / 2;
+  int r = 0, l = 0;
+  unsigned char crs = *mycrs;
+
+  if (x < lx && crs >= 128)
+  {
+    if (crs >= 192)
+      *mycrs += range;
+    else
+      *mycrs -= range;
+    l = 1;
+  }
+  else if (x > rx && crs < 128)
+  {
+    if (crs > 64)
+      *mycrs += range;
+    else
+      *mycrs -= range;
+    r = 1;
+  }
+  if (y < ty && (crs >= 192 || crs < 64))
+  {
+    if (crs >= 192 && !l)
+      *mycrs -= range;
+    else
+      *mycrs += range;
+  }
+  else if (y > by && (crs < 192 && crs >= 64))
+  {
+    if (crs < 128 && !r)
+      *mycrs -= range;
+    else
+      *mycrs += range;
+  }
+}
+
+/* return rnd between -range & range */
+rrnd(range)
+  int range;
+{
+  return lrand48() % (2 * range) - range;
+}
+
+#ifdef nodef
+/* NOTUSED */
+contrast(t)
+  int t;
+{
+  return ROM;			/* experiment */
+  switch (t)
+  {
+   case FED:
+    return ORI;
+   case ORI:
+    return FED;
+   case KLI:
+    return ROM;
+   case ROM:
+    return KLI;
+   default:
+    return FED;
+  }
+}
+
+#endif
+
+snake_torp(t, n, p)
+  struct torp *t;
+  int n;
+  struct player *p;
+{
+  t->t_no = n;
+  t->t_status = TMOVE;
+  t->t_owner = p->p_no;
+  t->t_team = p->p_team;
+  t->t_dir = 128;
+  if (plan_guard == 0)
+    t->t_damage = SNAKETORPDAMAGE;
+  else
+    t->t_damage = SNAKETORPDAMAGE * 10;
+  t->t_speed = 0;
+  if (berserk)
+    t->t_war = FED | ROM | ORI | KLI;
+  else if (target == -1)
+    t->t_war = 0;
+  else
+    t->t_war = perfs[0]->p_swar | perfs[0]->p_hostile;
+  t->t_fuse = MAXINT;
+  t->t_turns = 0;
+  p->p_ntorp++;
+}
+
+struct player *
+whokilledme(pt)
+  struct plasmatorp *pt;
+{
+  register i;
+  register struct phaser *j;
+
+  for (i = 0, j = &phasers[i]; i < MAXPLAYER; i++, j++)
+  {
+    if (j->ph_status == PHHIT2)
+    {
+      if (debug)
+      {
+	fprintf(stderr, "found PHHIT2 from %d at %d,%d\n", players[i].p_no,
+		j->ph_x, j->ph_y);
+	fprintf(stderr, "plasma is at %d,%d\n", pt->pt_x, pt->pt_y);
+	fprintf(stderr, "fl is at %d,%d\n", fl->pt_x, fl->pt_y);
+	fprintf(stderr, "fr is at %d,%d\n", fr->pt_x, fr->pt_y);
+      }
+      if (j->ph_x == pt->pt_x && j->ph_y == pt->pt_y)
+      {
+	return &players[i];
+      }
+    }
+  }
+  return NULL;
+}
+
+/*
+ * NOTE: the procedure could be writing shared memory variables at the same
+ * time as the daemon.  This may produce unpredicatable results.  A better
+ * implementation would mark the "snake plasma" and have the daemon do the
+ * awarding.
+ */
+
+award(win)
+  struct player *win;
+{
+  char buf[80];
+  char addrbuf[10];
+
+  if (!win)
+    return;
+
+  if (target == -1 && !(win->p_flags & PFROBOT) && !WARHOSTILE(win))
+  {
+    strcpy(buf, "Snake eyes!");
+
+    /* what do we have for our big winner today, fred? */
+
+    if (((100 * win->p_damage) / win->p_ship.s_maxdamage) > 50 ||
+	((100 * win->p_shield) / win->p_ship.s_maxshield) < 50)
+    {
+      win->p_damage = 0;
+      win->p_shield = win->p_ship.s_maxshield;
+      strcat(buf, " You win free repairs!");
+    }
+    else if (((100 * win->p_fuel) / win->p_ship.s_maxfuel) < 50)
+    {
+      win->p_fuel = win->p_ship.s_maxfuel;
+      strcat(buf, " You win free fuel!");
+    }
+    else if (((100 * win->p_etemp) / win->p_ship.s_maxegntemp) > 60)
+    {
+      win->p_etemp = 0;
+      strcat(buf, " You win free engine cooling!");
+    }
+    else if (((100 * win->p_wtemp) / win->p_ship.s_maxwpntemp) > 60)
+    {
+      win->p_wtemp = 0;
+      strcat(buf, " You win free weapons cooling!");
+    }
+    else
+    {
+      win->p_damage = 0;
+      win->p_shield = win->p_ship.s_maxshield;
+      win->p_fuel = win->p_ship.s_maxfuel;
+      win->p_etemp = 0;
+      win->p_wtemp = 0;
+      strcat(buf, " You feel healthy!");
+    }
+
+    /* ... */
+
+    sprintf(addrbuf, "%s->%c%c", SERVNAME,
+	    teams[win->p_team].letter, shipnos[win->p_no]);
+    pmessage2(buf, win->p_no, MINDIV, addrbuf, 255);
+  }
+  sprintf(buf, "%s (%c%c) slew the vile space serpent!",
+	  win->p_name, teams[win->p_team].letter, shipnos[win->p_no]);
+  pmessage(buf, 0, MALL | MKILLA, MSERVA, 255);
+
+  /* and get .5 kills */
+
+  win->p_kills += 0.5;
+  if (win->p_ship.s_type == STARBASE)
+  {
+    if (win->p_stats.st_sbmaxkills < win->p_kills)
+    {
+      win->p_stats.st_sbmaxkills = win->p_kills;
+    }
+  }
+  else if (win->p_stats.st_tmaxkills < win->p_kills)
+  {
+    win->p_stats.st_tmaxkills = win->p_kills;
+  }
+}
+
+bombcheck(team1, team2)
+  int team1, team2;
+{
+  register i;
+  register struct player *j;
+  struct planet *p;
+
+  for (i = 0, j = players; i < MAXPLAYER; i++, j++)
+  {
+    if (j->p_status == PALIVE)
+    {
+      if ((j->p_flags & PFBOMB) && (j->p_flags & PFORBIT))
+      {
+	p = &planets[j->p_planet];
+	if (!((j->p_swar | j->p_hostile) & p->pl_owner))
+	  continue;
+
+	if (defenders[p->pl_owner] >= configvals->tournplayers)
+	  continue;
+
+#if 0
+	/* ignore planets that aren't within team boundaries */
+	if (p->pl_x > boundaries[p->pl_owner].rx ||
+	    p->pl_x < boundaries[p->pl_owner].lx ||
+	    p->pl_y > boundaries[p->pl_owner].by ||
+	    p->pl_y < boundaries[p->pl_owner].ty)
+	  continue;
+#endif
+
+	if (!team1 && !team2)
+	{
+	  /* any planet */
+	  printf("snake found bomber: targeting %c%c\n",
+		 teams[j->p_team].letter, shipnos[j->p_no]);
+	  fflush(stdout);
+	  make_war(j, p->pl_owner);
+	  return j->p_no;
+	}
+	else
+	{
+	  if (team1)
+	  {
+	    if (p->pl_owner == team1)
+	    {
+	      printf("found bomber: targeting %c%c\n",
+		     teams[j->p_team].letter, shipnos[j->p_no]);
+	      fflush(stdout);
+	      make_war(j, p->pl_owner);
+	      return j->p_no;
+	    }
+	  }
+	  if (team2)
+	  {
+	    if (p->pl_owner == team2)
+	    {
+	      printf("found bomber: targeting %c%c\n",
+		     teams[j->p_team].letter, shipnos[j->p_no]);
+	      fflush(stdout);
+	      make_war(j, p->pl_owner);
+	      return j->p_no;
+	    }
+	  }
+	}
+      }
+    }
+  }
+  return -1;
+}
+
+make_war(p, plteam)
+  struct player *p;
+  int plteam;
+{
+  register int i;
+  register struct player *j;
+  register struct torp *k;
+
+  perfs[0]->p_team = plteam;
+  perfs[0]->p_swar = 0;
+  perfs[0]->p_hostile = 0;
+  perfs[1]->p_team = plteam;
+  perfs[1]->p_swar = 0;
+  perfs[1]->p_hostile = 0;
+
+  perfs[0]->p_swar |= p->p_team;
+  perfs[0]->p_hostile |= p->p_team;
+  perfs[1]->p_swar |= p->p_team;
+  perfs[1]->p_hostile |= p->p_team;
+
+  /* update our torps war status */
+  for (j = perfs[0]; j; j = (j == perfs[1] ? NULL : perfs[1]))
+  {
+    for (i = j->p_no * MAXTORP, k = &torps[i];
+	 i < j->p_no * MAXTORP + length; i++, k++)
+    {
+
+      k->t_war = perfs[0]->p_swar | perfs[0]->p_hostile;
+    }
+  }
+}
+
+
+
+/*
+ * start planet areas are places where people will likely enter the game
+ * (only considers 1 start planet at this time)
+ */
+
+sp_area(x, y)
+  int x, y;
+{
+  register i, j, px, py;
+
+#if 0
+  /* check for proximity to a shipyard? */
+  return 0;
+#else
+
+  for (i = 0; i < NUMPLANETS; i++)
+  {
+    struct planet *pl = &planets[i];
+    if (!(pl->pl_flags & (PLSHIPYARD | PLHOME)))
+      continue;
+    px = pl->pl_x;
+    py = pl->pl_y;
+    /* printf("checking %s (%d,%d)\n", pl->pl_name, i*10,j); */
+
+    if (!(x < px - 5300 || x > px + 5300 ||
+	  y < py - 5300 || y > py + 5300))
+    {
+#ifdef maybe			/* not used. */
+      if (target != -1)
+      {
+	struct player *p = &players[target];
+	/*
+	 * if target is also in same home area, he should at least be able to
+	 * phaser the snake since the torps are already deadly
+	 */
+	if (!(p->p_x < px - 5300 || p->p_x > px + 5300 ||
+	      p->p_y < py - 5300 || p->p_y > py + 5300))
+	  return 0;
+	else
+	  return 1;
+      }
+#endif
+      return 1;
+    }
+  }
+
+  return 0;
+
+#endif
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/socket.c	Sat Dec 06 04:37:04 1997 +0000
@@ -0,0 +1,4607 @@
+/*--------------------------------------------------------------------------
+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 <stdio.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <math.h>
+#include <signal.h>
+#include <errno.h>
+#include <string.h>
+#include <zlib.h>
+#include "defs.h"
+#include "struct.h"
+#include "data.h"
+#include "packets.h"
+#include "shmem.h"
+#include "path.h"
+#include "gppackets.h"
+
+#ifdef OOPS
+#ifdef MIPSEL
+#ifndef htonl
+
+#define htonl(x) ((u_long) (((u_long) x << 24) | (((u_long) x & 0xff00) << 8) | \
+		  (((u_long) x & 0xff0000) >> 8) | ((u_long) x >> 24)))
+#define ntohl(x) htonl(x)
+#define htons(x) ((u_short) (((u_short) x << 8) | ((u_short) x >> 8)))
+#define ntohs(x) htons(x)
+
+#endif				/* htonl */
+#endif				/* MIPSEL */
+#endif				/* OOPS */
+
+extern void (*r_signal()) ();
+
+/* #define DOUBLE_UDP		/* comment this out to disable it */
+
+/* #define BROKEN	/* for local stress testing; drops 20% of packets */
+/* #define HOSED		/* combine with BROKEN; drops 90% of packets */
+
+void handleTorpReq(), handlePhasReq(), handleSpeedReq();
+void handleDirReq(), handleShieldReq(), handleRepairReq(), handleOrbitReq();
+void handlePractrReq(), handleBombReq(), handleBeamReq(), handleCloakReq();
+void handleDetTReq(), handleCopilotReq();
+void handleOutfit(), handleLoginReq();
+void handlePlasmaReq(), handleWarReq(), handlePlanlockReq();
+void handlePlaylockReq(), handleDetMReq();
+void handleTractorReq(), handleRepressReq();
+void handleCoupReq(), handleRefitReq(), handleMessageReq();
+void handleQuitReq(), handleOptionsPacket();
+void handleSocketReq(), handleByeReq();
+void handleDockingReq(), handleReset();
+void handleUpdatesReq(), handleReserved();
+void handleScan();
+void handleUdpReq(), handleSequence();
+void handleAskMOTD();
+void handleRSAKey();
+void handlePingResponse();
+#ifdef SHORT_PACKETS
+void handleShortReq(), handleThresh(), handleSMessageReq();
+#endif
+#ifdef FEATURE
+void handleFeature(), sendFeature();	/* in feature.c */
+#endif
+
+static int remoteaddr = -1;	/* inet address in net format */
+extern int errno;
+
+struct packet_handler handlers[] = {
+  {0},				/* record 0 */
+  {handleMessageReq},		/* CP_MESSAGE */
+  {handleSpeedReq},		/* CP_SPEED */
+  {handleDirReq},		/* CP_DIRECTION */
+  {handlePhasReq},		/* CP_PHASER */
+  {handlePlasmaReq},		/* CP_PLASMA */
+  {handleTorpReq},		/* CP_TORP */
+  {handleQuitReq},		/* CP_QUIT */
+  {handleLoginReq},		/* CP_LOGIN */
+  {handleOutfit},		/* CP_OUTFIT */
+  {handleWarReq},		/* CP_WAR */
+  {handlePractrReq},		/* CP_PRACTR */
+  {handleShieldReq},		/* CP_SHIELD */
+  {handleRepairReq},		/* CP_REPAIR */
+  {handleOrbitReq},		/* CP_ORBIT */
+  {handlePlanlockReq},		/* CP_PLANLOCK */
+  {handlePlaylockReq},		/* CP_PLAYLOCK */
+  {handleBombReq},		/* CP_BOMB */
+  {handleBeamReq},		/* CP_BEAM */
+  {handleCloakReq},		/* CP_CLOAK */
+  {handleDetTReq},		/* CP_DET_TORPS */
+  {handleDetMReq},		/* CP_DET_MYTORP */
+  {handleCopilotReq},		/* CP_COPLIOT */
+  {handleRefitReq},		/* CP_REFIT */
+  {handleTractorReq},		/* CP_TRACTOR */
+  {handleRepressReq},		/* CP_REPRESS */
+  {handleCoupReq},		/* CP_COUP */
+  {handleSocketReq},		/* CP_SOCKET */
+  {handleOptionsPacket},	/* CP_OPTIONS */
+  {handleByeReq},		/* CP_BYE */
+  {handleDockingReq},		/* CP_DOCKPERM */
+  {handleUpdatesReq},		/* CP_UPDATES */
+  {handleReset},		/* CP_RESETSTATS */
+  {handleReserved},		/* CP_RESERVED */
+  {handleScan},			/* CP_SCAN (ATM) */
+  {handleUdpReq},		/* CP_UDP_REQ */
+  {handleSequence},		/* CP_SEQUENCE */
+  {handleRSAKey},		/* CP_RSA_KEY */
+  {handleAskMOTD},		/* CP_ASK_MOTD */
+  {0},
+  {0},
+  {0},
+  {handlePingResponse},		/* CP_PING_RESPONSE */
+#ifdef SHORT_PACKETS
+  {handleShortReq},		/* CP_S_REQ */
+  {handleThresh},		/* CP_S_THRS */
+  {handleSMessageReq},		/* CP_S_MESSAGE */
+  {0},				/* CP_S_RESERVED */
+  {0},				/* CP_S_DUMMY */
+#else
+  {0},
+  {0},
+  {0},
+  {0},
+  {0},
+#endif
+  {0},				/* 48 */
+  {0},				/* 49 */
+  {0},				/* 50 */
+  {0},				/* 51 */
+  {0},				/* 52 */
+  {0},				/* 53 */
+  {0},				/* 54 */
+  {0},				/* 55 */
+  {0},				/* 56 */
+  {0},				/* 57 */
+  {0},				/* 58 */
+  {0},				/* 59 */
+  {handleFeature},		/* CP_FEATURE */
+  {0}
+};
+#define NUM_PACKETS (sizeof(handlers) / sizeof(*handlers) - 1)
+
+int size_of_spacket();
+int size_of_cpacket();
+
+int packetsReceived[256] = {0};
+int packetsSent[256] = {0};
+
+int clientDead = 0;
+
+static int udpLocalPort = 0;
+static int udpClientPort = 0;
+int udpMode = MODE_SIMPLE;	/* what kind of UDP trans we want */
+
+/* this stuff is used for Fat UDP */
+typedef void *PTR;		/* adjust this if you lack (void *) */
+typedef struct fat_node_t
+{
+  PTR packet;
+  int pkt_size;
+  struct fat_node_t *prev;
+  struct fat_node_t *next;
+}   FAT_NODE;
+
+/* needed for fast lookup of semi-critical fat nodes */
+extern FAT_NODE fat_kills[MAXPLAYER];
+extern FAT_NODE fat_torp_info[MAXPLAYER * MAXTORP];
+extern FAT_NODE fat_thingy_info[TOTALTHINGIES];
+extern FAT_NODE fat_phaser[MAXPLAYER];
+extern FAT_NODE fat_plasma_info[MAXPLAYER * MAXPLASMA];
+extern FAT_NODE fat_you;
+#if 0
+extern FAT_NODE fat_status;
+extern FAT_NODE fat_planet[MAXPLANETS];
+#else
+extern FAT_NODE fat_status2;
+extern FAT_NODE fat_planet2[MAXPLANETS];
+#endif
+extern FAT_NODE fat_flags[MAXPLAYER];
+extern FAT_NODE fat_hostile[MAXPLAYER];
+
+struct plyr_info_spacket clientPlayersInfo[MAXPLAYER];
+struct plyr_login_spacket clientLogin[MAXPLAYER];
+struct hostile_spacket clientHostile[MAXPLAYER];
+struct stats_spacket clientStats[MAXPLAYER];
+struct player_spacket clientPlayers[MAXPLAYER];
+struct kills_spacket clientKills[MAXPLAYER];
+struct flags_spacket clientFlags[MAXPLAYER];
+struct pstatus_spacket clientPStatus[MAXPLAYER];
+int msgCurrent;
+struct torp_info_spacket clientTorpsInfo[MAXPLAYER * MAXTORP];
+struct torp_spacket clientTorps[MAXPLAYER * MAXTORP];
+struct thingy_info_spacket clientThingysInfo[TOTALTHINGIES];
+struct thingy_spacket clientThingys[TOTALTHINGIES];
+int clientThingyStatus[TOTALTHINGIES];
+struct phaser_spacket clientPhasers[MAXPLAYER];
+struct you_spacket clientSelf;
+struct pe1_num_missiles_spacket clientMissiles;
+#if 0
+struct status_spacket clientStatus;
+struct planet_spacket clientPlanets[MAXPLANETS];
+#endif
+struct planet_loc_spacket clientPlanetLocs[MAXPLANETS];
+struct plasma_info_spacket clientPlasmasInfo[MAXPLAYER * MAXPLASMA];
+struct plasma_spacket clientPlasmas[MAXPLAYER * MAXPLASMA];
+int mustUpdate[MAXPLAYER];
+struct status_spacket2 clientStatus2;	/* new stats packets */
+struct stats_spacket2 clientStats2[MAXPLAYER];
+struct planet_spacket2 clientPlanets2[MAXPLANETS];
+
+#ifdef SHORT_PACKETS
+
+struct youss_spacket clientSelfShip;
+struct youshort_spacket clientSelfShort;
+
+/* HW */
+static unsigned char clientVPlanets[MAXPLANETS * sizeof(struct planet_s_spacket) + 2 + 6];
+static int clientVPlanetCount;
+static int vtsize[9] = {4, 8, 8, 12, 12, 16, 20, 20, 24};	/* How big is the
+								 * SP_S_TORP packet */
+static int vtdata[9] = {0, 3, 5, 7, 9, 12, 14, 16, 18};	/* How big is Torpdata */
+static int mustsend;		/* Flag to remind me that i must send
+				 * SP_S_TORP */
+
+static unsigned char clientVTorps[40];
+
+static unsigned char clientVTorpsInfo[16];
+
+static unsigned char clientVPlayers[MAXPLAYER * VPLAYER_SIZE + 16];
+#if MAXPLAYER > 32
+static unsigned char clientVXPlayers[33 * 4];
+#endif
+static int clientVPlayerCount;
+static int clientVXPlayerCount;
+static int big, small;
+
+static int send_threshold = 0;	/* infinity */
+static int send_short = 0;
+static int send_mesg = 1;
+static int send_kmesg = 1;
+static int send_warn = 1;
+static int numupdates = 5;	/* For threshold */
+static int actual_threshold = 0;/* == send_threshold / numupdates */
+static int spk_update_sall = 0;	/* Small Update: Only weapons, Kills and
+				 * Planets */
+static int spk_update_all = 0;	/* Full Update minus SP_STATS */
+
+#define         SPK_VOFF         0	/* variable packets off */
+#define         SPK_VON          1	/* variable packets on */
+#define         SPK_MOFF         2	/* message packets off */
+#define         SPK_MON          3	/* message packets on */
+#define 	SPK_M_KILLS	 4
+#define 	SPK_M_NOKILLS	 5
+#define		SPK_THRESHOLD	 6
+#define		SPK_M_WARN	 7
+#define		SPK_M_NOWARN	 8
+#define	SPK_SALL 9		/* only planets,kills and weapons */
+#define 	SPK_ALL 10	/* Full Update - SP_STATS */
+
+#endif
+
+
+extern long unsigned int inet_addr( /* ??? */ );
+void initClientData();
+void updateTorpInfos();
+void short_updateTorps(), updateTorps();
+void updateMissiles();
+void updateThingies();
+void updatePlasmas();
+void updateStatus();
+void updateSelf();
+void updatePhasers();
+void updateShips();
+void updatePlanets();
+void updateTerrain();
+void updateMessages();
+void sendMissileNum();
+extern void updateWarnings();	/* warning.c */
+void sendClientSizedPacket();
+void sendClientPacket();
+void flushSockBuf();
+void updateMOTD();
+int parseQuery();
+void bounce();
+int gwrite();
+void printUdpInfo();
+int closeUdpConn();
+void updateFat();
+int fatten();
+void fatMerge();
+int doRead();
+extern int read();
+extern void perror();
+void logmessage();
+extern int ntorp();
+extern int phaser();
+extern int set_speed();
+extern int set_course();
+extern int shield_up();
+extern int shield_down();
+extern int repair();
+extern int orbit();
+extern pid_t fork();
+extern int execl();
+extern int bomb_planet();
+extern int beam_up();
+extern int beam_down();
+extern int cloak_on();
+extern int cloak_off();
+extern void detothers();
+extern void fire_missile_dir();
+extern int nplasmatorp();
+extern int lock_planet();
+extern int lock_player();
+extern int do_refit();
+extern int pmessage2();
+extern int parse_command_mess();
+extern int write();
+extern int setitimer();
+extern int gethostname();
+extern int decryptRSAPacket();
+extern int makeRSAPacket();
+extern int encryptReservedPacket();
+void forceUpdate();
+int connUdpConn();
+extern int sendMotd();
+void dequeue();
+void enqueue();
+extern int pmessage();
+
+int
+connectToClient(machine, port)
+  char *machine;
+  int port;
+{
+  int ns;
+  struct sockaddr_in addr;
+  struct hostent *hp;
+  /* int len,cc; */
+  /* char buf[BUFSIZ]; */
+  /* int i; */
+
+  if (sock != -1)
+  {
+    shutdown(sock, 2);
+    sock = -1;
+  }
+  /* printf("Connecting to %s through %d\n", machine, port); */
+
+  if ((ns = socket(AF_INET, SOCK_STREAM, 0)) < 0)
+  {
+    printf("I cannot create a socket\n");
+    exit(2);
+  }
+  addr.sin_family = AF_INET;
+  addr.sin_port = htons(port);
+
+  if (remoteaddr != -1)
+  {
+    addr.sin_addr.s_addr = remoteaddr;
+  }
+  else if ((addr.sin_addr.s_addr = inet_addr(machine)) == -1)
+  {
+    if ((hp = gethostbyname(machine)) == NULL)
+    {
+      printf("I cannot get host name\n");
+      close(ns);
+      exit(1);
+    }
+    else
+    {
+#if 1
+      memcpy((char *) &addr.sin_addr, hp->h_addr, hp->h_length);
+#else
+      addr.sin_addr.s_addr = *(long *) hp->h_addr;
+#endif
+    }
+  }
+  remoteaddr = addr.sin_addr.s_addr;
+
+  if (connect(ns, (struct sockaddr *) & addr, sizeof(addr)) < 0)
+  {
+    /* printf("I cannot connect through port %d\n", port); */
+    close(ns);
+    return (0);
+  }
+  sock = ns;
+  initClientData();
+  testtime = -1;
+  return (1);
+}
+
+/*
+ * Check the socket to read it's inet addr for possible future use.
+ */
+void
+checkSocket()
+{
+  struct sockaddr_in sin;
+  int length;
+
+  length = sizeof(sin);
+  if (getpeername(sock, (struct sockaddr *) & sin, &length) < 0)
+  {
+    /* A bad thing. */
+    return;
+  }
+  remoteaddr = sin.sin_addr.s_addr;
+}
+
+void
+initClientData()
+/* invalidates all data, so it is all sent to the client */
+{
+  int i;
+
+  clientDead = 0;
+  clientMissiles.num = 0;
+  for (i = 0; i < MAXPLAYER; i++)
+  {
+    clientHostile[i].hostile = -1;
+    clientStats[i].losses = -1;
+    clientLogin[i].rank = -1;
+    clientPlayersInfo[i].shiptype = -1;
+    clientPStatus[i].status = -1;
+    clientPlayers[i].x = htonl(-1);
+    clientPhasers[i].status = -1;
+    clientKills[i].kills = htonl(-1);
+    clientFlags[i].flags = htonl(-1);
+    mustUpdate[i] = 0;
+
+    fat_hostile[i].packet = (PTR) & clientHostile[i];
+    fat_hostile[i].pkt_size = sizeof(struct hostile_spacket);
+    fat_hostile[i].prev = fat_hostile[i].next = (FAT_NODE *) NULL;
+    fat_phaser[i].packet = (PTR) & clientPhasers[i];
+    fat_phaser[i].pkt_size = sizeof(struct phaser_spacket);
+    fat_phaser[i].prev = fat_phaser[i].next = (FAT_NODE *) NULL;
+    fat_kills[i].packet = (PTR) & clientKills[i];
+    fat_kills[i].pkt_size = sizeof(struct kills_spacket);
+    fat_kills[i].prev = fat_kills[i].next = (FAT_NODE *) NULL;
+    fat_flags[i].packet = (PTR) & clientFlags[i];
+    fat_flags[i].pkt_size = sizeof(struct flags_spacket);
+    fat_flags[i].prev = fat_flags[i].next = (FAT_NODE *) NULL;
+  }
+  for (i = 0; i < MAXPLAYER * MAXTORP; i++)
+  {
+    clientTorpsInfo[i].status = -1;
+    clientTorps[i].x = -1;
+
+    fat_torp_info[i].packet = (PTR) & clientTorpsInfo[i];
+    fat_torp_info[i].pkt_size = sizeof(struct torp_info_spacket);
+    fat_torp_info[i].prev = fat_torp_info[i].next = (FAT_NODE *) NULL;
+  }
+  for (i = 0; i < TOTALTHINGIES; i++)
+  {
+    clientThingysInfo[i].shape = htons(-1);
+    clientThingysInfo[i].owner = htons(i / NPTHINGIES);
+    clientThingys[i].x = htonl(-1);
+
+    fat_thingy_info[i].packet = (PTR) & clientThingysInfo[i];
+    fat_thingy_info[i].pkt_size = sizeof(struct torp_info_spacket);
+    fat_thingy_info[i].prev = fat_thingy_info[i].next = (FAT_NODE *) NULL;
+  }
+  for (i = 0; i < MAXPLAYER * MAXPLASMA; i++)
+  {
+    clientPlasmasInfo[i].status = -1;
+    clientPlasmas[i].x = -1;
+
+    fat_plasma_info[i].packet = (PTR) & clientPlasmasInfo[i];
+    fat_plasma_info[i].pkt_size = sizeof(struct plasma_info_spacket);
+    fat_plasma_info[i].prev = fat_plasma_info[i].next = (FAT_NODE *) NULL;
+  }
+  for (i = 0; i < MAXPLANETS; i++)
+  {
+    clientPlanets2[i].armies = htonl(-1);
+    clientPlanetLocs[i].x = htonl(-1);
+
+#if 0
+    fat_planet[i].packet = (PTR) & clientPlanets[i];
+    fat_planet[i].pkt_size = sizeof(struct planet_spacket);
+    fat_planet[i].prev = fat_planet[i].next = (FAT_NODE *) NULL;
+#else
+    fat_planet2[i].packet = (PTR) & clientPlanets2[i];
+    fat_planet2[i].pkt_size = sizeof(struct planet_spacket2);
+    fat_planet2[i].prev = fat_planet2[i].next = (FAT_NODE *) 0;
+#endif
+  }
+  msgCurrent = (mctl->mc_current + 1) % MAXMESSAGE;
+  clientSelf.pnum = -1;
+
+  fat_you.packet = (PTR) & clientSelf;
+  fat_you.pkt_size = sizeof(struct you_spacket);
+  fat_you.prev = fat_you.next = (FAT_NODE *) NULL;
+#if 0
+  fat_status.packet = (PTR) & clientStatus;
+  fat_status.pkt_size = sizeof(struct status_spacket);
+  fat_status.prev = fat_status.next = (FAT_NODE *) NULL;
+#else
+  fat_status2.packet = (PTR) & clientStatus2;
+  fat_status2.pkt_size = sizeof(struct status_spacket2);
+  fat_status2.prev = fat_status2.next = (FAT_NODE *) 0;
+#endif
+
+  reset_fat_list();
+}
+
+int
+isClientDead()
+{
+  return (clientDead);
+}
+
+void
+updateClient()
+{
+  int i;
+
+  for (i = 0; i < MAXPLAYER; i++)
+  {
+    mustUpdate[i] = 0;
+  }
+  updateShips();
+#ifdef SHORT_PACKETS
+  if (send_short)
+  {
+    short_updateTorps();
+  }
+  else
+#endif
+  {
+    updateTorps();
+    updateTorpInfos();
+  }
+
+  if (weaponsallowed[WP_MISSILE] ||
+      weaponsallowed[WP_FIGHTER])
+    updateMissiles();
+  updateThingies();
+  sendMissileNum(me->p_ship.s_missilestored);
+  updatePlasmas();
+  updateStatus();
+  updateSelf();
+  updatePhasers();
+  updatePlanets();
+  updateTerrain();		/* for galaxy reset */
+  updateMessages();
+  updateWarnings();		/* warning.c */
+
+  /*
+   * these checks are here to make sure we don't ping from the updateClient
+   * call in death().  The reason is that savestats() can take > 100ms,
+   * invalidating the next ping lag calc
+   */
+  /* Also, don't ping while in verification stage */
+
+  if (ping
+      && (repCount % efticks(5 * configvals->ping_period) == 0)
+      && me->p_status != PDEAD
+      && me->p_status != POUTFIT
+  /* && me->p_status != PTQUEUE */
+#ifdef AUTHORIZE
+      && testtime <= 0
+#endif
+    )
+    sendClientPing();		/* ping.c */
+
+  if (buffersEmpty())
+  {
+    /* We sent nothing!  We better send something to wake him */
+    sendClientPacket((struct player_spacket *) & clientSelf);
+  }
+  flushSockBuf();
+  repCount++;
+}
+
+void
+briefUpdateClient()
+{
+  updateMessages();
+  updateMOTD();
+  updateWarnings();
+
+  flushSockBuf();
+  repCount++;
+}
+
+void
+updateStatus()
+{
+  if (repCount % efticks(75) == 0 &&
+      ((ntohl(clientStatus2.timeprod) != status->timeprod) ||
+       (clientStatus2.tourn != status->tourn)))
+  {
+    clientStatus2.type = SP_STATUS2;
+    clientStatus2.tourn = status->tourn;
+    clientStatus2.dooshes = htonl(status->dooshes);
+    clientStatus2.armsbomb = htonl(status->armsbomb);
+    clientStatus2.resbomb = htonl(status->resbomb);
+    clientStatus2.planets = htonl(status->planets);
+    clientStatus2.kills = htonl(status->kills);
+    clientStatus2.losses = htonl(status->losses);
+    clientStatus2.sbkills = htonl(status->sbkills);
+    clientStatus2.sblosses = htonl(status->sblosses);
+    clientStatus2.sbtime = htonl(status->sbtime);
+    clientStatus2.wbkills = htonl(status->wbkills);
+    clientStatus2.wblosses = htonl(status->wblosses);
+    clientStatus2.wbtime = htonl(status->wbtime);
+    clientStatus2.jsplanets = htonl(status->jsplanets);
+    clientStatus2.jstime = htonl(status->jstime);
+    clientStatus2.time = htonl(status->time);
+    clientStatus2.timeprod = htonl(status->timeprod);
+    sendClientPacket((struct player_spacket *) & clientStatus2);
+  }
+}
+
+struct player *
+maybe_watching(p)
+  struct player *p;
+{
+  struct player *tg = &players[me->p_playerl];
+  return (p == me
+	  && me->p_status == POBSERVE
+	  && (me->p_flags & PFPLOCK)
+	  && (me->p_teamspy & tg->p_team)
+	  && tg->p_spyable) ?
+    tg : p;
+}
+
+struct planet *
+maybe_watching_planet()
+{
+  return (me->p_status == POBSERVE && (me->p_flags & PFPLLOCK)) ?
+  &planets[me->p_planet] : 0;
+}
+
+void
+updateSelf()
+{
+  struct player *watched = maybe_watching(me);
+  int armies = maybe_watching_planet()
+  ? maybe_watching_planet()->pl_armies
+  : watched->p_armies;
+  int damage;
+
+  damage = watched->p_damage
+    + shipvals[watched->p_ship.s_type].s_maxdamage
+    - watched->p_ship.s_maxdamage;
+
+  if (ntohl(clientSelf.fuel) != watched->p_fuel ||
+      ntohl(clientSelf.shield) != watched->p_shield ||
+      ntohl(clientSelf.damage) != damage ||
+      ntohs(clientSelf.etemp) != watched->p_etemp ||
+      ntohs(clientSelf.wtemp) != watched->p_wtemp ||
+      ntohl(clientSelf.flags) != watched->p_flags ||
+      clientSelf.armies != armies ||
+      clientSelf.swar != watched->p_swar ||
+      ntohs(clientSelf.whydead) != watched->p_whydead ||
+      ntohs(clientSelf.whodead) != watched->p_whodead ||
+      clientSelf.pnum != me->p_no)
+  {
+
+    /* we want to send it, but how? */
+    clientSelf.type = SP_YOU;
+
+    if (commMode == COMM_UDP)
+    {
+      if (ntohl(clientSelf.flags) != watched->p_flags ||
+	  clientSelf.armies != armies ||
+	  clientSelf.swar != watched->p_swar)
+      {
+	clientSelf.type = SP_YOU | 0x40;	/* mark as semi-critical */
+      }
+      if (ntohs(clientSelf.whydead) != watched->p_whydead ||
+	  ntohs(clientSelf.whodead) != watched->p_whodead ||
+	  clientSelf.pnum != me->p_no)
+      {
+	clientSelf.type = SP_YOU | 0x80;	/* mark as critical */
+      }
+    }
+    clientSelf.pnum = me->p_no;
+    clientSelf.flags = htonl(watched->p_flags);
+    clientSelf.swar = watched->p_swar;
+    clientSelf.hostile = watched->p_hostile;
+    clientSelf.armies = armies;
+    clientSelf.shield = htonl(watched->p_shield);
+    clientSelf.fuel = htonl(watched->p_fuel);
+    clientSelf.etemp = htons(watched->p_etemp);
+    clientSelf.wtemp = htons(watched->p_wtemp);
+    clientSelf.whydead = htons(watched->p_whydead);
+    clientSelf.whodead = htons(watched->p_whodead);
+    clientSelf.damage = htonl(damage);
+    /* ATM - visible tractor */
+    clientSelf.tractor = (char) watched->p_tractor | 0x40;
+
+    clientSelf.pad2 = (unsigned char) (status->clock & 0xFF);
+    clientSelf.pad3 = (unsigned char) ((status->clock & 0xFF00) >> 8);
+    sendClientPacket((struct player_spacket *) & clientSelf);
+  }
+}
+
+extern int ignored[];
+
+void
+updateShips()
+{
+  register int i;
+  register struct player *pl;
+  register struct plyr_info_spacket *cpli;
+  register struct player_spacket *cpl;
+  register struct kills_spacket *kills;
+  register struct flags_spacket *flags;
+  register struct pstatus_spacket *pstatus;
+  register struct plyr_login_spacket *login;
+  register struct hostile_spacket *hostile;
+#if 0
+  struct stats_spacket ms_stats;
+#endif
+  register struct stats_spacket2 *stats;
+  int update;
+  int x, y;
+  /*
+   * #define FLAGMASK
+   * (PFSHIELD|PFBOMB|PFORBIT|PFCLOAK|PFROBOT|PFBEAMUP|PFBEAMDOWN|PFPRACTR|PFD
+   * OCK|PFTRACT|PFPRESS|PFDOCKOK) atm mask
+   */
+
+  /*
+   * #define FLAGMASK
+   * (PFSHIELD|PFBOMB|PFORBIT|PFCLOAK|PFROBOT|PFBEAMUP|PFBEAMDOWN|PFPRACTR|PFD
+   * OCK|PFTRACT|PFPRESS|PFDOCKOK) aieee, too much.  7/27/91 TC
+   */
+
+#define FLAGMASK (PFSHIELD|PFBOMB|PFORBIT|PFCLOAK|PFROBOT|PFPRACTR|PFDOCK|PFTRACT|PFPRESS|PFDOCKOK)
+#define INVISOMASK (PFCLOAK|PFROBOT|PFPRACTR|PFDOCKOK)
+
+  /* Please excuse the ugliness of this loop declaration */
+  for (i = 0, pl = players, cpli = clientPlayersInfo, cpl = clientPlayers, kills = clientKills, flags = clientFlags, pstatus = clientPStatus, login = clientLogin, hostile = clientHostile, stats = clientStats2;
+       i < MAXPLAYER;
+       i++, pl++, cpli++, cpl++, kills++, flags++, pstatus++, login++, hostile++, stats++)
+  {
+    update = 0;
+    if (strcmp(pl->p_name, login->name) != 0 ||
+	pl->p_stats.st_rank != login->rank ||
+	strcmp(pl->p_monitor, login->monitor) != 0)
+    {
+      strncpy(login->name, pl->p_name, 15);
+      strncpy(login->monitor, pl->p_monitor, 15);
+      strncpy(login->login, pl->p_login, 15);
+      login->name[15] = 0;
+      login->monitor[15] = 0;
+      login->login[15] = 0;
+      login->type = SP_PL_LOGIN;
+      login->pnum = i;
+      login->rank = pl->p_stats.st_rank;
+      sendClientPacket((struct player_spacket *) login);
+    }
+    if ((pl != me && (pl->p_swar & me->p_team) != hostile->war) ||
+	(pl != me && (pl->p_hostile & me->p_team) != hostile->hostile) ||
+	(pl == me && pl->p_swar != hostile->war) ||
+	(pl == me && pl->p_hostile != hostile->hostile))
+    {
+      hostile->type = SP_HOSTILE;
+      if (pl == me)
+      {
+	hostile->war = pl->p_swar;
+	hostile->hostile = pl->p_hostile;
+      }
+      else
+      {
+	hostile->war = (pl->p_swar & me->p_team);
+	hostile->hostile = (pl->p_hostile & me->p_team);
+      }
+      hostile->pnum = i;
+      sendClientPacket((struct player_spacket *) hostile);
+    }
+    /*
+     * Send stat packets once per five updates. But, only send one.  We will
+     * cycle through them all eventually.
+     */
+    /*
+     * Also, update if status chages (i.e., entered game, died, tq'ed, etc)
+     */
+
+    if (pl->p_status != pstatus->status ||
+	(repCount % (MAXPLAYER * efticks(5)) == i * efticks(5) &&
+	 (stats->di != htonl(pl->p_stats.st_di) ||
+	  stats->kills != htonl(pl->p_stats.st_tkills) ||
+	  stats->losses != htonl(pl->p_stats.st_tlosses) ||
+	  stats->armsbomb != htonl(pl->p_stats.st_tarmsbomb) ||
+	  stats->resbomb != htonl(pl->p_stats.st_tresbomb) ||
+	  stats->dooshes != htonl(pl->p_stats.st_tdooshes) ||
+	  stats->planets != htonl(pl->p_stats.st_tplanets) ||
+	  stats->sbkills != htonl(pl->p_stats.st_sbkills) ||
+	  stats->sblosses != htonl(pl->p_stats.st_sblosses) ||
+	  stats->wbkills != htonl(pl->p_stats.st_wbkills) ||
+	  stats->wblosses != htonl(pl->p_stats.st_wblosses) ||
+	  stats->jsplanets != htonl(pl->p_stats.st_jsplanets) ||
+	  stats->rank != htonl(pl->p_stats.st_rank) ||
+	  stats->royal != htonl(pl->p_stats.st_royal))))
+    {
+
+      stats->genocides = htonl(pl->p_stats.st_genocides);
+      stats->maxkills = htonl((int) (pl->p_stats.st_tmaxkills * 100));
+      stats->di = htonl((int) (pl->p_stats.st_di * 100));
+      stats->kills = htonl(pl->p_stats.st_tkills);
+      stats->losses = htonl(pl->p_stats.st_tlosses);
+      stats->armsbomb = htonl(pl->p_stats.st_tarmsbomb);
+      stats->resbomb = htonl(pl->p_stats.st_tresbomb);
+      stats->dooshes = htonl(pl->p_stats.st_tdooshes);
+      stats->planets = htonl(pl->p_stats.st_tplanets);
+      stats->tticks = htonl(pl->p_stats.st_tticks);
+      stats->sbkills = htonl(pl->p_stats.st_sbkills);
+      stats->sblosses = htonl(pl->p_stats.st_sblosses);
+      stats->sbticks = htonl(pl->p_stats.st_sbticks);
+      stats->sbmaxkills = htonl((int) (pl->p_stats.st_sbmaxkills * 100));
+      stats->wbkills = htonl(pl->p_stats.st_wbkills);
+      stats->wblosses = htonl(pl->p_stats.st_wblosses);
+      stats->wbticks = htonl(pl->p_stats.st_wbticks);
+      stats->wbmaxkills = htonl((int) (pl->p_stats.st_wbmaxkills * 100));
+      stats->jsplanets = htonl(pl->p_stats.st_jsplanets);
+      stats->jsticks = htonl(pl->p_stats.st_jsticks);
+      stats->rank = htonl(pl->p_stats.st_rank);
+      stats->royal = htonl(pl->p_stats.st_royal);
+      stats->type = SP_STATS2;
+      stats->pnum = i;
+      /* if (blk_metaserver == 0) */
+      sendClientPacket((struct player_spacket *) stats);
+#if 0
+      else
+      {
+	ms_stats.type = SP_STATS;
+	ms_stats.pnum = i;
+	ms_stats.tkills = htonl(pl->p_stats.st_tkills);
+	ms_stats.tlosses = htonl(pl->p_stats.st_tlosses);
+	ms_stats.kills = htonl(1);
+	ms_stats.losses = htonl(1);
+	ms_stats.tticks = htonl(pl->p_stats.st_tticks);
+	ms_stats.tplanets = htonl(pl->p_stats.st_tplanets);
+	ms_stats.tarmies = htonl(pl->p_stats.st_tarmsbomb);
+	ms_stats.sbkills = htonl(pl->p_stats.st_sbkills);
+	ms_stats.sblosses = htonl(pl->p_stats.st_sblosses);
+	ms_stats.armies = htonl(1);
+	ms_stats.planets = htonl(1);
+	ms_stats.maxkills = htonl((long) (pl->p_stats.st_tmaxkills * 100));
+	ms_stats.sbmaxkills = htonl((long) (pl->p_stats.st_sbmaxkills * 100));
+	sendClientPacket((struct player_spacket *) & ms_stats);
+      }
+#endif
+    }
+    if (maybe_watching(pl)->p_ship.s_type != cpli->shiptype ||
+	pl->p_team != cpli->team)
+    {
+      cpli->type = SP_PLAYER_INFO;
+      cpli->pnum = i;
+      cpli->shiptype = maybe_watching(pl)->p_ship.s_type;
+      cpli->team = pl->p_team;
+      sendClientPacket((struct player_spacket *) cpli);
+      /*
+       * if (!blk_flag) cpli->shiptype=pl->p_ship.s_type;
+       */
+    }
+    if (kills->kills != htonl((int) (maybe_watching(pl)->p_kills * 100)))
+    {
+      kills->type = SP_KILLS;
+      kills->pnum = i;
+      kills->kills = htonl((int) (maybe_watching(pl)->p_kills * 100));
+      sendClientPacket((struct player_spacket *) kills);
+    }
+    {
+      int plstat = pl->p_status;
+
+#ifdef LEAGUE_SUPPORT
+      if (status2->paused && pl->p_team != me->p_team)
+	plstat = PFREE;		/* enemies are invisible when the game is
+				 * paused */
+#endif
+
+      if (pstatus->status != plstat)
+      {
+	/*
+	 * We update the location of people whose status has changed. (like
+	 * if they just re-entered...)
+	 */
+	update = 1;
+	pstatus->type = SP_PSTATUS;
+	pstatus->pnum = i;
+	pstatus->status = plstat;
+	if (pl->p_status == PFREE)
+	{
+	  /*
+	   * I think this will turn off ignores for players that leave.
+	   * 7/24/91 TC
+	   */
+	  ignored[i] = 0;
+	}
+	sendClientPacket((struct player_spacket *) pstatus);
+      }
+    }
+
+    /* Used to send flags here, see below 8/7/91 TC */
+
+    if (!configvals->hiddenenemy || pl->p_team == me->p_team ||
+	(maybe_watching(pl)->p_flags & PFSEEN) || (status->tourn == 0) ||
+	(maybe_watching(pl)->p_flags & PFROBOT))
+    {				/* a bot never has its PFSEEN bit set */
+
+      x = maybe_watching(pl)->p_x;
+      y = maybe_watching(pl)->p_y;
+      if (me != pl && flags->flags !=
+	  htonl(FLAGMASK & maybe_watching(pl)->p_flags))
+      {
+	flags->type = SP_FLAGS;
+	flags->pnum = i;
+	flags->flags = htonl(FLAGMASK & maybe_watching(pl)->p_flags);
+	flags->tractor = (char) maybe_watching(pl)->p_tractor | 0x40;	/* ATM - visible tractor */
+	sendClientPacket((struct player_spacket *) flags);
+      }
+    }
+    else
+    {
+      /* A hack to make him inviso */
+      x = -100000;
+      y = -100000;
+
+      /* reduce flag info if he's inviso 8/7/91 TC */
+
+      if (me != pl && flags->flags != htonl(INVISOMASK & pl->p_flags))
+      {
+	flags->type = SP_FLAGS;
+	flags->pnum = i;
+	flags->flags = htonl(INVISOMASK & pl->p_flags);
+	sendClientPacket((struct player_spacket *) flags);
+      }
+    }
+    if (x != ntohl(cpl->x) || y != ntohl(cpl->y) ||
+	maybe_watching(pl)->p_dir != cpl->dir ||
+	maybe_watching(pl)->p_speed != cpl->speed)
+    {
+      /*
+       * We update the player if: 1) haven't updated him for 9 intervals. 2)
+       * he is on the screen 3) he was on the screen recently.
+       */
+      if (!update && repCount % efticks(9) != 0 &&
+	  (ntohl(cpl->x) < me->p_x - SCALE * WINSIDE / 2 ||
+	   ntohl(cpl->x) > me->p_x + SCALE * WINSIDE / 2 ||
+	   ntohl(cpl->y) > me->p_y + SCALE * WINSIDE / 2 ||
+	   ntohl(cpl->y) < me->p_y - SCALE * WINSIDE / 2) &&
+	  (y > me->p_y + SCALE * WINSIDE / 2 ||
+	   x > me->p_x + SCALE * WINSIDE / 2 ||
+	   x < me->p_x - SCALE * WINSIDE / 2 ||
+	   y < me->p_y - SCALE * WINSIDE / 2))
+	continue;
+      /*
+       * If the guy is cloaked, give information only occasionally, and make
+       * it slightly inaccurate. Also, we don't give a direction. The client
+       * has no reason to know.
+       */
+      if ((pl->p_flags & PFCLOAK) &&
+	  (pl->p_cloakphase == (CLOAK_PHASES - 1)) &&
+	  (maybe_watching(me) != pl) && !mustUpdate[i])
+      {
+	if (repCount % efticks(9) != 0)
+	  continue;
+	cpl->type = SP_PLAYER;
+	cpl->pnum = i;
+	cpl->x = htonl(x + (lrand48() % 2000) - 1000);
+	cpl->y = htonl(y + (lrand48() % 2000) - 1000);
+	sendClientPacket(cpl);
+	continue;
+      }
+      cpl->type = SP_PLAYER;
+      cpl->pnum = i;
+      cpl->x = htonl(x);
+      cpl->y = htonl(y);
+      cpl->speed = maybe_watching(pl)->p_speed;
+      cpl->dir = maybe_watching(pl)->p_dir;
+      sendClientPacket(cpl);
+    }
+  }
+}
+
+void
+updateTorpInfos()
+{
+  register struct torp *torp;
+  register int i;
+  register struct torp_info_spacket *tpi;
+
+  for (i = 0, torp = torps, tpi = clientTorpsInfo;
+       i < MAXPLAYER * MAXTORP;
+       i++, torp++, tpi++)
+  {
+    if (torp->t_owner == me->p_no)
+    {
+      if (torp->t_war != tpi->war ||
+	  torp->t_status != tpi->status)
+      {
+	tpi->type = SP_TORP_INFO;
+	tpi->war = torp->t_war;
+	tpi->status = torp->t_status;
+	tpi->tnum = htons(i);
+	sendClientPacket((struct player_spacket *) tpi);
+      }
+    }
+    else
+    {				/* Someone else's torp... */
+      if (torp->t_y > me->p_y + SCALE * WINSIDE / 2 ||
+	  torp->t_x > me->p_x + SCALE * WINSIDE / 2 ||
+	  torp->t_x < me->p_x - SCALE * WINSIDE / 2 ||
+	  torp->t_y < me->p_y - SCALE * WINSIDE / 2 ||
+	  torp->t_status == TFREE)
+      {
+	if (torp->t_status == TFREE && tpi->status == TEXPLODE)
+	{
+	  tpi->status = TFREE;
+	  continue;
+	}
+	if (tpi->status != TFREE)
+	{
+	  tpi->status = TFREE;
+	  tpi->tnum = htons(i);
+	  tpi->type = SP_TORP_INFO;
+	  sendClientPacket((struct player_spacket *) tpi);
+	}
+      }
+      else
+      {				/* in view */
+	enum torp_status_e tstatus = torp->t_status;
+
+#ifdef LEAGUE_SUPPORT
+	if (status2->paused
+	    && players[torp->t_owner].p_team != me->p_team)
+	  tstatus = TFREE;	/* enemy torps are invisible during game
+				 * pause */
+#endif
+
+	if (tstatus != tpi->status ||
+	    (torp->t_war & me->p_team) != tpi->war)
+	{
+	  /* Let the client fade away the explosion on its own */
+	  tpi->war = torp->t_war & me->p_team;
+	  tpi->type = SP_TORP_INFO;
+	  tpi->tnum = htons(i);
+	  tpi->status = tstatus;
+	  sendClientPacket((struct player_spacket *) tpi);
+	}
+      }
+    }
+  }
+}
+
+
+
+void
+updateTorps()
+{
+  register struct torp *torp;
+  register int i;
+  register struct torp_spacket *tp;
+
+  for (i = 0, torp = torps, tp = clientTorps;
+       i < MAXPLAYER * MAXTORP;
+       i++, torp++, tp++)
+  {
+    if (torp->t_owner == me->p_no)
+    {
+
+      if (tp->x != htonl(torp->t_x) ||
+	  tp->y != htonl(torp->t_y))
+      {
+	tp->type = SP_TORP;
+	tp->x = htonl(torp->t_x);
+	tp->y = htonl(torp->t_y);
+	tp->dir = torp->t_dir;
+	tp->tnum = htons(i);
+	sendClientPacket((struct player_spacket *) tp);
+      }
+    }
+    else
+    {				/* Someone else's torp... */
+      if (torp->t_y > me->p_y + SCALE * WINSIDE / 2 ||
+	  torp->t_x > me->p_x + SCALE * WINSIDE / 2 ||
+	  torp->t_x < me->p_x - SCALE * WINSIDE / 2 ||
+	  torp->t_y < me->p_y - SCALE * WINSIDE / 2 ||
+	  torp->t_status == TFREE)
+      {
+	/* do nothing */
+      }
+      else
+      {				/* in view */
+	enum torp_status_e tstatus = torp->t_status;
+
+#ifdef LEAGUE_SUPPORT
+	if (status2->paused
+	    && players[torp->t_owner].p_team != me->p_team)
+	  tstatus = TFREE;	/* enemy torps are invisible during game
+				 * pause */
+#endif
+
+	if (tstatus == TFREE)
+	  continue;		/* no need to transmit position */
+
+	if (tp->x != htonl(torp->t_x) ||
+	    tp->y != htonl(torp->t_y))
+	{
+	  tp->x = htonl(torp->t_x);
+	  tp->y = htonl(torp->t_y);
+	  tp->dir = torp->t_dir;
+	  tp->tnum = htons(i);
+	  tp->type = SP_TORP;
+	  sendClientPacket((struct player_spacket *) tp);
+	}
+      }
+    }
+  }
+}
+
+#ifdef SHORT_PACKETS
+
+#define NIBBLE()	*(*data)++ = (torp->t_war & 0xf) | (torp->t_status << 4)
+
+int 
+encode_torp_status(torp, pnum, data, tpi, tp, mustsend)
+  struct torp *torp;
+  int pnum;
+  char **data;
+  struct torp_info_spacket *tpi;
+  struct torp_spacket *tp;
+  int *mustsend;
+{
+  if (pnum != me->p_no)
+  {
+    int dx, dy;
+    int i = SCALE * WINSIDE / 2;
+    dx = me->p_x - torp->t_x;
+    dy = me->p_y - torp->t_y;
+    if (dx < -i || dx > i || dy < -i || dy > i || torp->t_status == TFREE)
+    {
+      if (torp->t_status == TFREE && tpi->status == TEXPLODE)
+	tpi->status = TFREE;
+      else if (tpi->status != TFREE)
+      {
+	tpi->status = TFREE;
+	*mustsend = 1;
+      }
+      return 0;
+    }
+  }
+
+  if (torp->t_war != tpi->war)
+  {
+    tpi->war = torp->t_war;
+    tpi->status = torp->t_status;
+    NIBBLE();
+    return 1;
+  }
+  else if (torp->t_status != tpi->status)
+  {
+    switch (torp->t_status)
+    {
+     case TFREE:
+      {
+	int rval = 0;
+	if (tpi->status == TEXPLODE)
+	{
+	  NIBBLE();
+	  rval = 1;
+	}
+	else
+	  *mustsend = 1;
+	tpi->status = torp->t_status;
+	tp->x = htonl(torp->t_x);
+	tp->y = htonl(torp->t_y);
+	return rval;
+      }
+      break;
+     case TMOVE:
+     case TSTRAIGHT:
+      tpi->status = torp->t_status;
+      break;
+     default:
+      NIBBLE();
+      tpi->status = torp->t_status;
+      return 1;
+      break;
+    }
+  }
+  return 0;
+}
+
+#define	TORP_INVISIBLE(tstatus) ( \
+				 (tstatus)== TFREE || \
+				 (tstatus) == TOFF || \
+				 (tstatus) == TLAND)
+
+int 
+encode_torp_position(torp, pnum, data, shift, cache)
+  struct torp *torp;
+  int pnum;
+  char **data;
+  int *shift;
+  struct torp_spacket *cache;
+{
+  int x, y;
+
+  if (htonl(torp->t_x) == cache->x &&
+      htonl(torp->t_y) == cache->y)
+    return 0;
+
+  cache->x = htonl(torp->t_x);
+  cache->y = htonl(torp->t_y);
+
+  if (TORP_INVISIBLE(torp->t_status)
+#ifdef LEAGUE_SUPPORT
+      || (status2->paused &&
+	  players[pnum].p_team != me->p_team)
+#endif
+    )
+    return 0;
+
+  x = torp->t_x / SCALE - me->p_x / SCALE + WINSIDE / 2;
+  y = torp->t_y / SCALE - me->p_y / SCALE + WINSIDE / 2;
+
+  if (x < 0 || x >= WINSIDE ||
+      y < 0 || y >= WINSIDE)
+  {
+    if (pnum != me->p_no)
+      return 0;
+    x = y = 501;
+  }
+
+  **data |= x << *shift;
+  *(++(*data)) = (0x1ff & x) >> (8 - *shift);
+  (*shift)++;
+  **data |= y << *shift;
+  *(++(*data)) = (0x1ff & y) >> (8 - *shift);
+  (*shift)++;
+  if (*shift == 8)
+  {
+    *shift = 0;
+    *(++(*data)) = 0;
+  }
+  return 1;
+}
+
+void
+short_updateTorps()
+{
+  register int i;
+
+  for (i = 0; i <= (MAXPLAYER * MAXTORP - 1) / 8; i++)
+  {
+    struct torp *torp = &torps[i * 8];
+    int j;
+    char packet[2		/* packet type and player number */
+		+   1		/* torp mask */
+		+   1		/* torp info mask */
+		+   18		/* 2*8 9-bit numbers */
+		+   8		/* 8 torp info bytes */
+    ];
+    char *data = packet + 4;
+    char info[8];
+    char *ip = info;
+    int shift = 0;
+    int torppos_mask = 0;
+    int torpinfo_mask = 0;
+    int mustsend;
+
+    /* encode screen x and y coords */
+    data[0] = 0;
+#define TIDX	(j+i*8)
+#define PNUM	((int)((j+i*8)/MAXTORP))
+    for (j = 0; j < 8 && TIDX < MAXPLAYER * MAXTORP; j++)
+    {
+      torpinfo_mask |= encode_torp_status
+	(&torp[j], PNUM, &ip, &clientTorpsInfo[TIDX], &clientTorps[TIDX], &mustsend) << j;
+      torppos_mask |= encode_torp_position
+	(&torp[j], PNUM, &data, &shift, &clientTorps[TIDX]) << j;
+    }
+
+    /*
+     * if (!torppos_mask) continue;
+     */
+
+    if (torpinfo_mask)
+    {
+      if (shift)
+	data++;
+      for (j = 0; j < 8 && &info[j] < ip; j++)
+	data[j] = info[j];
+      packet[0] = SP_S_TORP_INFO;
+      packet[1] = torppos_mask;
+      packet[2] = i;
+      packet[3] = torpinfo_mask;
+      sendClientSizedPacket(packet, (data - packet + j));
+    }
+    else if (torppos_mask == 0xff)
+    {
+      /* what a disgusting hack */
+      packet[2] = SP_S_8_TORP;
+      packet[3] = i;
+      sendClientSizedPacket(packet + 2, 20);
+    }
+    else if (mustsend || torppos_mask != 0)
+    {
+      packet[1] = SP_S_TORP;
+      packet[2] = torppos_mask & 0xff;
+      packet[3] = i;
+      sendClientSizedPacket(packet + 1, (data - (packet + 1) + (shift != 0)));
+    }
+  }
+#undef PNUM
+#undef TIDX
+}
+
+
+#endif
+
+
+void
+updateMissiles()
+{
+  register struct missile *missile;
+  register int i;
+  register struct thingy_info_spacket *dpi;
+  register struct thingy_spacket *dp;
+
+  for (i = 0, missile = missiles, dpi = clientThingysInfo, dp = clientThingys;
+       i < MAXPLAYER * NPTHINGIES;
+       i++, missile++, dpi++, dp++)
+  {
+    enum torp_status_e msstatus = missile->ms_status;
+
+#ifdef LEAGUE_SUPPORT
+    if (status2->paused &&
+	players[missile->ms_owner].p_team != me->p_team)
+      msstatus = TFREE;		/* enemy torps are invisible during game
+				 * pause */
+#endif
+
+    switch (msstatus)
+    {
+     case TFREE:
+     case TLAND:
+     case TOFF:
+      dpi->shape = htons(SHP_BLANK);
+      break;
+     case TMOVE:
+     case TRETURN:
+     case TSTRAIGHT:
+      dpi->shape = htons((missile->ms_type == FIGHTERTHINGY)
+			 ? SHP_FIGHTER
+			 : SHP_MISSILE);
+      break;
+     case TEXPLODE:
+     case TDET:
+      dpi->shape = htons(SHP_PBOOM);
+      break;
+    }
+
+    dpi->type = SP_THINGY_INFO;
+    dpi->tnum = htons(i);
+
+    dp->type = SP_THINGY;
+    dp->tnum = htons(i);
+    dp->dir = missile->ms_dir;
+
+    if (missile->ms_owner == me->p_no)
+    {
+      if (missile->ms_war != dpi->war ||
+	  msstatus != clientThingyStatus[i])
+      {
+	dpi->war = missile->ms_war;
+	clientThingyStatus[i] = msstatus;
+	sendClientPacket((struct player_spacket *) dpi);
+      }
+      if (dp->x != htonl(missile->ms_x) ||
+	  dp->y != htonl(missile->ms_y))
+      {
+	dp->x = htonl(missile->ms_x);
+	dp->y = htonl(missile->ms_y);
+	/* printf("missile at %d,%d\n", dp->x, dp->y); */
+	sendClientPacket((struct player_spacket *) dp);
+      }
+    }
+    else
+    {				/* Someone else's missile... */
+      if (msstatus == TFREE ||
+	  missile->ms_y > me->p_y + SCALE * WINSIDE / 2 ||
+	  missile->ms_x > me->p_x + SCALE * WINSIDE / 2 ||
+	  missile->ms_x < me->p_x - SCALE * WINSIDE / 2 ||
+	  missile->ms_y < me->p_y - SCALE * WINSIDE / 2)
+      {
+	if (msstatus == TFREE && clientThingyStatus[i] == TEXPLODE)
+	{
+	  clientThingyStatus[i] = TFREE;
+	  continue;
+	}
+	if (clientThingyStatus[i] != TFREE)
+	{
+	  clientThingyStatus[i] = TFREE;
+	  dpi->shape = htons(SHP_BLANK);
+	  sendClientPacket((struct player_spacket *) dpi);
+	}
+      }
+      else
+      {				/* in view */
+	if (dp->x != htonl(missile->ms_x) ||
+	    dp->y != htonl(missile->ms_y))
+	{
+	  dp->x = htonl(missile->ms_x);
+	  dp->y = htonl(missile->ms_y);
+	  sendClientPacket((struct player_spacket *) dp);
+	}
+	if (msstatus != clientThingyStatus[i] ||
+	    (missile->ms_war & me->p_team) != dpi->war)
+	{
+	  /* Let the client fade away the explosion on its own */
+	  dpi->war = missile->ms_war & me->p_team;
+	  clientThingyStatus[i] = msstatus;
+	  sendClientPacket((struct player_spacket *) dpi);
+	}
+      }
+    }
+  }
+}
+
+static void
+fill_thingy_info_packet(thing, packet)
+  struct thingy *thing;
+  struct thingy_info_spacket *packet;
+{
+  switch (thing->type)
+  {
+   case TT_NONE:
+    packet->war = 0;
+    packet->shape = htons(SHP_BLANK);
+    packet->owner = 0;
+    break;
+   case TT_WARP_BEACON:
+    packet->war = 0;
+    if (thing->u.wbeacon.owner == me->p_team)
+    {
+      packet->shape = htons(SHP_WARP_BEACON);
+      packet->owner = htons(thing->u.wbeacon.owner);
+    }
+    else
+    {
+      packet->shape = htons(SHP_BLANK);
+      packet->owner = 0;
+    }
+    break;
+   default:
+    printf("Unknown thingy type: %d\n", (int) thing->type);
+    break;
+  }
+}
+
+static void
+fill_thingy_packet(thing, packet)
+  struct thingy *thing;
+  struct thingy_spacket *packet;
+{
+  switch (thing->type)
+  {
+   case TT_NONE:
+    packet->dir = 0;
+    packet->x = packet->y = htonl(0);
+    break;
+   case TT_WARP_BEACON:
+    packet->dir = 0;
+    if (thing->u.wbeacon.owner == me->p_team)
+    {
+      packet->x = htonl(thing->u.wbeacon.x);
+      packet->y = htonl(thing->u.wbeacon.y);
+    }
+    else
+    {
+      packet->x = packet->y = htonl(0);
+    }
+    break;
+   default:
+    printf("Unknown thingy type: %d\n", (int) thing->type);
+    break;
+  }
+}
+
+void
+updateThingies()
+{
+  struct thingy *thing;
+  struct thingy_info_spacket *tip;
+  struct thingy_spacket *tp;
+  int i;
+
+  for (i = 0; i < NGTHINGIES; i++)
+  {
+    struct thingy_info_spacket ti1;
+    struct thingy_spacket t2;
+
+    thing = &thingies[i];
+    tip = &clientThingysInfo[i + MAXPLAYER * NPTHINGIES];
+    tp = &clientThingys[i + MAXPLAYER * NPTHINGIES];
+
+    ti1.type = SP_THINGY_INFO;
+    ti1.tnum = htons(i + MAXPLAYER * NPTHINGIES);
+    fill_thingy_info_packet(thing, &ti1);
+
+    if (0 != memcmp((char *) tip, (char *) &ti1, sizeof(ti1)))
+    {
+      memcpy(tip, &ti1, sizeof(ti1));
+      sendClientPacket((struct player_spacket *) tip);
+    }
+
+    if (tip->shape != htons(SHP_BLANK))
+    {
+      t2.type = SP_THINGY;
+      t2.tnum = htons(i + MAXPLAYER * NPTHINGIES);
+      fill_thingy_packet(thing, &t2);
+
+      if (0 != memcmp(tp, &t2, sizeof(t2)))
+      {
+	memcpy(tp, &t2, sizeof(t2));
+	sendClientPacket((struct player_spacket *) tp);
+      }
+    }
+  }
+
+}
+
+void
+updatePlasmas()
+{
+  register struct plasmatorp *torp;
+  register int i;
+  register struct plasma_info_spacket *tpi;
+  register struct plasma_spacket *tp;
+
+  for (i = 0, torp = plasmatorps, tpi = clientPlasmasInfo, tp = clientPlasmas;
+       i < MAXPLAYER * MAXPLASMA;
+       i++, torp++, tpi++, tp++)
+  {
+    if (torp->pt_owner == me->p_no)
+    {
+      if (torp->pt_war != tpi->war ||
+	  torp->pt_status != tpi->status)
+      {
+	tpi->type = SP_PLASMA_INFO;
+	tpi->war = torp->pt_war;
+	tpi->status = torp->pt_status;
+	tpi->pnum = htons(i);
+	sendClientPacket((struct player_spacket *) tpi);
+      }
+      if (tp->x != htonl(torp->pt_x) ||
+	  tp->y != htonl(torp->pt_y))
+      {
+	tp->type = SP_PLASMA;
+	tp->x = htonl(torp->pt_x);
+	tp->y = htonl(torp->pt_y);
+	tp->pnum = htons(i);
+	sendClientPacket((struct player_spacket *) tp);
+      }
+    }
+    else
+    {				/* Someone else's torp... */
+      enum torp_status_e ptstatus = torp->pt_status;
+
+#ifdef LEAGUE_SUPPORT
+      if (status2->paused &&
+	  players[torp->pt_owner].p_team != me->p_team)
+	ptstatus = TFREE;	/* enemy torps are invisible during game
+				 * pause */
+#endif
+      if (torp->pt_y > me->p_y + SCALE * WINSIDE / 2 ||
+	  torp->pt_x > me->p_x + SCALE * WINSIDE / 2 ||
+	  torp->pt_x < me->p_x - SCALE * WINSIDE / 2 ||
+	  torp->pt_y < me->p_y - SCALE * WINSIDE / 2 ||
+	  ptstatus == PTFREE)
+      {
+	if (ptstatus == PTFREE && tpi->status == PTEXPLODE)
+	{
+	  tpi->status = PTFREE;
+	  continue;
+	}
+	if (tpi->status != PTFREE)
+	{
+	  tpi->status = PTFREE;
+	  tpi->pnum = htons(i);
+	  tpi->type = SP_PLASMA_INFO;
+	  sendClientPacket((struct player_spacket *) tpi);
+	}
+      }
+      else
+      {				/* in view */
+	/* Send torp (we assume it moved) */
+	tp->x = htonl(torp->pt_x);
+	tp->y = htonl(torp->pt_y);
+	tp->pnum = htons(i);
+	tp->type = SP_PLASMA;
+	sendClientPacket((struct player_spacket *) tp);
+	if (ptstatus != tpi->status ||
+	    (torp->pt_war & me->p_team) != tpi->war)
+	{
+	  tpi->war = torp->pt_war & me->p_team;
+	  tpi->type = SP_PLASMA_INFO;
+	  tpi->pnum = htons(i);
+	  tpi->status = ptstatus;
+	  sendClientPacket((struct player_spacket *) tpi);
+	}
+      }
+    }
+  }
+}
+
+void
+updatePhasers()
+{
+  register int i;
+  register struct phaser_spacket *ph;
+  register struct phaser *phase;
+  register struct player *pl;
+
+  for (i = 0, ph = clientPhasers, phase = phasers, pl = players;
+       i < MAXPLAYER; i++, ph++, phase++, pl++)
+  {
+    if (pl->p_y > me->p_y + SCALE * WINSIDE / 2 ||
+	pl->p_x > me->p_x + SCALE * WINSIDE / 2 ||
+	pl->p_x < me->p_x - SCALE * WINSIDE / 2 ||
+	pl->p_y < me->p_y - SCALE * WINSIDE / 2)
+    {
+      if (ph->status != PHFREE)
+      {
+	ph->pnum = i;
+	ph->type = SP_PHASER;
+	ph->status = PHFREE;
+	sendClientPacket((struct player_spacket *) ph);
+      }
+    }
+    else
+    {
+      if (phase->ph_status == PHHIT)
+      {
+	mustUpdate[phase->ph_target] = 1;
+      }
+      if (ph->status != phase->ph_status ||
+	  ph->dir != phase->ph_dir ||
+	  ph->target != htonl(phase->ph_target))
+      {
+	ph->pnum = i;
+	ph->type = SP_PHASER;
+	ph->status = phase->ph_status;
+	ph->dir = phase->ph_dir;
+	ph->x = htonl(phase->ph_x);
+	ph->y = htonl(phase->ph_y);
+	ph->target = htonl(phase->ph_target);
+	sendClientPacket((struct player_spacket *) ph);
+      }
+    }
+  }
+}
+
+
+#define PLFLAGMASK (PLRESMASK|PLATMASK|PLSURMASK|PLPARADISE|PLTYPEMASK)
+
+void
+updatePlanets()
+{
+  register int i;
+  register struct planet *plan;
+  register struct planet_loc_spacket *pll;
+#if 0
+  register struct planet_spacket *mspl;
+#endif
+  register struct planet_spacket2 *pl;
+  int dx, dy;
+  int d2x, d2y;
+  char *name;
+
+  for (i = 0, pl = clientPlanets2, plan = planets, pll = clientPlanetLocs;
+       i < MAXPLANETS;
+       i++, pl++, plan++, pll++)
+  {
+    /*
+     * Send him info about him not having info if he doesn't but thinks he
+     * does. Also send him info on every fifth cycle if the planet needs to
+     * be redrawn.
+     */
+    if (((plan->pl_hinfo & me->p_team) == 0) && (pl->info & me->p_team))
+    {
+      pl->type = SP_PLANET2;
+      pl->pnum = i;
+      pl->info = 0;
+      pl->flags = PLPARADISE;
+      sendClientPacket((struct player_spacket *) pl);
+    }
+    else
+    {
+      struct teaminfo temp, *ptr;
+      if (configvals->durablescouting)
+      {
+	temp.owner = plan->pl_owner;
+	temp.armies = plan->pl_armies;
+	temp.flags = plan->pl_flags;
+	temp.timestamp = status->clock;
+	ptr = &temp;
+      }
+      else
+	ptr = &plan->pl_tinfo[me->p_team];
+
+      if (pl->info != plan->pl_hinfo ||
+	  pl->armies != htonl(ptr->armies) ||
+	  pl->owner != ptr->owner ||
+	  pl->flags != htonl(ptr->flags & PLFLAGMASK)
+	  || ((pl->timestamp != htonl(ptr->timestamp))
+	      && (me->p_team != plan->pl_owner)))
+      {
+	pl->type = SP_PLANET2;
+	pl->pnum = (char) i;
+	pl->info = (char) plan->pl_hinfo;
+	pl->flags = htonl(ptr->flags & PLFLAGMASK);
+	pl->armies = htonl(ptr->armies);
+	pl->owner = (char) ptr->owner;
+	pl->timestamp = htonl(ptr->timestamp);
+	sendClientPacket((struct player_spacket *) pl);
+      }
+    }
+    /* Assume that the planet only needs to be updated once... */
+
+    /* Odd, changes in pl_y not supported.  5/31/92 TC */
+
+    dx = ntohl(pll->x) - plan->pl_x;
+    if (dx < 0)
+      dx = -dx;
+    dy = ntohl(pll->y) - plan->pl_y;
+    if (dy < 0)
+      dy = -dy;
+
+    d2x = plan->pl_x - me->p_x;
+    d2y = plan->pl_y - me->p_y;
+    if (d2x < 0)
+      d2x = -d2x;
+    if (d2y < 0)
+      d2y = -d2y;
+
+    if (1 || plan->pl_hinfo & me->p_team)
+      name = plan->pl_name;
+    else
+      name = "   ";
+    /*
+     * if ((pll->x != htonl(plan->pl_x)) || (pll->y != htonl(plan->pl_y))) {
+     */
+    if (strcmp(pll->name, name) ||
+	((dx > 400 || dy > 400) ||
+	 ((dx >= 20 || dy >= 20) && (d2x < 10000 && d2y < 10000))))
+    {
+      pll->x = htonl(plan->pl_x);
+      pll->y = htonl(plan->pl_y);
+      pll->pnum = i;
+      if (plan->pl_system == 0)
+	pll->pad2 = 255;
+      else
+	pll->pad2 = (char) stars[plan->pl_system];
+      strcpy(pll->name, name);
+      pll->type = SP_PLANET_LOC;
+      sendClientPacket((struct player_spacket *) pll);
+    }
+  }
+}
+
+void
+updateMessages()
+{
+  int i;
+  struct message *cur;
+  struct mesg_spacket msg;
+
+  for (i = msgCurrent; i != (mctl->mc_current + 1) % MAXMESSAGE; i = (i + 1) % MAXMESSAGE)
+  {
+    if (i == MAXMESSAGE)
+      i = 0;
+    cur = &messages[i];
+
+    if (cur->m_flags & MVALID &&
+	(cur->m_flags & MALL ||
+	 (cur->m_flags & MTEAM && cur->m_recpt == me->p_team) ||
+	 (cur->m_flags & MINDIV && cur->m_recpt == me->p_no) ||
+	 (cur->m_flags & MGOD && cur->m_from == me->p_no)))
+    {
+      msg.type = SP_MESSAGE;
+      strncpy(msg.mesg, cur->m_data, 80);
+      msg.mesg[79] = '\0';
+      msg.m_flags = cur->m_flags;
+      msg.m_recpt = cur->m_recpt;
+      msg.m_from = cur->m_from;
+
+      if ((cur->m_from < 0)
+	  || (cur->m_from > MAXPLAYER)
+	  || (cur->m_flags & MGOD && cur->m_from == me->p_no)
+	  || (cur->m_flags & MALL && !(ignored[cur->m_from] & MALL))
+	  || (cur->m_flags & MTEAM && !(ignored[cur->m_from] & MTEAM)))
+	sendClientPacket((struct player_spacket *) & msg);
+      else if (cur->m_flags & MINDIV)
+      {
+
+	/* session stats now parsed here.  parseQuery == true */
+	/* means eat message 4/17/92 TC */
+
+	if (!parseQuery(&msg))
+	  if (ignored[cur->m_from] & MINDIV)
+	    bounce("That player is currently ignoring you.",
+		   cur->m_from);
+	  else
+	    sendClientPacket((struct player_spacket *) & msg);
+      }
+    }
+    msgCurrent = (msgCurrent + 1) % MAXMESSAGE;
+  }
+}
+
+/* Asteroid/Nebulae socket code (5/16/95 rpg) */
+
+#define DIM (MAX_GWIDTH/TGRID_GRANULARITY)
+
+void
+updateTerrain()
+{
+  int i;
+  int j, maxfor;
+  int status;
+  int npkts;
+  struct terrain_packet2 tpkt;
+  struct terrain_info_packet2 tinfo_pkt;
+  unsigned long olen = DIM * DIM, dlen = DIM * DIM / 1000 + DIM * DIM + 13;
+#if defined(T_DIAG) || defined(T_DIAG2)
+  char buf[80];
+#endif
+  unsigned char origBuf[DIM * DIM];
+  unsigned char gzipBuf[DIM * DIM / 1000 +
+			    DIM * DIM + 13];
+  /*
+   * Don't ask me.  The compression libs need (original size + 0.1% + 12
+   * bytes).
+   */
+  /*
+   * Note - this will have to be RADICALLY changed if alt1/alt2 are sent as
+   * well.
+   */
+
+  /* check to see if client can handle the terrain data first */
+  if (F_terrain)
+  {
+    if (galaxyValid[me->p_no])
+      return;
+
+#if defined(T_DIAG) || defined(T_DIAG2)
+    {
+      char buf[80];
+      sprintf(buf, "pno: %d gIsense: %d", me->p_no, galaxyValid[me->p_no]);
+      pmessage(buf, 0, MALL, MSERVA);
+    }
+#endif
+    galaxyValid[me->p_no] = 1;
+    /* Send initial packet. */
+    tinfo_pkt.type = SP_TERRAIN_INFO2;
+    tinfo_pkt.xdim = htons(DIM);
+    tinfo_pkt.ydim = htons(DIM);
+    sendClientPacket((struct player_spacket *) & tinfo_pkt);
+    for (i = 0; i < DIM * DIM; i++)
+    {
+      origBuf[i] = terrain_grid[i].types;	/* pack types field into
+						 * array */
+    }
+#if defined(T_DIAG) || defined(T_DIAG2)
+    status = compress(gzipBuf, &dlen, origBuf, olen);
+    if (status != Z_OK)
+    {
+      pmessage("TERRAIN: Cannot gzip terrain grid.", 0, MALL, MSERVA);
+      return;
+    }
+    else
+    {
+      sprintf(buf, "TERRAIN: Original length %d, compressed length %d", DIM * DIM, dlen);
+      pmessage(buf, 0, MALL, MSERVA);
+    }
+#else
+    compress(gzipBuf, &dlen, origBuf, olen);
+#endif
+    npkts = (dlen >> LOG2NTERRAIN);
+    if (dlen & TERRAIN_MASK)
+    {
+      npkts++;			/* require a partial packet */
+    }
+    for (i = 1; i <= npkts; i++)
+    {
+      tpkt.type = SP_TERRAIN2;
+      tpkt.sequence = (unsigned char) i;
+      tpkt.total_pkts = (unsigned char) npkts;
+      if (i < npkts)
+      {
+	maxfor = tpkt.length = NTERRAIN;
+      }
+      else
+      {
+	maxfor = tpkt.length = (dlen & TERRAIN_MASK);
+      }
+      for (j = 0; j < maxfor; j++)
+      {
+	tpkt.terrain_type[j] = gzipBuf[((i - 1) << LOG2NTERRAIN) + j];
+      }
+      /* ok, packet is filled in, send it */
+#ifdef T_DIAG2
+      sprintf(buf, "Sending terrain packet %d of %d", tpkt.sequence, tpkt.total_pkts);
+      pmessage(buf, 0, MALL, MSERVA);
+#endif
+      sendClientPacket((struct player_spacket *) & tpkt);
+    }
+  }
+#ifdef FEATURE_DIAG
+  else
+  {
+    pmessage("Mis-timed terrain data (F_terrain = 0)!", 0, MALL, MSERVA);
+  }
+#endif
+}
+
+void
+updateMOTD()
+{
+  static int spinner = 0;
+
+  if (--spinner < 0)
+  {
+    static struct stat oldstat;
+    static int firsttime = 1;
+
+    char *path;
+    struct stat newstat;
+    struct obvious_packet pkt;
+
+    spinner = 10;
+
+    if (!firsttime)
+    {
+      path = build_path(MOTD);
+      stat(path, &newstat);
+      if (newstat.st_ino == oldstat.st_ino &&
+	  newstat.st_mtime == oldstat.st_mtime)
+	return;
+      oldstat.st_ino = newstat.st_ino;
+      oldstat.st_mtime = newstat.st_mtime;
+
+      pkt.type = SP_NEW_MOTD;
+      sendClientPacket((struct player_spacket *) & pkt);
+    }
+    else
+    {
+      sendMotd();		/* can't build_path before this */
+      path = build_path(MOTD);
+      stat(path, &oldstat);
+      /* printf("%s: %d, %d\n", path, oldstat.st_ino, oldstat.st_mtime); */
+      firsttime = 0;
+    }
+  }
+}
+
+void
+sendQueuePacket(pos)
+  short int pos;
+{
+  struct queue_spacket qPacket;
+
+  qPacket.type = SP_QUEUE;
+  qPacket.pos = htons(pos);
+  sendClientPacket((struct player_spacket *) & qPacket);
+  flushSockBuf();
+}
+
+void
+sendClientPacket(packet)
+  struct player_spacket *packet;
+{
+  sendClientSizedPacket(packet, -1);
+}
+
+void
+sendClientSizedPacket(packet, size)
+/* Pick a random type for the packet */
+  struct player_spacket *packet;
+  int size;
+{
+  int orig_type;
+  int issc;
+  static int oldStatus = POUTFIT;
+
+#if 0
+  if (blk_metaserver)
+#endif
+#ifdef SHOW_PACKETS
+  {
+    FILE *logfile;
+    char *paths;
+    paths = build_path("logs/metaserver.log");
+    logfile = fopen(paths, "a");
+    if (logfile)
+    {
+      fprintf(logfile, "Sending packet type %d\n", (int) packet->type);
+      fclose(logfile);
+    }
+
+  }
+#endif
+
+#ifdef T_DIAG2
+  if ((packet->type == SP_TERRAIN2) || (packet->type == SP_TERRAIN_INFO2))
+  {
+    pmessage("Sending TERRAIN packet\n", 0, MALL, MSERVA);
+  }
+#endif
+
+  orig_type = packet->type;
+#if 0
+  packet->type &= ~(0x40 | 0x80);	/* clear special flags */
+#else
+  packet->type &= (char) 0x3f;	/* above doesn't work? 4/18/92 TC */
+#endif
+#ifdef MAYBE
+  /*
+   * If we're dead, dying, or just born, we definitely want the transmission
+   * to get through (otherwise we can get stuck).  I don't think this will be
+   * a problem for anybody, though it might hang for a bit if the TCP
+   * connection is bad.
+   */
+  /* Okay, now I'm not so sure.  Whatever. */
+  if (oldStatus != PALIVE || (me != NULL && me->p_status != PALIVE))
+    orig_type = packet->type | 0x80;	/* pretend it's critical */
+#endif
+
+  /* if we're not given the size, calculate it */
+  if (size < 0)
+  {
+    if (size_of_spacket(packet) == 0)
+    {
+      printf("Attempt to send strange packet %d\n", packet->type);
+      return;
+    }
+    size = size_of_spacket(packet);
+  }
+  else
+  {
+    /* pad to 32-bits */
+    size = ((size - 1) / 4 + 1) * 4;
+  }
+
+  packetsSent[packet->type]++;
+
+
+  if (commMode == COMM_TCP
+      || (commMode == COMM_UDP && udpMode == MODE_TCP))
+  {
+    switch (orig_type)
+    {
+     case SP_MOTD:
+     case SP_MOTD_PIC:
+      /* these can afford to be delayed */
+      sendTCPdeferred((void *) packet, size);
+      break;
+
+     default:
+      /* business as usual, TCP */
+      sendTCPbuffered((void *) packet, size);
+      break;
+    }
+  }
+  else
+  {
+    /*
+     * do UDP stuff unless it's a "critical" packet (note that both kinds get
+     * a sequence number appended) (FIX)
+     */
+    issc = 0;
+    switch (orig_type)
+    {
+     case SP_KILLS:
+     case SP_TORP_INFO:
+     case SP_THINGY_INFO:
+     case SP_PHASER:
+     case SP_PLASMA_INFO:
+     case SP_YOU | 0x40:	/* ??? what is this? */
+     case SP_STATUS:
+     case SP_STATUS2:
+     case SP_PLANET:
+     case SP_PLANET2:
+     case SP_FLAGS:
+     case SP_HOSTILE:
+      /*
+       * these are semi-critical; flag as semi-critical and fall through
+       */
+      issc = 1;
+
+     case SP_PLAYER:
+     case SP_TORP:
+#ifdef SHORT_PACKETS
+     case SP_S_TORP:
+     case SP_S_8_TORP:
+#endif
+     case SP_THINGY:
+     case SP_YOU:
+     case SP_PLASMA:
+     case SP_STATS:
+     case SP_STATS2:
+      /* case SP_SCAN: */
+     case SP_PING:
+     case SP_UDP_REPLY:	/* only reply when COMM_UDP is SWITCH_VERIFY */
+      /* these are non-critical updates; send them via UDP */
+      V_UDPDIAG(("Sending type %d\n", packet->type));
+      packets_sent++;
+      sendUDPbuffered(issc, (void *) packet, size);
+      break;
+
+     case SP_MOTD:
+     case SP_MOTD_PIC:
+      sendTCPdeferred((void *) packet, size);
+      break;
+
+     default:
+      sendTCPbuffered((void *) packet, size);
+      break;
+    }
+  }
+
+  if (me != NULL)
+    oldStatus = me->p_status;
+}
+
+/*
+ * flushSockBuf, socketPause, socketWait were here
+ */
+
+/* Find out if client has any requests */
+int
+readFromClient()
+{
+  struct timeval timeout;
+  fd_set readfds, writefds;
+  int retval = 0;
+
+  if (clientDead)
+    return (0);
+
+  timeout.tv_sec = 0;
+  timeout.tv_usec = 0;
+
+  build_select_masks(&readfds, &writefds);
+
+  if (select(32, &readfds, &writefds, (fd_set *) 0, &timeout) != 0)
+  {
+    /* Read info from the xtrek client */
+    if (FD_ISSET(sock, &readfds))
+    {
+      retval += doRead(sock);
+    }
+    if (udpSock >= 0 && FD_ISSET(udpSock, &readfds))
+    {
+      V_UDPDIAG(("Activity on UDP socket\n"));
+      retval += doRead(udpSock);
+    }
+    if (retval == 0 &&		/* no other traffic */
+	FD_ISSET(sock, &writefds))
+    {
+      flushDeferred();		/* we have an eye in the packet hurricane */
+    }
+  }
+  return (retval != 0);		/* convert to 1/0 */
+}
+
+static int
+input_allowed(packettype)
+  int packettype;
+{
+  switch (packettype)
+  {
+   case CP_MESSAGE:
+   case CP_SOCKET:
+   case CP_OPTIONS:
+   case CP_BYE:
+   case CP_UPDATES:
+   case CP_RESETSTATS:
+   case CP_RESERVED:
+   case CP_RSA_KEY:
+   case CP_ASK_MOTD:
+   case CP_PING_RESPONSE:
+   case CP_UDP_REQ:
+#ifdef FEATURE
+   case CP_FEATURE:
+#endif
+#ifdef SHORT_PACKETS
+   case CP_S_MESSAGE:
+#endif
+    return 1;
+   default:
+    if (!me)
+      return;
+
+    if (me->p_status == PTQUEUE)
+      return (packettype == CP_OUTFIT
+	);
+    else if (me->p_status == POBSERVE)
+      return (packettype == CP_QUIT
+	      || packettype == CP_PLANLOCK
+	      || packettype == CP_PLAYLOCK
+	      || packettype == CP_SCAN
+	      || packettype == CP_SEQUENCE	/* whatever this is */
+	);
+
+    if (inputMask >= 0 && inputMask != packettype)
+      return 0;
+    if (me == NULL)
+      return 1;
+    if (!(me->p_flags & (PFWAR | PFREFITTING)))
+      return 1;
+
+    return 0;
+  }
+}
+
+static int rsock;		/* ping stuff */
+
+/* ripped out of above routine */
+int
+doRead(asock)
+  int asock;
+{
+  struct timeval timeout;
+  /* int readfds; */
+  fd_set readfds;
+  char buf[BUFSIZ * 2];
+  char *bufptr;
+  int size;
+  int count;
+  int temp;
+
+  rsock = asock;		/* need the socket in the ping handler
+				 * routine */
+
+  timeout.tv_sec = 0;
+  timeout.tv_usec = 0;
+  /* readfds = 1<<asock; */
+  FD_ZERO(&readfds);
+  FD_SET(asock, &readfds);
+  /* Read info from the xtrek server */
+  count = read(asock, buf, BUFSIZ * 2);
+  if (count <= 0)
+  {
+#if DEBUG
+    /* (this happens when the client hits 'Q') */
+    fprintf(stderr, "1) read() failed in doRead (%d, error %d)\n",
+	    count, errno);
+    fprintf(stderr, "asock=%d, sock=%d\n", asock, sock);
+#endif
+    if (asock == udpSock)
+    {
+      if (errno == ECONNREFUSED)
+      {
+	struct sockaddr_in addr;
+
+	UDPDIAG(("Hiccup(%d)!  Reconnecting\n", errno));
+	addr.sin_addr.s_addr = remoteaddr;
+	addr.sin_port = htons(udpClientPort);
+	addr.sin_family = AF_INET;
+	if (connect(udpSock, (struct sockaddr *) & addr, sizeof(addr)) < 0)
+	{
+	  perror("hiccup connect");
+	  UDPDIAG(("Unable to reconnect\n"));
+	  /* and fall through to disconnect */
+	}
+	else
+	{
+	  UDPDIAG(("Reconnect successful\n"));
+	  return (0);
+	}
+      }
+      UDPDIAG(("*** UDP disconnected (res=%d, err=%d)\n",
+	       count, errno));
+      printUdpInfo();
+      closeUdpConn();
+      commMode = COMM_TCP;
+      return (0);
+    }
+    clientDead = 1;
+    return (0);
+  }
+  bufptr = buf;
+  while (bufptr < buf + count)
+  {
+    if (*bufptr < 1 ||
+	(unsigned char) *bufptr > NUM_PACKETS ||
+	size_of_cpacket((void *) bufptr) == 0)
+    {
+      printf("Unknown packet type: %d, aborting...\n", *bufptr);
+      return (0);
+    }
+    size = size_of_cpacket(bufptr);
+    while (size > count + (buf - bufptr))
+    {
+      /*
+       * We wait for up to twenty seconds for rest of packet. If we don't get
+       * it, we assume the client died.
+       */
+      timeout.tv_sec = 20;
+      timeout.tv_usec = 0;
+      /* readfds=1<<asock; */
+      FD_ZERO(&readfds);
+      FD_SET(asock, &readfds);
+      if (select(32, &readfds, 0, 0, &timeout) == 0)
+      {
+	logmessage("Died while waiting for packet...");
+	fprintf(stderr, "1a) read() failed (%d, error %d)\n",
+		count, errno);
+	clientDead = 1;
+	return (0);
+      }
+      temp = read(asock, buf + count, size - (count + (buf - bufptr)));
+      if (temp <= 0)
+      {
+	if (errno != EINTR)
+	{
+	  sprintf(buf, "Died in second read(), return=%d", temp);
+	  logmessage(buf);
+	  fprintf(stderr, "2) read() failed (%d, error %d)\n",
+		  count, errno);
+	  clientDead = 1;
+	  return (0);
+	}
+      }
+      else
+	count += temp;
+    }
+    /*
+     * Check to see if the handler is there and the request is legal. The
+     * code is a little ugly, but it isn't too bad to worry about yet.
+     */
+#if 0
+    {
+      FILE *logfile;
+      char *paths;
+      if (blk_metaserver)
+      {
+	paths = build_path("logs/metaserver.log");
+	logfile = fopen(paths, "a");
+	if (logfile)
+	{
+	  fprintf(logfile, "Receiving packet type %d\n", (int) *bufptr);
+	  fclose(logfile);
+	}
+      }
+    }
+#endif
+    packetsReceived[(unsigned char) *bufptr]++;
+
+    if (asock == udpSock)
+      packets_received++;
+
+    if (handlers[(unsigned char) *bufptr].handler != NULL)
+    {
+      if (input_allowed(*bufptr))
+      {
+	if (me && me->p_flags & PFSELFDEST
+	    && *bufptr != CP_PING_RESPONSE)
+	{
+	  me->p_flags &= ~PFSELFDEST;
+	  warning("Self Destruct has been canceled");
+	}
+	(*(handlers[(unsigned char) *bufptr].handler)) (bufptr);
+      }
+      /* Otherwise we ignore the request */
+    }
+    else
+    {
+      printf("Handler for packet %d not installed...\n", *bufptr);
+    }
+    bufptr += size;
+    if (bufptr > buf + BUFSIZ)
+    {
+      memcpy(buf, buf + BUFSIZ, BUFSIZ);
+      if (count == BUFSIZ * 2)
+      {
+	/* readfds = 1<<asock; */
+	FD_ZERO(&readfds);
+	FD_SET(asock, &readfds);
+	if (select(32, &readfds, 0, 0, &timeout))
+	{
+	  temp = read(asock, buf + BUFSIZ, BUFSIZ);
+	  count = BUFSIZ + temp;
+	  if (temp <= 0)
+	  {
+	    sprintf(buf, "Died in third read(), return=%d", temp);
+	    fprintf(stderr, "3) read() failed (%d, error %d)\n",
+		    count, errno);
+	    logmessage(buf);
+	    clientDead = 1;
+	    return (0);
+	  }
+	}
+	else
+	{
+	  count = BUFSIZ;
+	}
+      }
+      else
+      {
+	count -= BUFSIZ;
+      }
+      bufptr -= BUFSIZ;
+    }
+  }
+  return (1);
+}
+
+void
+handleTorpReq(packet)
+  struct torp_cpacket *packet;
+{
+  ntorp((CARD8) packet->dir, (int) TMOVE);
+}
+
+void
+handlePhasReq(packet)
+  struct phaser_cpacket *packet;
+{
+  phaser(packet->dir);
+}
+
+void
+handleSpeedReq(packet)
+  struct speed_cpacket *packet;
+{
+  set_speed(packet->speed, 1);
+}
+
+void
+handleDirReq(packet)
+  struct dir_cpacket *packet;
+{
+  me->p_flags &= ~(PFPLOCK | PFPLLOCK);
+  set_course(packet->dir);
+}
+
+void
+handleShieldReq(packet)
+  struct shield_cpacket *packet;
+{
+  if (packet->state)
+  {
+    shield_up();
+  }
+  else
+  {
+    shield_down();
+  }
+}
+
+void
+handleRepairReq(packet)
+  struct repair_cpacket *packet;
+{
+  if (packet->state)
+  {
+    repair();
+  }
+  else
+  {
+    me->p_flags &= ~(PFREPAIR);
+  }
+}
+
+void
+handleOrbitReq(packet)
+  struct orbit_cpacket *packet;
+{
+  if (packet->state)
+  {
+    orbit();
+  }
+  else
+  {
+    me->p_flags &= ~PFORBIT;
+#if 0
+    planets[me->p_planet].pl_torbit &= ~me->p_team;
+#endif
+    if (me->p_flags & PFDOCK)
+    {
+      if (players[me->p_docked].p_speed > 4)
+      {
+	warning("It's unsafe to disengage from bases while over warp 4.");
+	return;
+      }
+      else
+	undock_player(me);
+    }
+  }
+}
+
+/*-----------------------------PRACTICE_ROBOT-----------------------------*/
+/*
+ * Send in a practice robot.  You can only bring i a practice robot if no
+ * other players are in the game.
+ */
+
+static void
+practice_robo()
+{
+  char *paths;			/* to hold dot dir path */
+  char *arg1;
+  register int i;		/* looping var */
+  register struct player *j;	/* to point to players */
+  static struct timeval space = {0, 0};
+
+  if (!temporally_spaced(&space, 1000000))	/* damn auto-repeating... */
+    return;
+
+  for (i = 0, j = &players[i]; i < MAXPLAYER; i++, j++)
+  {
+    if (j->p_status != PALIVE)	/* if payer not alive, that's ok */
+      continue;
+    if (j == me)		/* ignore myself */
+      continue;
+    warning("Can't send in practice robot with other players in the game.");
+    return;			/* another player discovered--out of here */
+  }
+
+  if (fork() == 0)
+  {				/* do if fork successful */
+    (void) r_signal(SIGALRM, SIG_DFL);
+    (void) close(0);
+    (void) close(1);
+    (void) close(2);
+    switch (me->p_team)
+    {				/* decide which teaem robot is on */
+     case FED:
+      arg1 = "-Tf";		/* fed option */
+      break;
+     case ROM:
+      arg1 = "-Tr";		/* rom option */
+      break;
+     case KLI:
+      arg1 = "-Tk";		/* klingon option */
+      break;
+     case ORI:
+      arg1 = "-To";		/* orion option */
+      break;
+     default:
+      arg1 = "-Ti";		/* in case something screwy happens */
+      break;
+    }
+
+    paths = build_path(ROBOT);
+
+    execl(paths, "robot", arg1, "-p", "-f", "-h", 0);
+    _exit(1);			/* failure :(  died at birth */
+  }
+}
+
+/*--------------------------------------------------------------------------*/
+
+/* ARGSUSED */
+void
+handlePractrReq(packet)
+  struct practr_cpacket *packet;
+{
+  practice_robo();
+}
+
+void
+handleBombReq(packet)
+  struct bomb_cpacket *packet;
+{
+  if (packet->state)
+  {
+    bomb_planet();
+  }
+  else
+  {
+    me->p_flags &= ~(PFBOMB);
+  }
+}
+
+void
+handleBeamReq(packet)
+  struct beam_cpacket *packet;
+{
+  if (packet->state == 1)
+  {
+    beam_up();
+  }
+  else if (packet->state)
+  {
+    beam_down();
+  }
+  else
+  {
+    me->p_flags &= ~(PFBEAMUP | PFBEAMDOWN);
+  }
+}
+
+void
+handleCloakReq(packet)
+  struct cloak_cpacket *packet;
+{
+  if (packet->state)
+  {
+    cloak_on();
+  }
+  else
+  {
+    cloak_off();
+  }
+}
+
+/* ARGSUSED */
+void
+handleDetTReq(packet)
+  struct det_torps_cpacket *packet;
+{
+  detothers();
+}
+
+/* ARGSUSED */
+void
+handleCopilotReq(packet)
+  struct copilot_cpacket *packet;
+{
+  /*
+   * Unsupported... if (packet->state) { me->p_flags |= PFCOPILOT; } else {
+   * me->p_flags &= ~PFCOPILOT; }
+   */
+}
+
+void
+handleOutfit(packet)
+  struct outfit_cpacket *packet;
+{
+  shipPick = packet->ship;
+  teamPick = packet->team;
+}
+
+void
+sendPickokPacket(state)
+  int state;
+{
+  struct pickok_spacket pickPack;
+
+  pickPack.type = SP_PICKOK;
+  pickPack.state = state;
+  sendClientPacket((struct player_spacket *) & pickPack);
+}
+
+void
+handleLoginReq(packet)
+  struct login_cpacket *packet;
+{
+  if (packet->pad2 == 0x69)
+  {
+    if (packet->pad3 == 0x42)
+      blk_flag = 1;		/* added 1/19/93 KAO */
+    if (packet->pad3 == 0x43)
+      blk_flag = 2;
+  }
+  strncpy(namePick, packet->name, 16);
+  namePick[15] = 0;
+  strncpy(passPick, packet->password, 16);
+  passPick[15] = 0;
+  /* Is this a name query or a login? */
+  if (packet->query)
+  {
+    passPick[15] = 1;
+  }
+  strncpy(login, packet->login, 16);
+  login[15] = 0;
+}
+
+void
+sendClientLogin(stats)
+  struct stats *stats;
+{
+  struct login_spacket logPacket;
+  logPacket.pad2 = 69;
+  if (configvals->galaxygenerator == 4)
+    logPacket.pad3 = 88;
+  else
+    logPacket.pad3 = 42;
+  logPacket.type = SP_LOGIN;
+  if (stats == NULL)
+  {
+    logPacket.accept = 0;
+  }
+  else
+  {
+    logPacket.accept = 1;
+    logPacket.flags = htonl(stats->st_flags);
+  }
+  sendClientPacket((struct player_spacket *) & logPacket);
+}
+
+void
+handlePlasmaReq(packet)
+  struct plasma_cpacket *packet;
+{
+  if (me->p_specweap & SFNHASMISSILE)
+  {
+    fire_missile_dir(packet->dir);
+  }
+  else if (me->p_specweap & SFNPLASMAARMED)
+  {
+    nplasmatorp(packet->dir, PTMOVE);
+  }
+  else
+  {
+    warning("This ship is armed with no special weapons");
+  }
+}
+
+void
+handleWarReq(packet)
+  struct war_cpacket *packet;
+{
+  declare_war(packet->newmask);
+}
+
+void
+handlePlanlockReq(packet)
+  struct planlock_cpacket *packet;
+{
+  lock_planet(packet->pnum);
+}
+
+void
+handlePlaylockReq(packet)
+  struct playlock_cpacket *packet;
+{
+  lock_player(packet->pnum);
+}
+
+void
+handleDetMReq(packet)
+  struct det_mytorp_cpacket *packet;
+{
+  struct torp *atorp;
+  short t;
+
+  /* you can det individual torps */
+  t = ntohs(packet->tnum);
+  if (t < 0)
+  {
+    struct missile *dr;
+    int i, any;
+
+    any = 0;
+
+    for (i = 0; i < MAXTORP; i++)
+    {
+      atorp = &torps[me->p_no * MAXTORP + i];
+      if (atorp->t_status == TMOVE || atorp->t_status == TSTRAIGHT)
+      {
+	atorp->t_status = TOFF;
+	any = 1;
+      }
+    }
+
+    if (any)
+      return;
+
+    for (i = 0; i < NPTHINGIES; i++)
+    {
+      dr = &missiles[me->p_no * NPTHINGIES + i];
+      if (dr->ms_status == TMOVE || dr->ms_status == TSTRAIGHT)
+      {
+	switch (dr->ms_type)
+	{
+	 case MISSILETHINGY:
+	  dr->ms_status = TOFF;
+	  break;
+	 case FIGHTERTHINGY:
+	  dr->ms_status = TRETURN;
+	  break;
+	}
+	any = 1;
+      }
+    }
+
+    /* any ? */
+  }
+  else
+  {
+
+    if (t < 0 || t >= MAXPLAYER * MAXTORP)
+      return;
+    atorp = &torps[t];
+
+    if (atorp->t_owner != me->p_no)
+      return;
+    if (atorp->t_status == TMOVE || atorp->t_status == TSTRAIGHT)
+    {
+      atorp->t_status = TOFF;
+    }
+  }
+}
+
+void
+handleTractorReq(packet)
+  struct tractor_cpacket *packet;
+{
+  int target;
+  struct player *player;
+
+  if (weaponsallowed[WP_TRACTOR] == 0)
+  {
+    warning("Tractor beams haven't been invented yet.");
+    return;
+  }
+  target = packet->pnum;
+  if (packet->state == 0)
+  {
+    me->p_flags &= ~(PFTRACT | PFPRESS);
+    return;
+  }
+  if (me->p_flags & PFCLOAK)
+  {
+    warning("Weapons's Officer:  Cannot tractor while cloaked, sir!");
+    return;
+  }
+  if (target < 0 || target >= MAXPLAYER || target == me->p_no)
+    return;
+  player = &players[target];
+  if (player->p_flags & PFCLOAK)
+    return;
+  if (me->p_flags & PFDOCK && players[me->p_docked].p_speed > 4)
+  {
+    warning("It's unsafe to tractor while docked and moving at a warp greater then 4.");
+    return;
+  }
+  if (ihypot(me->p_x - player->p_x, me->p_y - player->p_y) <
+      (TRACTDIST) * me->p_ship.s_tractrng)
+  {
+    undock_player(me);
+    me->p_flags &= ~PFORBIT;
+#if 0
+    undock_player(player);	/* harmless if they're not docked */
+
+#if 0
+    if (player->p_flags & PFORBIT)
+      planets[player->p_planet].pl_torbit &= ~player->p_team;
+    if (me->p_flags & PFORBIT)
+      planets[me->p_planet].pl_torbit &= ~me->p_team;
+#endif
+    player->p_flags &= ~(PFORBIT | PFDOCK);
+    me->p_flags &= ~(PFORBIT | PFDOCK);
+#endif
+    me->p_tractor = target;
+    me->p_flags |= PFTRACT;
+
+  }
+  else
+  {
+    warning("Weapon's Officer:  Vessel is out of range of our tractor beam.");
+  }
+}
+
+void
+handleRepressReq(packet)
+  struct repress_cpacket *packet;
+{
+  int target;
+  struct player *player;
+
+  if (weaponsallowed[WP_TRACTOR] == 0)
+  {
+    warning("Pressor beams haven't been invented yet.");
+    return;
+  }
+  target = packet->pnum;
+  if (packet->state == 0)
+  {
+    me->p_flags &= ~(PFTRACT | PFPRESS);
+    return;
+  }
+  if (me->p_flags & PFCLOAK)
+  {
+    warning("Weapons's Officer:  Cannot pressor while cloaked, sir!");
+    return;
+  }
+  if (target < 0 || target >= MAXPLAYER || target == me->p_no)
+    return;
+  player = &players[target];
+  if (player->p_flags & PFCLOAK)
+    return;
+  if (me->p_flags & PFDOCK && players[me->p_docked].p_speed > 4)
+  {
+    warning("It's unsafe to pressor while docked and moving at a warp greater then 4.");
+    return;
+  }
+  if (ihypot(me->p_x - player->p_x, me->p_y - player->p_y) <
+      (TRACTDIST) * me->p_ship.s_tractrng)
+  {
+    undock_player(me);
+    me->p_flags &= ~PFORBIT;
+#if 0
+    undock_player(player);
+
+#if 0
+    if (player->p_flags & PFORBIT)
+      planets[player->p_planet].pl_torbit &= ~player->p_team;
+    if (me->p_flags & PFORBIT)
+      planets[me->p_planet].pl_torbit &= ~me->p_team;
+#endif
+    player->p_flags &= ~(PFORBIT | PFDOCK);
+    me->p_flags &= ~(PFORBIT | PFDOCK);
+#endif
+    me->p_tractor = target;
+    me->p_flags |= (PFTRACT | PFPRESS);
+  }
+  else
+  {
+    warning("Weapon's Officer:  Vessel is out of range of our pressor beam.");
+  }
+}
+
+void
+sendMotdLine(line)
+  char *line;
+{
+  struct motd_spacket motdPacket;
+
+  motdPacket.type = SP_MOTD;
+  strncpy(motdPacket.line, line, 80);
+  motdPacket.line[79] = '\0';
+  sendClientPacket((struct player_spacket *) & motdPacket);
+}
+
+/* ARGSUSED */
+void
+handleCoupReq(packet)
+  struct coup_cpacket *packet;
+{
+  switch_special_weapon();
+}
+
+void
+handleRefitReq(packet)
+  struct refit_cpacket *packet;
+{
+  do_refit(packet->ship);
+}
+
+void
+handleMessageReq(packet)
+  struct mesg_cpacket *packet;
+{
+  char addrbuf[9];
+  static long lasttime = 0 /* , time() */ ;
+  static int balance = 0;	/* make sure he doesn't get carried away */
+  long thistime;
+
+  int isCensured();		/* "shut up and play" code 7/21/91 TC */
+  int parseIgnore();		/* still more code, 7/24/91 TC */
+
+  /*
+   * Some random code to make sure the player doesn't get carried away about
+   * the number of messages he sends.  After all, he could try to jam peoples
+   * communications if we let him.
+   */
+
+  thistime = time(NULL);
+  if (lasttime != 0)
+  {
+    balance = balance - (thistime - lasttime);
+    if (balance < 0)
+      balance = 0;
+  }
+  lasttime = thistime;
+  if (balance >= 15)
+  {
+    warning("Be quiet");
+    balance += 3;
+    if (balance > time(NULL) + 60)
+    {
+      balance = time(NULL) + 60;
+    }
+    return;
+  }
+  balance += 3;
+  /* packet->mesg[69] = '\0'; */
+  sprintf(addrbuf, " %s->", twoletters(me));
+  if (parseIgnore(packet))
+    return;			/* moved this up 4/6/92 TC */
+  if (packet->group & MGOD)
+  {
+    strcpy(addrbuf + 5, "GOD");
+  }
+  else if (packet->group & MALL)
+  {
+    sprintf(addrbuf + 5, "ALL");
+    if (isCensured(me->p_login))
+    {
+      warning("You are censured.  Message was not sent.");
+      return;
+    }
+  }
+  else if (packet->group & MTEAM)
+  {
+    if (packet->indiv != FED && packet->indiv != ROM &&
+	packet->indiv != KLI && packet->indiv != ORI)
+      return;
+    if (isCensured(me->p_login) && (packet->indiv != me->p_team))
+    {
+      warning("You are censured.  Message was not sent.");
+      return;
+    }
+    sprintf(addrbuf + 5, teams[packet->indiv].shortname);
+  }
+  else if (packet->group & MINDIV)
+  {
+    if (packet->indiv < 0 || packet->indiv >= MAXPLAYER)
+      return;
+    if (players[packet->indiv].p_status == PFREE)
+      return;
+    if (isCensured(me->p_login) && (players[packet->indiv].p_team != me->p_team))
+    {
+      warning("You are censured.  Message was not sent.");
+      return;
+    }
+    if (ignored[packet->indiv] & MINDIV)
+    {
+      warning("You are ignoring that player.  Message was not sent.");
+      return;
+    }
+    if ((me->p_team != players[packet->indiv].p_team) &&
+	(isCensured(players[packet->indiv].p_login)))
+    {
+      warning("That player is censured.  Message was not sent.");
+      return;
+    }
+    sprintf(addrbuf + 5, "%s ", twoletters(&players[packet->indiv]));
+  }
+  else
+  {
+    return;
+  }
+#if 0
+  if ((packet->group == MGOD
+       || me->p_no == packet->indiv && packet->group == MINDIV)
+      && parse_command_mess(packet->mesg, me->p_no))
+  {
+    /* message parsed. Eat it */
+  }
+  else
+  {
+    pmessage2(packet->mesg, packet->indiv, packet->group, addrbuf, me->p_no);
+  }
+#else
+  /* don't eat the parsed messages */
+  pmessage2(packet->mesg, packet->indiv, packet->group, addrbuf, me->p_no);
+  if (me->p_no == packet->indiv && packet->group == MINDIV)
+  {
+    char tmpbuf[sizeof(packet->mesg) + 1];
+    strncpy(tmpbuf, packet->mesg, sizeof(packet->mesg));
+    tmpbuf[sizeof(packet->mesg)] = 0;
+    parse_command_mess(tmpbuf, me->p_no);
+  }
+#endif
+
+  /*
+   * Blech !!!
+   * 
+   * Don't do this:
+   * 
+   * if (me->p_no == packet->indiv && packet->mesg[0] == '_') me = &players[0];
+   */
+}
+
+/* ARGSUSED */
+void
+handleQuitReq(packet)
+  struct quit_cpacket *packet;
+{
+  if (me->p_status == POBSERVE)
+  {
+    me->p_status = PTQUEUE;
+    return;
+  }
+  me->p_flags |= PFSELFDEST;
+
+  switch (me->p_ship.s_type)
+  {
+   case STARBASE:
+   case WARBASE:
+    selfdest = 60;
+    break;
+   default:
+    selfdest = 10;
+  }
+
+  selfdest = me->p_updates + selfdest * 10;
+
+  warning("Self destruct initiated");
+}
+
+void
+sendMaskPacket(mask)
+  int mask;
+{
+  struct mask_spacket maskPacket;
+
+  maskPacket.type = SP_MASK;
+  maskPacket.mask = mask;
+  sendClientPacket((struct player_spacket *) & maskPacket);
+}
+
+void
+handleOptionsPacket(packet)
+  struct options_cpacket *packet;
+{
+  mystats->st_flags = ntohl(packet->flags) |
+    (mystats->st_flags & ST_CYBORG);	/* hacked fix 8/24/91 TC */
+  keeppeace = (mystats->st_flags / ST_KEEPPEACE) & 1;
+}
+
+void
+handleSocketReq(packet)
+  struct socket_cpacket *packet;
+{
+  nextSocket = ntohl(packet->socket);
+  userVersion = packet->version;
+  userUdpVersion = packet->udp_version;
+}
+
+/* ARGSUSED */
+void
+handleByeReq(packet)
+  struct bye_cpacket *packet;
+{
+  noressurect = 1;
+}
+
+int
+checkVersion()
+{
+  struct badversion_spacket packet;
+
+  if (userVersion != SOCKVERSION)
+  {
+    packet.type = SP_BADVERSION;
+    packet.why = 0;
+    sendClientPacket((struct player_spacket *) & packet);
+    flushSockBuf();
+    return (0);
+  }
+  return (1);
+}
+
+void
+logEntry()
+{
+  FILE *logfile;
+  int curtime;
+  char *paths;
+
+  paths = build_path(LOGFILENAME);
+  logfile = fopen(paths, "a");
+  if (!logfile)
+    return;
+  curtime = time(NULL);
+
+#ifdef LOG_LONG_INFO		/*-[ prints out long info to the log files ]-*/
+
+  fprintf(logfile, "Joining: %s, (%c) <%s@%s> %s", me->p_name,
+	  shipnos[me->p_no],
+	  me->p_login,		/* debug 2/21/92 TMC */
+
+#else
+
+  fprintf(logfile, "Joining: %s <%s@%s> %s", me->p_name, me->p_login,
+
+#endif				/*-[ LOG_LONG_INFO ]-*/
+
+	  me->p_full_hostname,
+	  ctime((time_t *) & curtime));
+
+  fclose(logfile);
+}
+
+/* gwrite was here */
+
+void
+handleDockingReq(packet)
+  struct dockperm_cpacket *packet;
+{
+  int i;
+
+  if (allows_docking(me->p_ship))
+  {
+    if (me->p_speed > 4 && me->p_docked)
+    {
+      warning("It's unsafe to disengage other ships while over warp 4.");
+      return;
+    }
+    else
+    {
+      for (i = 0; i < me->p_ship.s_numports; i++)
+	base_undock(me, i);
+      me->p_docked = 0;
+
+      if (packet->state)
+	me->p_flags |= PFDOCKOK;
+      else
+	me->p_flags &= ~PFDOCKOK;
+    }
+  }
+}
+
+void
+handleReset(packet)
+  struct resetstats_cpacket *packet;
+{
+  extern int startTkills, startTlosses, startTarms, startTplanets, startTticks;
+
+  if (packet->verify != 'Y')
+    return;
+
+  /* Gee, they seem to want to reset their stats!  Here goes... */
+#if 0
+  mystats->st_maxkills = 0.0;
+  mystats->st_kills = 0;
+  mystats->st_losses = 0;
+  mystats->st_armsbomb = 0;
+  mystats->st_planets = 0;
+  mystats->st_ticks = 0;
+  mystats->st_tkills = 0;
+  mystats->st_tlosses = 0;
+  mystats->st_tarmsbomb = 0;
+  mystats->st_tplanets = 0;
+  mystats->st_tticks = 1;
+  mystats->st_rank = 0;
+  mystats->st_sbkills = 0;
+  mystats->st_sblosses = 0;
+  mystats->st_sbticks = 0;
+  mystats->st_sbmaxkills = 0.0;
+
+  startTkills = mystats->st_tkills;
+  startTlosses = mystats->st_tlosses;
+  startTarms = mystats->st_tarmsbomb;
+  startTplanets = mystats->st_tplanets;
+  startTticks = mystats->st_tticks;
+#endif
+
+  mystats->st_genocides = 0;
+  mystats->st_tmaxkills = 0.0;
+  mystats->st_di = 0.0;
+  mystats->st_tkills = 0;
+  mystats->st_tlosses = 0;
+  mystats->st_tarmsbomb = 0;
+  mystats->st_tresbomb = 0;
+  mystats->st_tdooshes = 0;
+  mystats->st_tplanets = 0;
+  mystats->st_tticks = 1;
+  mystats->st_sbkills = 0;
+  mystats->st_sblosses = 0;
+  mystats->st_sbmaxkills = 0.0;
+  mystats->st_sbticks = 1;
+  mystats->st_wbkills = 0;
+  mystats->st_wblosses = 0;
+  mystats->st_wbmaxkills = 0.0;
+  mystats->st_wbticks = 1;
+  mystats->st_jsplanets = 0;
+  mystats->st_jsticks = 1;
+  mystats->st_rank = 0;
+  mystats->st_royal = 0;
+
+  startTkills = mystats->st_tkills;
+  startTlosses = mystats->st_tlosses;
+  startTarms = mystats->st_tarmsbomb;
+  startTplanets = mystats->st_tplanets;
+  startTticks = mystats->st_tticks;
+}
+
+void
+handleUpdatesReq(packet)
+  struct updates_cpacket *packet;
+{
+  struct itimerval udt;
+  extern int interrupting;	/* main.c */
+  int min_delay = me->p_observer
+  ? configvals->min_observer_upd_delay
+  : configvals->min_upd_delay;
+
+  timerDelay = ntohl(packet->usecs);
+  if (timerDelay < min_delay)
+    timerDelay = min_delay;
+  if (timerDelay >= 1000000)
+    timerDelay = 999999;
+
+  if (interrupting)
+  {				/* only setitimer if the ntserv is configured
+				 * to handle it.  It's NOT configured to
+				 * handle it in the outfit loop... */
+    udt.it_interval.tv_sec = 0;
+    udt.it_interval.tv_usec = timerDelay;
+    udt.it_value.tv_sec = 0;
+    udt.it_value.tv_usec = timerDelay;
+    setitimer(ITIMER_REAL, &udt, 0);
+  }
+
+}
+
+void
+logmessage(string)
+  char *string;
+{
+  FILE *fp;
+  char *paths;
+
+  paths = build_path(LOGFILENAME);
+
+  fp = fopen(paths, "a");
+  if (fp)
+  {
+    fprintf(fp, "%s\n", string);
+    fclose(fp);
+  }
+}
+
+#if 0
+handleReserved(packet)
+  struct reserved_cpacket *packet;
+{
+  /* char temp[20]; */
+  struct reserved_cpacket mycp;
+  struct reserved_spacket mysp;
+  char serverName[64];		/* now get serverName from system 8/2/92 TC */
+
+  if (testtime == 1)
+    return;
+  if (memcmp(packet->data, testdata, 16) != 0)
+  {
+    testtime = 1;
+    return;
+  }
+  memcpy(mysp.data, testdata, 16);
+  if (gethostname(serverName, 64))
+    fprintf(stderr, "gethostname() error\n");	/* 8/2/92 TC */
+  encryptReservedPacket(&mysp, &mycp, serverName, me->p_no);
+  if (memcmp(packet->resp, mycp.resp, 16) != 0)
+  {
+    fprintf(stderr, "User verified incorrectly.\n");
+    testtime = 1;
+    return;
+  }
+  testtime = 0;
+}
+
+#ifdef ATM_STUFF
+void 
+dummy_()
+{
+  if ((configvals->binconfirm == 2) &&
+      !strcmp(packet->resp, "Cyborg"))
+  {
+    testtime = 0;		/* accept */
+    cyborg = 1;
+    if (me->p_name[0] != '+')
+    {
+      temp[0] = '+';		/* indicate cyborg */
+      strcpy(temp + 1, me->p_name);	/* this happens AFTER entry, */
+      temp[15] = '\0';		/* so changing enter() isn't */
+      strcpy(me->p_name, temp);	/* sufficient */
+    }
+    return;
+  }
+
+  if (memcmp(packet->resp, mycp.resp, 16) != 0)
+  {
+    fprintf(stderr, "User verified incorrectly.\n");
+    testtime = 1;
+    return;
+  }
+
+  testtime = 0;
+}
+
+#endif
+#else
+
+void
+handleRSAKey(packet)
+  struct rsa_key_cpacket *packet;
+{
+#ifdef AUTHORIZE
+  struct rsa_key_spacket mysp;
+  char serverName[64];
+
+  if (testtime == 1)
+    return;
+  if (RSA_Client != 1)
+    return;
+  memcpy(mysp.data, testdata, KEY_SIZE);
+  if (gethostname(serverName, 64))
+    fprintf(stderr, "gethostname() error\n");
+  if (decryptRSAPacket(&mysp, packet, serverName))
+  {
+    fprintf(stderr, "User verified incorrectly.\n");
+    testtime = 1;
+    return;
+  }
+  testtime = 0;
+#endif				/* AUTHORIZE */
+}
+
+void
+handleReserved(packet)
+  struct reserved_cpacket *packet;
+{
+#ifdef AUTHORIZE
+  struct reserved_cpacket mycp;
+  struct reserved_spacket mysp;
+  struct rsa_key_spacket rsp;
+  char serverName[64];		/* now get serverName from system 8/2/92 TC */
+
+  if (testtime == 1)
+    return;
+  if (memcmp(packet->data, testdata, RESERVED_SIZE) != 0)
+  {
+    testtime = 1;
+    return;
+  }
+  if (!strncmp(packet->resp, RSA_VERSION, 3))
+  {
+    /* This is an RSA type client */
+    RSA_Client = 2;
+    warning(RSA_VERSION);
+    if (!strncmp(packet->resp, RSA_VERSION, strlen("RSA v??")))
+    {
+      /* This is the right major version */
+      RSA_Client = 1;
+      makeRSAPacket(&rsp);
+      memcpy(testdata, rsp.data, KEY_SIZE);
+      sendClientPacket((struct player_spacket *) & rsp);
+      return;
+    }
+    testtime = 1;
+    return;
+  }
+  memcpy(mysp.data, testdata, RESERVED_SIZE);
+  if (gethostname(serverName, 64))
+    fprintf(stderr, "gethostname() error\n");	/* 8/2/92 TC */
+  encryptReservedPacket(&mysp, &mycp, serverName, me->p_no);
+  if (memcmp(packet->resp, mycp.resp, RESERVED_SIZE) != 0)
+  {
+    fprintf(stderr, "User verified incorrectly.\n");
+    testtime = 1;
+    return;
+  }
+  /* Use .sysdef CONFIRM flag to allow old style clients. */
+  if (configvals->binconfirm == 2)
+    testtime = 0;
+  else
+    testtime = 1;
+
+#endif				/* AUTHORIZE */
+}
+
+#endif
+
+void
+handleScan(packet)		/* ATM */
+  struct scan_cpacket *packet;
+{
+#if 0
+  struct scan_spacket response;
+  struct player *pp;
+
+  memset(&response, 0, sizeof(struct scan_spacket));
+  response.type = SP_SCAN;
+  response.pnum = packet->pnum;
+  if (!weaponsallowed[WP_SCANNER])
+  {
+    warning("Scanners haven't been invented yet");
+    response.success = 0;
+  }
+  else
+  {
+    response.success = scan(packet->pnum);
+
+    if (response.success)
+    {
+      /fill in all the goodies /
+	pp = &players[packet->pnum];
+      response.p_fuel = htonl(pp->p_fuel);
+      response.p_armies = htonl(pp->p_armies);
+      response.p_shield = htonl(pp->p_shield);
+      response.p_damage = htonl(pp->p_damage);
+      response.p_etemp = htonl(pp->p_etemp);
+      response.p_wtemp = htonl(pp->p_wtemp);
+    }
+  }
+  sendClientPacket((struct player_spacket *) & response);
+#endif
+}
+
+
+void
+handlePingResponse(packet)
+  struct ping_cpacket *packet;
+{
+  char buf[80];
+  /* client requests pings by sending pingme == 1 on TCP socket */
+
+  if (rsock == sock)
+  {
+    if (!ping && packet->pingme == 1)
+    {
+      ping = 1;
+      sprintf(buf, "Server sending ping packets at %d second intervals",
+	      configvals->ping_period);
+      warning(buf);
+      return;
+    }
+    /* client says stop */
+    else if (ping && !packet->pingme)
+    {
+      ping = 0;
+      warning("Server no longer sending ping packets.");
+      return;
+    }
+  }
+  pingResponse(packet);		/* ping.c */
+}
+
+#ifdef SHORT_PACKETS
+
+void 
+handleShortReq(packet)
+  struct shortreq_cpacket *packet;
+{
+  struct shortreply_spacket resp;
+
+  switch (packet->req)
+  {
+   case SPK_VOFF:
+    send_short = 0;
+    warning("Not sending variable and short packets.  Back to default.");
+    if (udpSock >= 0 && udpMode == MODE_FAT)
+      forceUpdate();
+    break;
+
+   case SPK_VON:
+    if (packet->version != (char) SHORTVERSION)
+    {
+      warning("Your SHORT Protocol Version is not right!");
+      packet->req = SPK_VOFF;
+      break;
+    }
+    if (!send_short)
+      warning("Sending variable and short packets. ");	/* send only firsttime */
+    send_short = 1;
+    resp.winside = ntohs(WINSIDE);
+    resp.gwidth = ntohl(GWIDTH);
+    break;
+
+   case SPK_MOFF:
+    send_mesg = 1;
+    warning("Obsolete!");
+    packet->req = SPK_MON;
+    break;
+
+   case SPK_MON:
+    send_mesg = 1;
+    warning("All messages sent.");
+    break;
+
+   case SPK_M_KILLS:
+    send_kmesg = 1;
+    warning("Kill messages sent");
+    break;
+
+   case SPK_M_NOKILLS:
+    send_kmesg = 1;
+    warning("Obsolete!");
+    packet->req = SPK_M_KILLS;
+    break;
+
+   case SPK_M_WARN:
+    send_warn = 1;
+    warning("Warn messages sent");
+    break;
+
+   case SPK_M_NOWARN:
+    send_warn = 1;
+    warning("Obsolete!");
+    packet->req = SPK_M_WARN;
+    break;
+
+   case SPK_SALL:
+    if (send_short)
+    {
+      spk_update_sall = 1;
+      spk_update_all = 0;
+      forceUpdate();
+    }
+    else
+      warning("Activate SHORT Packets first!");
+    return;
+
+   case SPK_ALL:
+    if (send_short)
+    {
+      spk_update_sall = 0;
+      spk_update_all = 1;
+      forceUpdate();
+    }
+    else
+      warning("Activate SHORT Packets first!");
+    return;
+
+   default:
+    warning("Unknown short packet code");
+    return;
+  }
+
+  resp.type = SP_S_REPLY;
+  resp.repl = (char) packet->req;
+
+  sendClientPacket((struct player_spacket *) & resp);
+}
+
+void 
+handleThresh(packet)
+  struct threshold_cpacket *packet;
+{
+  send_threshold = packet->thresh;
+#ifdef SHORT_THRESHOLD
+  if (send_threshold == 0)
+  {
+    actual_threshold = 0;
+    warning("Threshold test deactivated.");
+  }
+  else
+  {
+    actual_threshold = send_threshold / numupdates;
+    if (actual_threshold < 60)
+    {				/* my low value */
+      actual_threshold = 60;	/* means: 1 SP_S_PLAYER+SP_S_YOU + 16 bytes */
+      sprintf(buf, "Threshold set to %d .  %d / Update(Server limit!)",
+	      numupdates * 60, 60);
+      warning(buf);
+    }
+    else
+    {
+      sprintf(buf, "Threshold set to %d .  %d / Update", send_threshold, actual_threshold);
+      warning(buf);
+    }
+  }
+#else
+  warning("Server is compiled without Thresholdtesting!");
+#endif
+}
+
+void 
+handleSMessageReq(packet)
+  struct mesg_s_cpacket *packet;
+{
+  /* If someone would delete the hardcoded things in handleMessageReq */
+  /* like     packet->mesg[69]='\0';   */
+  /* we could give handleMessageReq the packet without copying */
+  /* But i have no time  HW 04/6/93 */
+
+  struct mesg_cpacket mesPacket;
+  mesPacket.type = CP_MESSAGE;
+  mesPacket.group = packet->group;
+  mesPacket.indiv = packet->indiv;
+  strcpy(mesPacket.mesg, packet->mesg);
+  handleMessageReq(&mesPacket);
+  /* I hope this was it */
+}
+
+
+#endif
+
+/*
+ * 
+ * ---------------------------------------------------------------------------
+ * Strictly UDP from here on
+ * ---------------------------------------------------------------------------
+ * */
+
+void
+handleUdpReq(packet)
+  struct udp_req_cpacket *packet;
+{
+  struct udp_reply_spacket response;
+  int mode;
+
+  response.type = SP_UDP_REPLY;
+
+  if (packet->request == COMM_VERIFY)
+  {
+    /* this request should ONLY come through the UDP connection */
+    if (commMode == COMM_UDP)
+    {
+      UDPDIAG(("Got second verify from %s; resending server verify\n",
+	       me->p_name));
+      response.reply = SWITCH_VERIFY;
+      goto send;
+    }
+    UDPDIAG(("Receieved UDP verify from %s\n", me->p_name));
+    UDPDIAG(("--- UDP connection established to %s\n", me->p_name));
+#ifdef BROKEN
+    warning("WARNING: BROKEN mode is enabled");
+#endif
+
+    resetUDPsequence();		/* reset sequence numbers */
+    commMode = COMM_UDP;	/* at last */
+    udpMode = MODE_SIMPLE;	/* just send one at a time */
+
+    /* note that we don't NEED to send a SWITCH_VERIFY packet; the client */
+    /*
+     * will change state when it receives ANY packet on the UDP connection
+     */
+    /* (this just makes sure that it gets one) */
+    /* (update: recvfrom() currently tosses the first packet it gets...)  */
+    response.reply = SWITCH_VERIFY;
+    goto send;
+    /* return; */
+  }
+  if (packet->request == COMM_MODE)
+  {
+    /* wants to switch modes; mode is in "conmode" */
+    mode = packet->connmode;
+    if (mode < MODE_TCP || mode > MODE_DOUBLE)
+    {
+      warning("Server can't do that UDP mode");
+      UDPDIAG(("Got bogus request for UDP mode %d from %s\n",
+	       mode, me->p_name));
+    }
+    else
+    {
+      /* I don't bother with a reply, though it can mess up the opt win */
+      switch (mode)
+      {
+       case MODE_TCP:
+	warning("Server will send with TCP only");
+	break;
+       case MODE_SIMPLE:
+	warning("Server will send with simple UDP");
+	break;
+       case MODE_FAT:
+	warning("Server will send with fat UDP; sent full update");
+	V_UDPDIAG(("Sending full update to %s\n", me->p_name));
+	forceUpdate();
+	break;
+#ifdef DOUBLE_UDP
+       case MODE_DOUBLE:
+	warning("Server will send with double UDP");
+	scbufptr = scbuf + sizeof(struct sc_sequence_spacket);
+	break;
+#else
+       case MODE_DOUBLE:
+	warning("Request for double UDP DENIED (set to simple)");
+	mode = MODE_SIMPLE;
+	break;
+#endif				/* DOUBLE_UDP */
+      }
+
+      udpMode = mode;
+      UDPDIAG(("Switching %s to UDP mode %d\n", me->p_name, mode));
+    }
+    return;
+  }
+  if (packet->request == COMM_UPDATE)
+  {
+    /* client wants a FULL update */
+    V_UDPDIAG(("Sending full update to %s\n", me->p_name));
+    forceUpdate();
+
+    return;
+  }
+  UDPDIAG(("Received request for %s mode from %s\n",
+	   (packet->request == COMM_TCP) ? "TCP" : "UDP", me->p_name));
+  if (packet->request == commMode)
+  {
+    /* client asking to switch to current mode */
+    if (commMode == COMM_UDP)
+    {
+      /*
+       * client must be confused... whatever the cause, he obviously isn't
+       * connected to us, so we better drop out end and retry.
+       */
+      UDPDIAG(("Rcvd UDP req from %s while in UDP mode; dropping old\n",
+	       me->p_name));
+      closeUdpConn();
+      commMode = COMM_TCP;
+      /* ...and fall thru to the UDP request handler */
+    }
+    else
+    {
+      /*
+       * Again, client is confused.  This time there's no damage though. Just
+       * tell him that he succeeded.  Could also happen if the client tried
+       * to connect to our UDP socket but failed, and decided to back off.
+       */
+      UDPDIAG(("Rcvd TCP req from %s while in TCP mode\n", me->p_name));
+
+      response.reply = SWITCH_TCP_OK;
+      sendClientPacket((struct player_spacket *) & response);
+
+      if (udpSock >= 0)
+      {
+	closeUdpConn();
+	UDPDIAG(("Closed UDP socket\n"));
+      }
+      return;
+    }
+  }
+  /* okay, we have a request to change modes */
+  if (packet->request == COMM_UDP)
+  {
+    udpClientPort = ntohl(packet->port);	/* where to connect to */
+    if (!configvals->udpAllowed)
+    {
+      UDPDIAG(("Rejected UDP request from %s\n", me->p_name));
+      response.reply = SWITCH_DENIED;
+      response.port = htons(0);
+      goto send;
+    }
+    else
+    {
+      if (userUdpVersion != UDPVERSION)
+      {
+	char buf[80];
+	sprintf(buf, "Server UDP is v%.1f, client is v%.1f",
+		(float) UDPVERSION / 10.0,
+		(float) userUdpVersion / 10.0);
+	warning(buf);
+	UDPDIAG(("%s (rejected %s)\n", buf, me->p_name));
+	response.reply = SWITCH_DENIED;
+	response.port = htons(1);
+	goto send;
+      }
+      if (udpSock >= 0)
+      {
+	/* we have a socket open, but the client doesn't seem aware */
+	/* (probably because our UDP verify got lost down the line) */
+	UDPDIAG(("Receieved second request from %s, reconnecting\n",
+		 me->p_name));
+	closeUdpConn();
+      }
+      /* (note no openUdpConn(); we go straight to connect) */
+      if (connUdpConn() < 0)
+      {
+	response.reply = SWITCH_DENIED;
+	response.port = 0;
+	goto send;
+      }
+      UDPDIAG(("Connected UDP socket (%d:%d) for %s\n", udpSock,
+	       udpLocalPort, me->p_name));
+
+      /* we are now connected to the client, but he's merely bound */
+      /* don't switch to UDP mode yet; wait until client connects */
+      response.reply = SWITCH_UDP_OK;
+      response.port = htonl(udpLocalPort);
+
+      UDPDIAG(("packet->connmode = %d\n", packet->connmode));
+      if (packet->connmode == CONNMODE_PORT)
+      {
+	/* send him our port # so he can connect to us */
+	goto send;
+      }
+      else
+      {				/* send him a packet; he'll get port from
+				 * recvfrom() */
+	int t = sizeof(response);
+	if (gwrite(udpSock, (char *) &response, sizeof(response)) != t)
+	{
+	  UDPDIAG(("Attempt to send UDP packet failed; using alt\n"));
+	}
+	goto send;
+      }
+
+    }
+  }
+  else if (packet->request == COMM_TCP)
+  {
+    closeUdpConn();
+    commMode = COMM_TCP;
+    response.reply = SWITCH_TCP_OK;
+    response.port = 0;
+    UDPDIAG(("Closed UDP socket for %s\n", me->p_name));
+    goto send;
+  }
+  else
+  {
+    fprintf(stderr, "ntserv: got weird UDP request (%d)\n",
+	    packet->request);
+    return;
+  }
+send:
+  sendClientPacket((struct player_spacket *) & response);
+}
+
+
+int
+connUdpConn()
+{
+  struct sockaddr_in addr;
+  int len;
+
+  if (udpSock > 0)
+  {
+    fprintf(stderr, "ntserv: tried to open udpSock twice\n");
+    return (0);			/* pretend we succeeded (this could be bad) */
+  }
+  resetUDPbuffer();
+  if ((udpSock = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
+  {
+    perror("ntserv: unable to create DGRAM socket");
+    return (-1);
+  }
+  addr.sin_family = AF_INET;
+  addr.sin_addr.s_addr = remoteaddr;	/* addr of our client */
+  addr.sin_port = htons(udpClientPort);	/* client's port */
+
+  if (connect(udpSock, (struct sockaddr *) & addr, sizeof(addr)) < 0)
+  {
+    perror("ntserv: connect to client UDP port");
+    UDPDIAG(("Unable to connect() to %s on port %d\n", me->p_name,
+	     udpClientPort));
+    close(udpSock);
+    udpSock = -1;
+    return (-1);
+  }
+  UDPDIAG(("connect to %s's port %d on 0x%x succeded\n",
+	   me->p_name, udpClientPort, remoteaddr));
+
+  /* determine what our port is */
+  len = sizeof(addr);
+  if (getsockname(udpSock, (struct sockaddr *) & addr, &len) < 0)
+  {
+    perror("netrek: unable to getsockname(UDP)");
+    UDPDIAG(("Can't get our own socket; connection failed\n"));
+    close(udpSock);
+    udpSock = -1;
+    return (-1);
+  }
+  udpLocalPort = (int) ntohs(addr.sin_port);
+
+  if (configvals->udpAllowed > 2)	/* verbose debug mode? */
+    printUdpInfo();
+
+  return (0);
+}
+
+int
+closeUdpConn()
+{
+  V_UDPDIAG(("Closing UDP socket\n"));
+  if (udpSock < 0)
+  {
+    fprintf(stderr, "ntserv: tried to close a closed UDP socket\n");
+    return (-1);
+  }
+  shutdown(udpSock, 2);		/* wham */
+  close(udpSock);		/* bam */
+  udpSock = -1;			/* (nah) */
+
+  return (0);
+}
+
+/* used for debugging */
+void
+printUdpInfo()
+{
+  struct sockaddr_in addr;
+  int len;
+
+  len = sizeof(addr);
+  if (getsockname(udpSock, (struct sockaddr *) & addr, &len) < 0)
+  {
+    perror("printUdpInfo: getsockname");
+    return;
+  }
+  UDPDIAG(("LOCAL: addr=0x%lx, family=%d, port=%d\n",
+	   (u_long) addr.sin_addr.s_addr,
+	   addr.sin_family, ntohs(addr.sin_port)));
+
+  if (getpeername(udpSock, (struct sockaddr *) & addr, &len) < 0)
+  {
+    perror("printUdpInfo: getpeername");
+    return;
+  }
+  UDPDIAG(("PEER : addr=0x%lx, family=%d, port=%d\n",
+	   (u_long) addr.sin_addr.s_addr,
+	   addr.sin_family, ntohs(addr.sin_port)));
+}
+
+void
+handleSequence()
+{
+  /* we don't currently deal with sequence numbers from clients */
+}
+
+void
+handleAskMOTD()
+{
+  sendMotd();
+}
+
+
+#ifdef DOUBLE_UDP
+/*
+ * If we're in double-UDP mode, then we need to send a separate semi-critical
+ * transmission over UDP.  We need to give it the same sequence number as the
+ * previous transmission, but the sequence packet will have type
+ * SP_CP_SEQUENCE instead of SP_SEQUENCE.
+ */
+void
+sendSC()
+{
+  struct sequence_spacket *ssp;
+  struct sc_sequence_spacket *sc_sp;
+  int cc;
+
+  if (commMode != COMM_UDP || udpMode != MODE_DOUBLE)
+  {
+    /* mode not active, keep buffer clear */
+    scbufptr = scbuf;
+    return;
+  }
+  if (scbufptr - scbuf <= sizeof(struct sc_sequence_spacket))
+  {
+    /* nothing to send */
+    return;
+  }
+  /* copy sequence #, send what we got, then reset buffer */
+  sc_sp = (struct sc_sequence_spacket *) scbuf;
+  ssp = (struct sequence_spacket *) udpbuf;
+  sc_sp->type = SP_SC_SEQUENCE;
+  sc_sp->sequence = ssp->sequence;
+  if ((cc = gwrite(udpSock, scbuf, scbufptr - scbuf)) != scbufptr - scbuf)
+  {
+    fprintf(stderr, "UDP sc gwrite failed (%d, error %d)\n", cc, errno);
+    UDPDIAG(("*** UDP diSConnected for %s\n", me->p_name));
+    printUdpInfo();
+    closeUdpConn();
+    commMode = COMM_TCP;
+    return;
+  }
+  scbufptr = scbuf + sizeof(struct sc_sequence_spacket);
+}
+
+#endif
+
+/*
+ * This is a truncated version of initClientData().  Note that it doesn't
+ * explicitly reset all the fat UDP stuff; sendClientData will take care of
+ * that by itself eventually.
+ * 
+ * Only semi-critical data is sent, with a few exceptions for non-critical data
+ * which would be nice to update (stats, kills, player posn, etc). The
+ * critical stuff can't be lost, so there's no point in resending it.
+ * 
+ * (Since the fat data begins in an unqueued state, forceUpdate() should be
+ * called immediately after switching to fat mode.  This guarantees that
+ * every packet will end up on a queue.  The only real reason for doing this
+ * is so that switching to fat mode will clear up your display and keep it
+ * cleared; otherwise you could have torps floating around forever because
+ * the packet for them isn't on a queue.  Will it reduce the effectiveness of
+ * fat UDP? No, because as soon as the player hits the "update all" key it's
+ * gonna happen anyway...)
+ */
+void
+forceUpdate()
+{
+  static time_t lastone = 0;
+  time_t now;
+  int i;
+
+  now = time(0);
+  if (now - lastone < UDP_UPDATE_WAIT)
+  {
+    warning("Update request DENIED (chill out!)");
+    return;
+  }
+  lastone = now;
+
+  /* clientDead=0; */
+  for (i = 0; i < MAXPLAYER; i++)
+  {
+    clientHostile[i].hostile = -1;
+    clientStats[i].losses = -1;	/* (non-critical, but nice) */
+    /* clientLogin[i].rank= -1;		(critical) */
+    /* clientPlayersInfo[i].shiptype= -1;	(critical) */
+    /* clientPStatus[i].status= -1;		(critical) */
+    clientPlayers[i].x = htonl(-1);	/* (non-critical, but nice) */
+    clientPhasers[i].status = -1;
+    clientKills[i].kills = htonl(-1);	/* (non-critical, but nice) */
+    clientFlags[i].flags = htonl(-1);
+    mustUpdate[i] = 0;
+  }
+  for (i = 0; i < MAXPLAYER * MAXTORP; i++)
+  {
+    clientTorpsInfo[i].status = -1;
+    /* clientTorps[i].x= -1;			(non-critical) */
+  }
+  for (i = 0; i < MAXPLAYER * MAXPLASMA; i++)
+  {
+    clientPlasmasInfo[i].status = -1;
+    /* clientPlasmas[i].x= -1;			(non-critical) */
+  }
+  for (i = 0; i < TOTALTHINGIES; i++)
+  {
+
+    clientThingysInfo[i].shape = htons(-1);
+    /* clientThingys[i].x= -1;			(non-critical) */
+  }
+  for (i = 0; i < MAXPLANETS; i++)
+  {
+    clientPlanets2[i].armies = htonl(-2);
+    /* clientPlanetLocs[i].x= htonl(-1);	(critical) */
+  }
+  /* msgCurrent=(mctl->mc_current+1) % MAXMESSAGE; */
+  clientSelf.pnum = -1;
+}
+
+int
+isCensured(s)			/* return true if cannot message opponents */
+  char *s;
+{
+  return (
+#if 0
+	  (strncmp(s, "am4m", 4) == 0) ||	/* 7/21/91 TC */
+	  (strncmp(s, "dm3e", 4) == 0) ||	/* 7/21/91 TC */
+	  (strncmp(s, "gusciora", 8) == 0) ||	/* 7/25/91 TC */
+	  (strncmp(s, "flan", 4) == 0) ||	/* 4/2/91 TC */
+	  (strncmp(s, "kc3b", 4) == 0) ||	/* 4/4/91 TC */
+	  (strncmp(s, "windom", 6) == 0) ||	/* 7/20/92 TC */
+#endif
+	  0
+    );
+}
+
+/* return true if you should eat message */
+
+int
+parseIgnore(packet)
+  struct mesg_cpacket *packet;
+{
+  char *s;
+  int who;
+  int what;
+  char buf[80];
+  int noneflag;
+
+  /* if (packet->indiv != me->p_no) return 0; */
+
+  s = packet->mesg;
+
+  who = packet->indiv;
+  if ((*s != ':') && (strncmp(s, "     ", 5) != 0))
+    return 0;
+  if ((who == me->p_no) || (*s == ' '))
+  {				/* check for borg call 4/6/92 TC */
+    if (configvals->binconfirm)
+      warning("No cyborgs allowed in the game at this time.");
+    else
+    {
+      char buf[80];
+      char buf2[5];
+      int i;
+      int cybflag = 0;
+
+      strcpy(buf, "Possible cyborgs: ");
+      for (i = 0; i < MAXPLAYER; i++)
+	if ((players[i].p_status != PFREE) &&
+	    (players[i].p_stats.st_flags & ST_CYBORG))
+	{
+	  sprintf(buf2, "%s ", twoletters(&players[i]));
+	  strcat(buf, buf2);
+	  cybflag = 1;
+	}
+      if (!cybflag)
+	strcat(buf, "None");
+      warning(buf);
+    }
+    if (*s != ' ')		/* if not a borg call, eat msg 4/6/92 TC */
+      return 1;
+    else
+      return 0;			/* otherwise, send it 4/6/92 TC */
+  }
+  if (packet->group != MINDIV)
+    return 0;			/* below is for indiv only */
+
+  do
+  {
+    what = 0;
+    switch (*(++s))
+    {
+     case 'a':
+     case 'A':
+      what = MALL;
+      break;
+     case 't':
+     case 'T':
+      what = MTEAM;
+      break;
+     case 'i':
+     case 'I':
+      what = MINDIV;
+      break;
+     case '\0':
+      what = 0;
+      break;
+     default:
+      what = 0;
+      break;
+    }
+    ignored[who] ^= what;
+  } while (what != 0);
+
+  strcpy(buf, "Ignore status for this player: ");
+  noneflag = 1;
+  if (ignored[who] & MALL)
+  {
+    strcat(buf, "All ");
+    noneflag = 0;
+  }
+  if (ignored[who] & MTEAM)
+  {
+    strcat(buf, "Team ");
+    noneflag = 0;
+  }
+  if (ignored[who] & MINDIV)
+  {
+    strcat(buf, "Indiv ");
+    noneflag = 0;
+  }
+  if (noneflag)
+    strcat(buf, "None");
+  warning(buf);
+  return 1;
+}
+
+/* give session stats if you send yourself a '?' 2/27/92 TC */
+/* or '!' for ping stats (HAK) */
+/* merged RSA query '#' here, too (HAK) */
+/* return true if you should eat message */
+
+int
+parseQuery(packet)
+  struct mesg_spacket *packet;	/* was cpacket 4/17/92 TC */
+{
+  char buf[80];
+  float sessionBombing, sessionPlanets, sessionOffense, sessionDefense;
+  int deltaArmies, deltaPlanets, deltaKills, deltaLosses, deltaTicks;
+
+  extern int startTkills, startTlosses, startTarms, startTplanets, startTticks;
+
+  /* 0-8 for address, 9 is space */
+
+  if (packet->mesg[11] != '\0')	/* one character only */
+    return 0;
+
+  switch (packet->mesg[10])
+  {
+   case '!':
+    return bouncePingStats(packet);
+   case '#':
+    sprintf(buf, "Client: %s", RSA_client_type);
+    bounce(buf, packet->m_from);
+    return 1;
+   case '?':
+    deltaPlanets = me->p_stats.st_tplanets - startTplanets;
+    deltaArmies = me->p_stats.st_tarmsbomb - startTarms;
+    deltaKills = me->p_stats.st_tkills - startTkills;
+    deltaLosses = me->p_stats.st_tlosses - startTlosses;
+    deltaTicks = me->p_stats.st_tticks - startTticks;
+
+    if (deltaTicks == 0)
+      return 1;			/* can happen if no tmode */
+
+    sessionPlanets = (float) deltaPlanets *status->timeprod /
+        ((float) deltaTicks * status->planets);
+
+    sessionBombing = (float) deltaArmies *status->timeprod /
+        ((float) deltaTicks * status->armsbomb);
+
+    sessionOffense = (float) deltaKills *status->timeprod /
+        ((float) deltaTicks * status->kills);
+
+    sessionDefense = (float) deltaTicks *status->losses /
+        (deltaLosses != 0 ?
+	     ((float) deltaLosses * status->timeprod) :
+	     (status->timeprod));
+
+    sprintf(buf, "%2s stats: %d planets and %d armies. %d wins/%d losses. %5.2f hours.",
+	    twoletters(me),
+	    deltaPlanets,
+	    deltaArmies,
+	    deltaKills,
+	    deltaLosses,
+	    (float) deltaTicks / 36000.0);
+    bounce(buf, packet->m_from);
+    sprintf(buf, "Ratings: Pla: %5.2f  Bom: %5.2f  Off: %5.2f  Def: %5.2f  Ratio: %4.2f",
+	    sessionPlanets,
+	    sessionBombing,
+	    sessionOffense,
+	    sessionDefense,
+	    (float) deltaKills /
+	    (float) ((deltaLosses == 0) ? 1 : deltaLosses));
+    bounce(buf, packet->m_from);
+    return 1;
+   default:
+    return 0;
+  }
+  /* NOTREACHED */
+}
+
+int
+bouncePingStats(packet)
+  struct mesg_spacket *packet;
+{
+  char buf[80];
+
+  if (me->p_avrt == -1)
+  {
+    /* client doesn't support it or server not pinging */
+    sprintf(buf, "No ping stats available for %s",
+	    twoletters(me));
+  }
+  else
+  {
+    sprintf(buf, "%s ping stats: Average: %d ms, Stdv: %d ms, Loss: %d%%",
+	    twoletters(me),
+	    me->p_avrt,
+	    me->p_stdv,
+	    me->p_pkls);
+  }
+  bounce(buf, packet->m_from);
+
+  return 1;
+}
+
+/* new code, sends bouncemsg to bounceto from GOD 4/17/92 TC */
+void
+bounce(bouncemsg, bounceto)
+  char *bouncemsg;
+  int bounceto;
+{
+  char buf[10];
+
+  sprintf(buf, "GOD->%s", twoletters(&players[bounceto]));
+  pmessage(bouncemsg, bounceto, MINDIV, buf);
+}
+
+
+/*
+ */
+
+void
+sendShipCap()
+{
+  struct ship_cap_spacket temppack;
+  struct ship ship;
+  int i;
+
+  if (!blk_flag)
+    return;
+  for (i = 0; i < NUM_TYPES; i++)
+  {
+    getship(&ship, i);
+    temppack.type = SP_SHIP_CAP;
+    temppack.operation = 0;
+    temppack.s_type = htons(ship.s_type);
+    temppack.s_torpspeed = htons(ship.s_torp.speed);
+#if 1
+    temppack.s_phaserrange = htons(ship.s_phaser.speed);
+#else
+    temppack.s_phaserrange = htons(ship.s_phaser.damage);
+#endif
+    temppack.s_maxspeed = htonl(ship.s_imp.maxspeed);
+    temppack.s_maxfuel = htonl(ship.s_maxfuel);
+    temppack.s_maxshield = htonl(ship.s_maxshield);
+    temppack.s_maxdamage = htonl(ship.s_maxdamage);
+    temppack.s_maxwpntemp = htonl(ship.s_maxwpntemp);
+    temppack.s_maxegntemp = htonl(ship.s_maxegntemp);
+    temppack.s_width = htons(ship.s_width);
+    temppack.s_height = htons(ship.s_height);
+    temppack.s_maxarmies = htons(ship.s_maxarmies);
+    temppack.s_letter = ship.s_letter;
+    temppack.s_desig1 = ship.s_desig1;
+    temppack.s_desig2 = ship.s_desig2;
+    if (blk_flag == 1)
+      temppack.s_bitmap = htons(ship.s_alttype);
+    else
+      temppack.s_bitmap = htons(ship.s_bitmap);
+    sendClientPacket((struct player_spacket *) & temppack);
+  }
+}
+
+void
+sendMotdPic(x, y, bits, page, width, height)
+  int x;
+  int y;
+  char *bits;
+  int page;
+  int width;
+  int height;
+{
+  struct motd_pic_spacket temppack;
+  short sx, sy, sp, sw, sh;
+  int size;
+
+  size = (width / 8 + (width % 8 != 0)) * height;
+  sx = x;
+  sy = y;
+  sp = page;
+  sw = width;
+  sh = height;
+  temppack.type = SP_MOTD_PIC;
+  temppack.x = htons(sx);
+  temppack.y = htons(sy);
+  temppack.width = htons(sw);
+  temppack.height = htons(sh);
+  temppack.page = htons(sp);
+  memcpy(temppack.bits, bits, size);
+
+  sendClientPacket((struct player_spacket *) & temppack);
+}
+
+
+void
+sendMotdNopic(x, y, page, width, height)
+  int x;
+  int y;
+  int page;
+  int width;
+  int height;
+{
+  struct pe1_missing_bitmap_spacket temppack;
+
+  temppack.type = SP_PARADISE_EXT1;
+  temppack.subtype = SP_PE1_MISSING_BITMAP;
+  temppack.page = htons((short) page);
+  temppack.x = htons((short) x);
+  temppack.y = htons((short) y);
+  temppack.width = htons((short) width);
+  temppack.height = htons((short) height);
+
+  sendClientPacket((struct player_spacket *) & temppack);
+}
+
+/* tells the client how many missiles carried [BDyess] */
+void
+sendMissileNum(num)
+  int num;
+{
+
+  /* remove the 1 || to enable missile updates [BDyess] */
+  if (clientMissiles.num == htons(num))
+    return;
+
+  clientMissiles.type = SP_PARADISE_EXT1;
+  clientMissiles.subtype = SP_PE1_NUM_MISSILES;
+  clientMissiles.num = htons(num);
+
+  sendClientPacket((struct player_spacket *) & clientMissiles);
+}
+
+#ifdef RSA_EXEMPTION_FILE
+
+/*
+ * this code was copied from
+ * 
+ * portname.c, part of faucet and hose: network pipe utilities Copyright (C)
+ * 1992 Robert Forsman
+ * 
+ * He has granted the Paradise project permission to use this code for
+ * non-profit purposes.
+ * 
+ */
+
+int 
+convert_hostname(char *name, struct in_addr * addr)
+{
+  struct hostent *hp;
+  int len;
+
+  hp = gethostbyname(name);
+  if (hp != NULL)
+    memcpy(addr, hp->h_addr, hp->h_length);
+  else
+  {
+    int count;
+    unsigned int a1, a2, a3, a4;
+
+    count = sscanf(name, "%i.%i.%i.%i%n", &a1, &a2, &a3, &a4, &len);
+
+    if (4 != count || 0 != name[len])
+      return 0;
+
+    addr->s_addr = (((((a1 << 8) | a2) << 8) | a3) << 8) | a4;
+  }
+  return 1;
+}
+
+/*
+ * figure out if our client is exempt from RSA authentication.
+ * 
+ * The host name resolution above doesn't handle gateways, which can have more
+ * than one internet address :/
+ */
+
+int 
+site_rsa_exempt()
+{
+  FILE *fp;
+  char buf[256];
+
+  if (remoteaddr == -1)
+  {
+    printf("remote address is not yet available?!\n");
+    return 0;			/* weird */
+  }
+
+  /* hopefully we've got the remote address at this point */
+
+  fp = fopen(build_path(RSA_EXEMPTION_FILE), "r");
+
+  if (!fp)
+    return 0;			/* nobody is exempt */
+
+  while (fgets(buf, sizeof(buf), fp))
+  {
+    char hostname[256];
+    char *playername;
+    int len;
+    int i;
+    struct in_addr addr;
+
+    len = strlen(buf);
+
+    if (buf[len - 1] == '\n')
+      buf[len - 1] = 0;
+
+    for (i = 0; buf[i] && !isspace(buf[i]); i++)
+      hostname[i] = buf[i];
+
+    hostname[i] = 0;		/* hostname is copied to buffer */
+
+    while (buf[i] && isspace(buf[i]))
+      i++;
+
+    playername = buf + i;	/* player name is stuff after hostname */
+
+    if (!(*playername == 0 || strcmp(playername, me->p_name) == 0))
+      continue;			/* name didn't match */
+
+    /*
+     * shit, I gotta parse this crap myself.  I'll steal this code from hose
+     * - RF
+     */
+    if (!convert_hostname(hostname, &addr))
+    {
+      printf("address in %s unparseable `%s'\n",
+	     RSA_EXEMPTION_FILE, hostname);
+      continue;
+    }
+
+    if (addr.s_addr == remoteaddr)
+      return 1;
+  }				/* while (line in rsa-exempt file) */
+
+  fclose(fp);
+
+  return 0;
+}
+
+#endif				/* RSA_EXEMPTION_FILE */