changeset 4:aa38447a4b21

First entry of Paradise Server 2.9 patch 10 Beta
author darius
date Sat, 06 Dec 1997 04:37:03 +0000
parents cafa94d86546
children 054275999194
files src/fatudp.c src/feature.c src/findslot.c src/gameconf.c src/getentry.c src/getname.c src/getship.c src/getship.h src/getstats.c src/gppackets.h src/grid.c src/grid.h src/imath.c src/input.c src/interface.c src/listen.c src/main.c src/mes src/message.c src/misc.c src/misc.h src/orbit.c src/packets.c src/packets.h src/parsexbm.c src/path.c src/path.h src/phaser.c src/ping.c src/pl_gen0.c src/pl_gen1.c src/pl_gen2.c src/pl_gen3.c src/pl_gen4.c src/pl_gen5.c
diffstat 35 files changed, 14779 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/fatudp.c	Sat Dec 06 04:37:03 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 <stdio.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+
+#include "defs.h"
+#include "data.h"
+#include "packets.h"
+#include "shmem.h"
+
+/* #define FATDIAG	/* define to get LOTS of fat UDP debugging messages */
+
+
+/* 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;
+
+FAT_NODE fat_kills[MAXPLAYER];
+FAT_NODE fat_torp_info[MAXPLAYER * MAXTORP];
+FAT_NODE fat_thingy_info[TOTALTHINGIES];
+FAT_NODE fat_phaser[MAXPLAYER];
+FAT_NODE fat_plasma_info[MAXPLAYER * MAXPLASMA];
+FAT_NODE fat_you;
+#if 0
+FAT_NODE fat_status;
+FAT_NODE fat_planet[MAXPLANETS];
+#else
+FAT_NODE fat_status2;
+FAT_NODE fat_planet2[MAXPLANETS];
+#endif
+FAT_NODE fat_flags[MAXPLAYER];
+FAT_NODE fat_hostile[MAXPLAYER];
+
+/* define the lists */
+#define MAX_FAT_LIST	5	/* tweakable; should be > 1 */
+typedef struct
+{
+  FAT_NODE *head;
+  FAT_NODE *tail;
+}   FAT_LIST;
+FAT_LIST fatlist[MAX_FAT_LIST], tmplist[MAX_FAT_LIST];
+/* tweakable parameters; compare with UDPBUFSIZE */
+/* NOTE: FAT_THRESH + MAX_FAT_DATA must be < UDPBUFSIZE                */
+/* MAX_FAT_DATA must be larger than biggest semi-critical packet */
+#define MAX_FAT_DATA	100	/* add at most this many bytes */
+#define MAX_NONFAT	10	/* if we have this much left, stop */
+
+
+void 
+reset_fat_list()
+{
+  int i;
+  for (i = 0; i < MAX_FAT_LIST; i++)
+    fatlist[i].head = fatlist[i].tail = (FAT_NODE *) NULL;
+}
+/*
+ * 
+ * ---------------------------------------------------------------------------
+ * Fat City
+ * ---------------------------------------------------------------------------
+ * */
+
+/*
+ * Remove a FAT_NODE from a queue.  If it's at the head or the tail of a
+ * list, then we need to figure out which list it's in and update the head or
+ * tail pointer.  It's easier to go searching than to maintain a queue number
+ * in every FAT_NODE.
+ * 
+ * This routine looks too complex... there must be a simpler way to do this.
+ */
+void
+dequeue(fatp)
+  FAT_NODE *fatp;
+{
+  int i;
+
+#ifdef V_FATDIAG
+  for (i = 0; i < MAX_FAT_LIST; i++)
+  {
+    printf("fatlist[i].head = 0x%.8lx tail = 0x%.8lx\n",
+	   fatlist[i].head, fatlist[i].tail);
+    if ((fatlist[i].head == NULL && fatlist[i].tail != NULL) ||
+	(fatlist[i].head != NULL && fatlist[i].tail == NULL))
+    {
+      printf("before!\n");
+      kill(getpid(), 15);
+    }
+  }
+#endif
+
+
+  if (fatp->next == NULL)
+  {
+    /* it's at the head or not in a queue */
+    for (i = 0; i < MAX_FAT_LIST; i++)
+    {
+      if (fatlist[i].head == fatp)
+      {
+	fatlist[i].head = fatp->prev;	/* move head back */
+	if (fatlist[i].head != NULL)
+	  (fatlist[i].head)->next = NULL;	/* amputate */
+	break;
+      }
+    }
+  }
+  else
+  {
+    /* it's not at the head */
+    if (fatp->prev != NULL)
+      fatp->prev->next = fatp->next;
+  }
+
+  if (fatp->prev == NULL)
+  {
+    /* it's at the tail or not in a queue */
+    for (i = 0; i < MAX_FAT_LIST; i++)
+    {
+      if (fatlist[i].tail == fatp)
+      {
+	fatlist[i].tail = fatp->next;	/* move head fwd */
+	if (fatlist[i].tail != NULL)
+	  (fatlist[i].tail)->prev = NULL;	/* amputate */
+	break;
+      }
+    }
+  }
+  else
+  {
+    /* it's not at the tail */
+    if (fatp->next != NULL)
+      fatp->next->prev = fatp->prev;
+  }
+
+#ifdef FATDIAG
+  printf("Removed 0x%.8lx...", fatp);	/* FATDIAG */
+  for (i = 0; i < MAX_FAT_LIST; i++)
+  {
+    if ((fatlist[i].head == NULL && fatlist[i].tail != NULL) ||
+	(fatlist[i].head != NULL && fatlist[i].tail == NULL))
+    {
+      printf("after: %d %.8lx %.8lx\n", i, fatlist[i].head, fatlist[i].tail);
+      kill(getpid(), 15);
+    }
+  }
+#endif
+  fatp->prev = NULL;
+  fatp->next = NULL;
+}
+
+/*
+ * Add a FAT_NODE to the tail of a temporary queue.  The merge() routine
+ * merges the temporary queues with the fatlists once the transmission is
+ * sent.
+ */
+void
+enqueue(fatp, list)
+  FAT_NODE *fatp;
+  int list;
+{
+#ifdef FATDIAG
+  printf("added to tmplist %d\n", list);	/* FATDIAG */
+#endif
+
+  if (tmplist[list].tail == NULL)
+  {
+    /* list was empty */
+    tmplist[list].tail = tmplist[list].head = fatp;
+  }
+  else
+  {
+    /* list wasn't empty */
+    fatp->next = tmplist[list].tail;
+    fatp->next->prev = fatp;
+    tmplist[list].tail = fatp;
+  }
+}
+
+/*
+ * This updates the "fat" tables; it's called from sendClientData().
+ */
+void
+updateFat(packet)
+/* Pick a random type for the packet */
+  struct player_spacket *packet;
+{
+  FAT_NODE *fatp;
+  struct kills_spacket *kp;
+  struct torp_info_spacket *tip;
+  struct thingy_info_spacket *thip;
+  struct phaser_spacket *php;
+  struct plasma_info_spacket *pip;
+  /* struct you_spacket *yp; */
+  /* struct status_spacket2 *sp2; */
+  /* struct planet_spacket *plp; */
+  struct planet_spacket2 *plp2;
+  struct flags_spacket *fp;
+  struct hostile_spacket *hp;
+  int idx;
+
+  /* step 1 : find the FAT_NODE for this packet */
+  switch (packet->type)
+  {
+   case SP_KILLS:
+    kp = (struct kills_spacket *) packet;
+    idx = (int) kp->pnum;
+    fatp = &fat_kills[idx];
+    break;
+   case SP_TORP_INFO:
+    tip = (struct torp_info_spacket *) packet;
+    idx = (int) ntohs(tip->tnum);
+    fatp = &fat_torp_info[idx];
+    break;
+   case SP_THINGY_INFO:
+    thip = (struct thingy_info_spacket *) packet;
+    idx = (int) ntohs(thip->tnum);
+    fatp = &fat_thingy_info[idx];
+    break;
+   case SP_PHASER:
+    php = (struct phaser_spacket *) packet;
+    idx = (int) php->pnum;
+    fatp = &fat_phaser[idx];
+    break;
+   case SP_PLASMA_INFO:
+    pip = (struct plasma_info_spacket *) packet;
+    idx = (int) ntohs(pip->pnum);
+    fatp = &fat_plasma_info[idx];
+    break;
+   case SP_YOU:
+    /* yp = (struct you_spacket *) packet; */
+    fatp = &fat_you;
+    break;
+#if 0
+   case SP_STATUS:
+    /* sp = (struct status_spacket *) packet; */
+    fatp = &fat_status;
+    break;
+   case SP_PLANET:
+    plp = (struct planet_spacket *) packet;
+    idx = plp->pnum;
+    fatp = &fat_planet[idx];
+    break;
+#else
+   case SP_STATUS2:
+    /* sp = (struct status_spacket *) packet; */
+    fatp = &fat_status2;
+    break;
+   case SP_PLANET2:
+    plp2 = (struct planet_spacket2 *) packet;
+    idx = plp2->pnum;
+    fatp = &fat_planet2[idx];
+    break;
+#endif
+   case SP_FLAGS:
+    fp = (struct flags_spacket *) packet;
+    idx = (int) fp->pnum;
+    fatp = &fat_flags[idx];
+    break;
+   case SP_HOSTILE:
+    hp = (struct hostile_spacket *) packet;
+    idx = (int) hp->pnum;
+    fatp = &fat_hostile[idx];
+    break;
+   default:
+    fprintf(stderr, "Fat error: bad semi-critical type (%d) in updateFat\n", (CARD8) packet->type);
+    return;
+  }
+
+  if (fatp->packet != (PTR) packet)
+  {
+    fprintf(stderr, "Fat error: fatp->packet=0x%.8lx, packet=0x%.8lx\n",
+	    (unsigned long) fatp->packet, (unsigned long) packet);
+    return;
+  }
+  /* step 2 : move this dude to temporary list 0 */
+  dequeue(fatp);
+  enqueue(fatp, 0);
+}
+
+/*
+ * This fattens up the transmission, adding up to MAX_FAT_DATA bytes.  The
+ * packets which get added will be moved to a higher queue, giving them less
+ * priority for next time.  Note that they are added to a parallel temporary
+ * list (otherwise they'd could be sent several times in the same
+ * transmission as the algorithm steps through the queues), and merged later
+ * on.
+ * 
+ * Packets are assigned from head to tail, on a first-fit basis.  If a
+ * semi-critical packet is larger than MAX_FAT_DATA, this routine will never
+ * send it, but it will skip around it.
+ * 
+ * This routine is called from flushSockBuf, before the transmission is sent.
+ * 
+ * A possible improvement is to have certain packets "expire", never to be seen
+ * again.  This way we don't keep resending torp packets for players who are
+ * long dead.  This raises the possibility that the dead player's torps will
+ * never go away though.
+ */
+int
+fatten()
+{
+  int bytesleft;
+  FAT_NODE *fatp, *nextfatp;
+  int list;
+
+#ifdef FATDIAG
+  printf("--- fattening\n");
+#endif
+  bytesleft = MAX_FAT_DATA;
+  for (list = 0; list < MAX_FAT_LIST; list++)
+  {
+    fatp = fatlist[list].head;
+    while (fatp != NULL)
+    {
+      nextfatp = fatp->prev;	/* move toward tail */
+#ifdef FATDIAG
+      if (nextfatp == fatp)
+      {
+	printf("Hey!  nextfatp == fatp!\n");
+	kill(getpid(), 15);
+      }
+#endif
+      if (fatp->pkt_size < bytesleft)
+      {
+	/* got one! */
+	sendUDPbuffered(0, fatp->packet, fatp->pkt_size);
+	bytesleft -= fatp->pkt_size;
+
+	packets_sent++;		/* counts as a udp packet sent */
+
+	/* move the packet to a higher queue (if there is one) */
+	dequeue(fatp);
+	if (list + 1 == MAX_FAT_LIST)
+	{
+	  /* enqueue(fatp, list); *//* keep packets on high queue? */
+	}
+	else
+	{
+	  enqueue(fatp, list + 1);
+	}
+
+	/* done yet? */
+	if (bytesleft < MAX_NONFAT)
+	  goto done;		/* don't waste time searching anymore */
+      }
+      fatp = nextfatp;
+    }
+  }
+
+done:
+  /* at this point, we either filled with fat or ran out of queued packets */
+#ifdef FATDIAG
+  printf("--- done\n");
+#endif
+  V_UDPDIAG(("- Added %d grams of fat\n", MAX_FAT_DATA - bytesleft));
+  return (0);			/* some compilers need something after a goto */
+}
+
+
+/*
+ * This gets called from flushSockBuf after the transmission is sent.  It
+ * appends all the packets sitting in temporary queues to the corresponding
+ * fat queues, where they will be eligible for fattening next transmission.
+ */
+void
+fatMerge()
+{
+  int i;
+
+  for (i = 0; i < MAX_FAT_LIST; i++)
+  {
+    if (tmplist[i].head == NULL)
+      continue;			/* temp list is empty, nothing to do */
+
+    if (fatlist[i].head == NULL)
+    {
+      /* fatlist is empty; just copy pointers */
+      fatlist[i].head = tmplist[i].head;
+      fatlist[i].tail = tmplist[i].tail;
+
+    }
+    else
+    {
+      /* stuff in both */
+      (tmplist[i].head)->next = fatlist[i].tail;	/* fwd pointer */
+      (fatlist[i].tail)->prev = tmplist[i].head;	/* back pointer */
+      fatlist[i].tail = tmplist[i].tail;	/* move tail back */
+      tmplist[i].head = tmplist[i].tail = NULL;	/* clear the tmp list */
+    }
+    tmplist[i].head = tmplist[i].tail = NULL;
+#ifdef FATDIAG
+    printf("merged list %d: %.8lx %.8lx\n", i, fatlist[i].head,
+	   fatlist[i].tail);
+#endif
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/feature.c	Sat Dec 06 04:37:03 1997 +0000
@@ -0,0 +1,228 @@
+/*--------------------------------------------------------------------------
+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"
+#ifdef FEATURE
+#ifdef HPUX
+#include <sys/types.h>
+#include <netinet/in.h>
+#endif
+#include "defs.h"
+#include "data.h"
+#include "struct.h"
+#include "packets.h"
+
+void sendClientPacket();
+
+#ifdef UNIXWARE			/* can you BELIEVE it doesn't have strcmpi?? */
+#if 0				/* just  use strcmp for now */
+int 
+strcmpi(char *a, char *b)
+{
+
+  char ta, tb;
+
+  while ((*a) && (*b))
+  {
+    ta = ((*a) >= 'a') && ((*b) <= 'z')) ? (*a) & 223 : (*a);
+    tb = ((*b) >= 'a') && ((*b) <= 'z')) ? (*b) & 223 : (*b);
+    if (ta < tb)
+      return (-1);
+    if (ta > tb)
+      return (1);
+    a++;
+    b++;
+  }
+  if (!(*a) && (*b))
+    return (1);
+  if (!(*b) && (*a))
+    return (-1);
+  return (0);
+}
+#endif
+#endif
+
+/*
+ * Feature.c
+ * 
+ * March, 1994.    Joe Rumsey, Tedd Hadley
+ * 
+ * most of the functions needed to handle SP_FEATURE/CP_FEATURE packets.  fill
+ * in the features list below for your client, and add a call to
+ * reportFeatures just before the RSA response is sent. handleFeature should
+ * just call checkFeature, which will search the list and set the appropriate
+ * variable.  features unknown to the server are set to the desired value for
+ * client features, and off for server/client features.
+ * 
+ * feature packets look like: struct feature_cpacket { char
+ * type; char                 feature_type; char                 arg1, arg2;
+ * int                  value; char                 name[80]; };
+ * 
+ * type is CP_FEATURE, which is 60.  feature_spacket is identical.
+ * 
+ * Code lifted July 1995 by Bob Glamm - enabled into server code.
+ * 
+ */
+
+void handleFeature(struct feature_cpacket *);
+void 
+sendFeature(char *name, int feature_type,
+	    int value, int arg1, int arg2);
+
+/* not the actual packets: this holds a list of features to report for */
+/* this client. */
+struct feature
+{
+  char *name;
+  int *var;			/* holds allowed/enabled status */
+  char feature_type;		/* 'S' or 'C' for server/client */
+  int value;			/* desired status */
+  char *arg1, *arg2;		/* where to copy args, if non-null */
+}   features[] =
+{
+  /*
+   * also sent seperately, put here for checking later. should be ok that
+   * it's sent twice.
+   */
+  {
+    "FEATURE_PACKETS", &F_feature_packets, 'S', 1, 0, 0
+  },
+
+  {
+    "VIEW_BOX", &F_allowViewBox, 'C', 1, 0, 0
+  },
+  {
+    "SHOW_ALL_TRACTORS", &F_allowShowAllTractorPressor, 'S', 1, 0, 0
+  },
+#ifdef CONTINUOUS_MOUSE
+  {
+    "CONTINUOUS_MOUSE", &F_allowContinuousMouse, 'C', 1, 0, 0
+  },
+#endif
+  {
+    "NEWMACRO", &F_UseNewMacro, 'C', 1, 0, 0
+  },
+  /* {"SMARTMACRO",&F_UseSmartMacro, 'C', 1, 0, 0}, */
+  {
+    "MULTIMACROS", &F_multiline_enabled, 'S', 1, 0, 0
+  },
+  {
+    "WHY_DEAD", &F_why_dead, 'S', 1, 0, 0
+  },
+  {
+    "CLOAK_MAXWARP", &F_cloakerMaxWarp, 'S', 1, 0, 0
+  },
+  /* {"DEAD_WARP", &F_dead_warp, 'S', 1, 0, 0}, */
+#ifdef RC_DISTRESS
+  {
+    "RC_DISTRESS", &F_gen_distress, 'S', 1, 0, 0
+  },
+#ifdef BEEPLITE
+  {
+    "BEEPLITE", &F_allow_beeplite, 'C', 1, (char *) &F_beeplite_flags, 0
+  },
+#endif
+#endif
+  /* terrain features */
+  {
+    "TERRAIN", &F_terrain, 'S', 1, (char *) &F_terrain_major, (char *) &F_terrain_minor
+  },
+  /* Gzipped MOTD */
+  {
+    "GZ_MOTD", &F_gz_motd, 'S', 1, (char *) &F_gz_motd_major, (char *) &F_gz_motd_minor
+  },
+  {
+    0, 0, 0, 0, 0, 0
+  }
+};
+
+void 
+handleFeature(packet)
+  struct feature_cpacket *packet;
+{
+  int feature = 0;
+  int value = ntohl(packet->value);
+
+#ifdef FEATURE_DIAG
+  pmessage("Whoohoo!  Getting a feature packet.", 0, MALL, MSERVA);
+#endif
+  while (features[feature].name)
+  {
+    if (!strcmp(features[feature].name, packet->name))
+    {
+#ifdef FEATURE_DIAG
+      {
+	char buf[80];
+	sprintf(buf, "BEANS!  Matched feature %s", packet->name);
+	pmessage(buf, 0, MALL, MSERVA);
+      }
+#endif
+      /* A match was found. */
+      if (features[feature].var)
+	*features[feature].var = packet->value;
+      if (features[feature].arg1)
+	*features[feature].arg1 = packet->arg1;
+      if (features[feature].arg2)
+	*features[feature].arg2 = packet->arg2;
+
+      /*
+       * tell the client that the server handles all of the above server
+       * features.
+       */
+      if (features[feature].feature_type == 'S')
+      {
+#ifdef FEATURE_DIAG
+	pmessage("Sending FEATURE_PACKETS right back at ya!", 0, MALL, MSERVA);
+#endif
+	sendFeature(features[feature].name,
+		    features[feature].feature_type,
+		    features[feature].value,
+		    (features[feature].arg1 ? *features[feature].arg1 : 0),
+		    (features[feature].arg2 ? *features[feature].arg2 : 0));
+      }
+    }
+    feature++;
+  }
+}
+
+void
+sendFeature(name, feature_type, value, arg1, arg2)
+  char *name;
+  int feature_type;
+  int value;
+  int arg1, arg2;
+{
+  struct feature_cpacket packet;
+#ifdef FEATURE_DIAG
+  char buf[80];
+
+  sprintf(buf, "Sending packet %d, name %s", SP_FEATURE, name);
+  pmessage(buf, 0, MALL, MSERVA);
+#endif
+
+  strncpy(packet.name, name, sizeof(packet.name));
+  packet.type = SP_FEATURE;
+  packet.name[sizeof(packet.name) - 1] = 0;
+  packet.feature_type = feature_type;
+  packet.value = htonl(value);
+  packet.arg1 = arg1;
+  packet.arg2 = arg2;
+  sendClientPacket((struct player_spacket *) & packet);
+}
+
+#endif				/* FEATURE */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/findslot.c	Sat Dec 06 04:37:03 1997 +0000
@@ -0,0 +1,491 @@
+/*--------------------------------------------------------------------------
+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 <pwd.h>
+#include <string.h>
+#include <ctype.h>
+#include "defs.h"
+#include "struct.h"
+#include "data.h"
+#include "packets.h"
+#include "shmem.h"
+
+int grabslot( /* int */ );
+void mapWaitCount( /* int */ );
+
+
+extern int isClientDead();
+extern unsigned int sleep();
+extern int sendQueuePacket();
+extern int flushSockBuf();
+
+int
+findslot(overload, homeaway)
+  int overload;
+  enum HomeAway homeaway;
+{
+  int i;
+
+  i = grabslot(overload, homeaway);
+  players[i].p_pos = -1;
+  memset(&players[i].p_stats, 0, sizeof(struct stats));
+  players[i].p_stats.st_tticks = 1;
+#if 0
+  for (j = 0; j < 95; j++)
+  {
+    players[i].p_stats.st_keymap[j] = j + 32;
+  }
+  players[i].p_stats.st_keymap[95] = 0;
+#endif
+  players[i].p_stats.st_flags = ST_INITIAL;
+  return (i);
+}
+
+static int 
+allocate_slot(homeaway, overload, allocate)
+  enum HomeAway homeaway;
+  int overload;
+  int allocate;
+{
+  int i;
+  if (overload)
+  {
+    for (i = MAXPLAYER - 1; i >= 0; i--)
+    {
+      if (players[i].p_status == PFREE)
+      {
+	if (allocate)
+	{
+	  players[i].p_status = POUTFIT;
+	  players[i].p_team = NOBODY;
+	}
+	return i;
+      }
+    }
+  }
+  else
+  {
+#ifdef LEAGUE_SUPPORT
+    if (status2->league)
+    {
+      /*
+       * for league play, make sure one team doesn't crowd out the other.
+       */
+      int count = 0;
+      for (i = 0; i < MAXPLAYER; i++)
+      {
+	if (players[i].p_status == PFREE)
+	  continue;
+	if (players[i].p_homeaway == homeaway)
+	  count++;
+      }
+      if (count * 2 >= MAXPLAYER - configvals->ntesters)
+	return -1;		/* our team is full */
+    }
+#endif
+    for (i = 0; i < MAXPLAYER - configvals->ntesters; i++)
+    {
+      if (players[i].p_status == PFREE)
+      {
+	if (allocate)
+	{
+	  players[i].p_status = POUTFIT;
+	  players[i].p_team = NOBODY;
+	}
+	return i;
+      }
+    }
+  }
+  return -1;
+}
+#if 0
+static int 
+ImAllowed(slotnum, homeaway)
+  int slotnum;
+  enum HomeAway homeaway;
+{
+#ifdef LEAGUE_SUPPORT
+  int half;
+  if (!status2->league)
+    return 1;
+
+  half = (MAXPLAYER - configvals->ntesters) / 2;
+  return (homeaway == AWAY) ? (slotnum < half) :
+    (slotnum >= half);
+#else
+  return 1;
+#endif
+}
+#endif
+/*
+ * The following code for grabslot() is really bizarre, and needs an
+ * explaination.
+ * 
+ * Basically, the queue works like this:  Each process that needs to wait takes
+ * a number, and when that number comes up, the process enters the game.
+ * status->count is the next number to take for a new process, and
+ * status->wait is the current process being served.
+ * 
+ * However, this is not enough to determine exactly how many people are waiting,
+ * because people may drop out.  So, 3 more variables are added,
+ * status->request posts a request of some sort to all of the other
+ * processes, and status->number is the process posting the request. Also,
+ * status->answer is available for any kind of response needed from the other
+ * processes.  (Needless to say, only one process can make a request at any
+ * one time).
+ * 
+ * Every process will wait for a second (sleep(1)), and then check the queue
+ * status, do what is appropriate, and repeat.
+ * 
+ * Above and beyond this, processes may die, and not report it (for whatever
+ * reason, and every process waiting on the queue watches the behavior of
+ * every other supposed process to make sure it is still alive).
+ * 
+ * When a space opens up, and the person who holds the number currently being
+ * served does not respond, then the processes argue over who deserves to get
+ * in next.  The first process to decide that no one is going to take the
+ * free slot says that his number is the next on to be served. He waits for
+ * anyone to disagree with him.  Any other processes which notice that their
+ * number is lower than the number being served claim that their number is
+ * the next one to be served.  They also wait for anyone to disagree with
+ * them.  Eventually, everyone is done waiting, and the process with the
+ * lowest count will be served.
+ * 
+ * Variables: status->wait:  	Number being served. status->count:	Next
+ * number to take.
+ * 
+ * status->request:	Process request. (status->number) (status->answer)
+ * REQFREE:	No requests pending. REQWHO:		How many people are
+ * before me?  In this case, every process in from of this process (whose
+ * position is recorded in status->number) increments status->answer.
+ * REQDEAD:	I am leaving the queue (Either to quit, or enter game).  Any
+ * process whose position is higher than this process will note that they are
+ * closer to the top of the queue.
+ * 
+ * (Local) waitWin:	The window. qwin:	The quit half of waitWin.
+ * countWin:	The count half of waitWin. count:	My number (Position
+ * in queue). pseudocount: Number of people in front of me (-1 means I don't
+ * know). myRequest:	This keeps track of requests I've made.  If it is non
+ * zero, then this is the number of times I will leave it there before I get
+ * my answer (if there is one), and reset status->request. idie:	This
+ * is set to one if I need to leave the queue.  When I get a chance, I will
+ * submit my request, and leave. wearein:	This is the slot we grabbed
+ * to enter the game.  If it is -1, then we haven't got a slot yet.  If we
+ * can grab a slot, then wearein is set to the slot #, and idie is set to 1.
+ * 
+ * Because we need to monitor other processes, the following variables also
+ * exist:
+ * 
+ * oldcount:	The number that was being served last time I looked. waits:
+ * Number of times I've seen oldcount as the number being served. If a
+ * position opens in the game, and no one takes it for a while, we assume
+ * that someone died. lastRequest:	The last request I have seen.
+ * lastNumber:	The process making this request. reqCount:	Number of
+ * times I've seen this request.  If I see this request 9 times, I assume it
+ * is obsolete, and I reset it.
+ */
+
+int
+grabslot(overload, homeaway)
+  int overload;			/* Indicates a request for a tester's slot. */
+  enum HomeAway homeaway;
+{
+  int count;			/* My number */
+  int oldcount;			/* Number that was being served last check */
+  int i;
+  int waits;			/* # times I have waited for someone else to
+				 * act */
+  int oldwait;			/* Number being served last check */
+  int pseudocount = -1;		/* Count on queue for sake of person waiting */
+  int myRequest = 0;		/* To keep track of any request I'm making */
+  int lastRequest = 0;		/* Last request I've seen */
+  int lastNumber = 0;		/* Last person making request */
+  int reqCount = 0;		/* Number of times I've seen this */
+  int idie = 0;			/* Do I want to die? */
+  int wearein = -1;		/* Slot we got in the game */
+  int rep = 0;
+
+  /* If other players waiting, we get in line behind them */
+  if (!overload && status->wait != status->count)
+  {
+    count = status->count++;
+  }
+  else
+  {
+    /* Get in game if posible */
+#if 1
+    i = allocate_slot(homeaway, overload, 1);
+    if (i >= 0)
+      return i;
+#else
+    if (overload)
+      for (i = MAXPLAYER - 1; i >= 0; i--)
+      {
+	if (players[i].p_status == PFREE)
+	{			/* We have a free slot */
+	  players[i].p_status = POUTFIT;	/* possible race code */
+	  players[i].p_team = NOBODY;
+	  return (i);
+	}
+      }
+    else
+      for (i = 0; i < MAXPLAYER - configvals->ntesters; i++)
+      {
+	if (ImAllowed(i, homeaway)
+	    && players[i].p_status == PFREE)
+	{			/* We have a free slot */
+	  players[i].p_status = POUTFIT;	/* possible race code */
+	  players[i].p_team = NOBODY;
+	  return (i);
+	}
+      }
+#endif
+    /* Game full.  We will wait. */
+    count = status->count++;
+  }
+  waits = 0;
+  oldwait = -1;
+  oldcount = status->wait;
+
+  /* For count = 0,1,2  I know that it is right */
+  if (count - status->wait < 1)
+  {
+    pseudocount = count - status->wait;
+  }
+  for (;;)
+  {
+    /* Send packets occasionally to see if he is accepting... */
+    if (rep++ % 10 == 0)
+    {
+      mapWaitCount(pseudocount);
+    }
+    if (isClientDead())
+    {
+      if (count == status->count - 1)
+      {
+	status->count--;
+	exit(0);
+      }
+      /* If we are at top, decrease it */
+      if (count == status->wait)
+      {
+	status->wait++;
+      }
+      idie = 1;
+      /* break;		warning, function has return e and return */
+      exit(0);
+    }
+    if (status->wait != oldcount)
+    {
+      mapWaitCount(pseudocount);
+      oldcount = status->wait;
+    }
+    /* To mimize process overhead and aid synchronization */
+    sleep(1);
+    /* Message from daemon that it died */
+    if (status->count == 0)
+      exit(0);
+    /* I have a completed request? */
+    if (myRequest != 0 && --myRequest == 0)
+    {
+      if (idie && status->request == REQDEAD)
+      {
+	status->request = REQFREE;
+	/* Out of queue, into game */
+	if (wearein != -1)
+	{
+	  return (wearein);
+	}
+	exit(0);
+      }
+      pseudocount = status->answer;
+      status->request = REQFREE;
+      if (pseudocount > 18)
+	idie = 1;
+      mapWaitCount(pseudocount);
+    }
+    /* Tell the world I am going bye bye */
+    if (idie && status->request == REQFREE)
+    {
+      status->request = REQDEAD;
+      status->number = count;
+      myRequest = 4;
+    }
+    /* Should I request a count for # of people waiting? */
+    if (pseudocount == -1 && status->request == REQFREE)
+    {
+      status->request = REQWHO;
+      status->number = count;
+      status->answer = 0;
+      myRequest = 4;
+      /* I give people 4 seconds to respond */
+    }
+    /* Is someone else making a request? */
+    if (status->request != REQFREE && myRequest == 0)
+    {
+      if (status->request == lastRequest &&
+	  status->number == lastNumber)
+      {
+	reqCount++;
+	/* 9 occurances of the same request implies that the process */
+	/* died.  I will reset request. */
+	if (reqCount > 8)
+	{
+	  status->request = REQFREE;
+	}
+      }
+      else
+      {
+	lastRequest = status->request;
+	lastNumber = status->number;
+	reqCount = 1;
+	if (lastRequest == REQWHO)
+	{
+	  if (count < lastNumber)
+	  {
+	    status->answer++;
+	  }
+	}
+	else if (lastRequest == REQDEAD)
+	{
+	  if (count > lastNumber && pseudocount != -1)
+	  {
+	    pseudocount--;
+	    mapWaitCount(pseudocount);
+	  }
+	}
+      }
+    }
+    /* If someone raised wait too high, I claim that I * am next in line */
+    if (status->wait > count && !idie)
+    {
+      status->wait = count;
+      /* Give people a chance to correct me */
+      sleep(2);
+    }
+#if 1
+    if (idie)
+      continue;
+    if (count == status->wait)
+    {
+      i = allocate_slot(homeaway, overload, 1);
+      if (i < 0)
+	continue;
+      status->wait++;
+      wearein = i;
+      idie = 1;
+    }
+    else
+    {
+      i = allocate_slot(homeaway, overload, 0);
+      if (i < 0)
+	continue;
+      if (oldwait == status->wait)
+      {
+	waits++;
+      }
+      else
+      {
+	oldwait = status->wait;
+	waits = 1;
+      }
+      /* If this is our fifth wait (5 sec), then something is */
+      /* wrong.  We assume someone died, and fix this problem */
+      if (waits == 5 && !idie)
+      {
+	/* I want to be next in line, so I say so. */
+	status->wait = count;
+	/* And I allow someone to correct me if I'm wrong */
+	sleep(2);
+	waits = 0;
+      }
+
+    }
+#else
+    for (i = 0; i < MAXPLAYER - configvals->ntesters; i++)
+    {
+      /* If we want to die anyway, we have no right looking for */
+      /* a free slot */
+      if (idie)
+	break;
+      if (ImAllowed(i, homeaway) && players[i].p_status == PFREE)
+      {
+	/* If I am next in line... */
+	if (count == status->wait)
+	{
+	  players[i].p_status = POUTFIT;
+	  players[i].p_team = NOBODY;
+	  /* Increase count for next player */
+	  status->wait++;
+	  /* I should check idie, but maybe he wants in, eh? */
+	  wearein = i;
+	  idie = 1;
+	  break;
+	}
+	else
+	{
+	  if (oldwait == status->wait)
+	  {
+	    waits++;
+	  }
+	  else
+	  {
+	    oldwait = status->wait;
+	    waits = 1;
+	  }
+	  /* If this is our fifth wait (5 sec), then something is */
+	  /* wrong.  We assume someone died, and fix this problem */
+	  if (waits == 5 && !idie)
+	  {
+	    /* I want to be next in line, so I say so. */
+	    status->wait = count;
+	    /* And I allow someone to correct me if I'm wrong */
+	    sleep(2);
+	    waits = 0;
+	  }
+	  break;
+	}
+      }
+    }
+#endif
+    /* this location is skipped if we didn't find a slot */
+  }
+}
+
+void
+mapWaitCount(count)
+  unsigned int count;
+{
+  if (count == -1)
+    return;
+
+  sendQueuePacket((short) count);
+  blk_flag = 1;
+  updateMOTD();
+  blk_flag = 0;
+
+  undeferDeferred();		/* send the MOTD through the TCP buffers */
+  flushSockBuf();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/gameconf.c	Sat Dec 06 04:37:03 1997 +0000
@@ -0,0 +1,343 @@
+/*--------------------------------------------------------------------------
+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 <sys/types.h>
+#include <stdio.h>
+#include <netinet/in.h>
+#include "defs.h"
+#include "gppackets.h"
+#include "shmem.h"
+#include "data.h"
+
+/* some game params packet stuff */
+/* status experimental */
+
+void
+updateGPrank()
+{
+  int i;
+  struct gp_rank_spacket pkt;
+
+  pkt.type = SP_GPARAM;
+  pkt.subtype = 5;
+
+  for (i = 0; i < NUMRANKS; i++)
+  {
+    pkt.rankn = i;
+    pkt.genocides = htonl(ranks[i].genocides);
+#ifndef BAD_SVR4_HACKS
+    pkt.milliDI = htonl(1000 * ranks[i].di);
+    pkt.millibattle = htonl(1000 * ranks[i].battle);
+    pkt.millistrat = htonl(1000 * ranks[i].strategy);
+    pkt.millispec = htonl(1000 * ranks[i].specship);
+#else				/* Unixware/IRIX requires explicit casts */
+    /* this next define will make the next more readable */
+#define BAD_SVR4_HACKS_CAST(a,b) (unsigned long)( (long double)a * (long double)b )
+    pkt.milliDI = htonl(BAD_SVR4_HACKS_CAST(1000, ranks[i].di));
+    pkt.millibattle = htonl(BAD_SVR4_HACKS_CAST(1000, ranks[i].battle));
+    pkt.millistrat = htonl(BAD_SVR4_HACKS_CAST(1000, ranks[i].strategy));
+    pkt.millispec = htonl(BAD_SVR4_HACKS_CAST(1000, ranks[i].specship));
+#endif				/* BAD_SVR4_HACKS */
+    strcpy(pkt.name, ranks[i].name);
+
+    sendClientPacket((struct player_spacket *) & pkt);
+  }
+}
+
+void
+updateGProyal()
+{
+  int i;
+  struct gp_royal_spacket pkt;
+
+  pkt.type = SP_GPARAM;
+  pkt.subtype = 6;
+
+  for (i = 0; i < NUMROYALRANKS; i++)
+  {
+    pkt.rankn = i;
+    strcpy(pkt.name, royal[i].name);
+    sendClientPacket((struct player_spacket *) & pkt);
+  }
+}
+
+void
+updateGPteams()
+{
+  struct gp_team_spacket pkt;
+  int i;
+
+  for (i = 0; i < NUMTEAM; i++)
+  {
+    pkt.type = SP_GPARAM;
+    pkt.subtype = 1;
+
+    pkt.index = i;
+    pkt.letter = teams[idx_to_mask(i)].letter;
+    strncpy(pkt.shortname, teams[idx_to_mask(i)].shortname,
+	    sizeof(pkt.shortname));
+    strncpy(pkt.teamname, teams[idx_to_mask(i)].name, sizeof(pkt.teamname));
+
+    sendClientPacket((struct player_spacket *) & pkt);
+  }
+}
+
+static void
+send_one_teamlogo(teamidx, data, width, height)
+  int teamidx;
+  unsigned char *data;
+  int width, height;
+{
+  struct gp_teamlogo_spacket pkt;
+  int pwidth;
+
+  if (width > 99 || height > 99)
+  {
+    printf("logo too big: %dx%d\n", width, height);
+    return;
+  }
+
+  pkt.type = SP_GPARAM;
+  pkt.subtype = 2;
+
+  pkt.logowidth = width;
+  pkt.logoheight = height;
+  pkt.teamindex = teamidx;
+
+  pwidth = (width - 1) / 8 + 1;
+  pkt.thisheight = sizeof(pkt.data) / pwidth;
+
+  for (pkt.y = 0; pkt.y < height; pkt.y += pkt.thisheight)
+  {
+
+    if (pkt.y + pkt.thisheight > height)
+      pkt.thisheight = height - pkt.y;
+
+    memcpy(pkt.data, data + pkt.y * pwidth, pkt.thisheight * pwidth);
+    sendClientPacket((struct player_spacket *) & pkt);
+  }
+}
+
+void
+updateGPteamlogos()
+{
+  char buf[40];
+  char *data;
+  int width, height;
+  int i;
+
+  for (i = 0; i < NUMTEAM; i++)
+  {
+    sprintf(buf, "artwork/%d/logo", i);
+#ifdef LEAGUE_SUPPORT
+    if (status2->league == 1)
+    {
+      if (i == 0)
+	sprintf(buf, "artwork/%s/logo", status2->home.name);
+      else if (i == 1)
+	sprintf(buf, "artwork/%s/logo", status2->away.name);
+    }
+    else if (status2->league)
+    {
+      if (i == status2->home.index)
+	sprintf(buf, "artwork/%s/logo", status2->home.name);
+      else if (i == status2->away.index)
+	sprintf(buf, "artwork/%s/logo", status2->away.name);
+    }
+#endif
+    {
+      FILE *fp;
+      fp = fopen(build_path(buf), "r");
+      if (!fp)
+	continue;		/* no image to transmit */
+      ParseXbmFile(fp, &width, &height, &data);
+      fclose(fp);
+    }
+    if (!data)
+    {
+      continue;
+    }
+    send_one_teamlogo(i, data, width, height);
+    free(data);
+  }
+}
+
+/* #include "borgcube.bm" */
+
+void
+updateGPshipshapes()
+{
+#if 0
+  {
+    struct gp_shipshape_spacket pkt;
+
+    pkt.type = SP_GPARAM;
+    pkt.subtype = 3;
+
+    pkt.shipno = ATT;
+    pkt.race = -1;
+    pkt.nviews = 1;
+    pkt.width = borgcube_width;
+    pkt.height = borgcube_height;
+
+    sendClientPacket((struct player_spacket *) & pkt);
+  }
+
+  {
+    struct gp_shipbitmap_spacket pkt;
+
+    pkt.type = SP_GPARAM;
+    pkt.subtype = 4;
+
+    pkt.shipno = ATT;
+    pkt.race = -1;
+    pkt.thisview = 0;
+
+    memcpy(pkt.bitmapdata, borgcube_bits, sizeof(borgcube_bits));
+
+    sendClientPacket((struct player_spacket *) & pkt);
+  }
+#endif
+}
+
+void
+updateGPplanetbitmaps()
+{
+  struct gp_teamplanet_spacket pkt;
+  char buf[40];
+  char *data;
+  int width, height;
+  int i;
+
+  for (i = 0; i < NUMTEAM; i++)
+  {
+
+    pkt.type = SP_GPARAM;
+    pkt.subtype = 7;
+
+    pkt.teamn = i;
+
+    sprintf(buf, "artwork/%d/tplanet", i);
+#ifdef LEAGUE_SUPPORT
+    if (status2->league == 1)
+    {
+      if (i == 0)
+	sprintf(buf, "artwork/%s/tplanet", status2->home.name);
+      else if (i == 1)
+	sprintf(buf, "artwork/%s/tplanet", status2->away.name);
+    }
+    else if (status2->league)
+    {
+      if (i == status2->home.index)
+	sprintf(buf, "artwork/%s/tplanet", status2->home.name);
+      else if (i == status2->away.index)
+	sprintf(buf, "artwork/%s/tplanet", status2->away.name);
+    }
+#endif
+    {
+      FILE *fp;
+      fp = fopen(build_path(buf), "r");
+      if (!fp)
+	continue;		/* no image to transmit */
+      ParseXbmFile(fp, &width, &height, &data);
+      fclose(fp);
+    }
+    if (!data)
+    {
+      continue;
+    }
+    memcpy(pkt.tactical, data, 120);
+    memcpy(pkt.tacticalM, data, 120);
+    free(data);
+
+    sprintf(buf, "artwork/%d/gplanet", i);
+#ifdef LEAGUE_SUPPORT
+    if (status2->league == 1)
+    {
+      if (i == 0)
+	sprintf(buf, "artwork/%s/gplanet", status2->home.name);
+      else if (i == 1)
+	sprintf(buf, "artwork/%s/gplanet", status2->away.name);
+    }
+    else if (status2->league)
+    {
+      if (i == status2->home.index)
+	sprintf(buf, "artwork/%s/gplanet", status2->home.name);
+      else if (i == status2->away.index)
+	sprintf(buf, "artwork/%s/gplanet", status2->away.name);
+    }
+#endif
+    {
+      FILE *fp;
+      fp = fopen(build_path(buf), "r");
+      if (!fp)
+	continue;		/* no image to transmit */
+      ParseXbmFile(fp, &width, &height, &data);
+      fclose(fp);
+    }
+    if (!data)
+    {
+      continue;
+    }
+    memcpy(pkt.galactic, data, 32);
+    memcpy(pkt.galacticM, data, 32);
+    free(data);
+
+    sendClientPacket((struct player_spacket *) & pkt);
+  }
+
+}
+
+void
+updateGameparams()
+{
+  struct gp_sizes_spacket pkt;
+
+  memset((char *) &pkt, 0, sizeof(pkt));
+
+  pkt.type = SP_GPARAM;
+  pkt.subtype = 0;
+
+  pkt.nplayers = MAXPLAYER;
+  pkt.nteams = 4;
+  pkt.nshiptypes = NUM_TYPES;
+  pkt.nranks = NUMRANKS;
+  pkt.nroyal = NUMROYALRANKS;
+  pkt.nphasers = 1;
+  pkt.ntorps = MAXTORP;
+  pkt.nplasmas = MAXPLASMA;
+  pkt.nthingies = NPTHINGIES;
+  pkt.gthingies = NGTHINGIES;
+  pkt.gwidth = GWIDTH;
+  pkt.flags = 0;
+  pkt.nplanets = configvals->numplanets;
+  sendClientPacket((struct player_spacket *) & pkt);
+
+  updateGPteams();
+  if (me == 0 || !(me->p_stats.st_flags & ST_NOBITMAPS))
+  {
+    updateGPteamlogos();
+    updateGPshipshapes();
+    updateGPplanetbitmaps();
+  }
+  updateGPrank();
+  updateGProyal();
+}
+
+/* end game params stuff */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/getentry.c	Sat Dec 06 04:37:03 1997 +0000
@@ -0,0 +1,421 @@
+/*--------------------------------------------------------------------------
+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/time.h>
+#include "defs.h"
+#include "struct.h"
+#include "data.h"
+#include "packets.h"
+#include "shmem.h"
+
+extern int overload;		/* 7/31/91 TC let overloaded join any team */
+
+extern int updateShips();
+extern int sendMaskPacket();
+int tournamentMask();
+extern int briefUpdateClient();
+extern int flushSockBuf();
+extern int socketPause();
+extern int readFromClient();
+extern int isClientDead();
+extern int exitGame();
+#ifndef	IRIX
+extern int printf();
+#endif
+extern int closeUdpConn();
+extern unsigned int sleep();
+extern int connectToClient();
+extern int updateSelf();
+extern int sendPickokPacket();
+extern int allowed_ship();
+extern int time_access();
+int deadTeam();
+int realNumShips();
+
+#if 1
+
+void
+detourneyqueue()
+{
+  me->p_status = POUTFIT;
+  me->p_whydead = KPROVIDENCE;
+}
+
+#endif
+
+
+void
+getEntry(team, stype)
+  int *team;
+  int *stype;
+{
+
+
+  int switching = -1;		/* confirm switches 7/27/91 TC */
+  inputMask = CP_OUTFIT;
+  for (;;)
+  {
+    /* updateShips so he knows how many players on each team */
+    if (blk_flag)
+      updateShips();
+    sendMaskPacket(tournamentMask(me->p_team));
+    if (blk_flag)
+      briefUpdateClient();
+    flushSockBuf();
+    /* Have we been busted? */
+    if (me->p_status == PFREE)
+    {
+      me->p_status = PDEAD;
+      me->p_explode = 600;
+    }
+    socketPause();
+    readFromClient();
+    if (isClientDead())
+    {
+      int i;
+
+      if (noressurect)
+	exitGame();
+      printf("Ack!  The client went away!\n");
+      printf("I will attempt to resurrect him!\n");
+
+      /* UDP fail-safe */
+      commMode = COMM_TCP;
+      if (udpSock >= 0)
+	closeUdpConn();
+
+      /* For next two minutes, we try to restore connection */
+      shutdown(sock, 2);
+      sock = -1;
+      for (i = 0;; i++)
+      {
+	switch (me->p_status)
+	{
+	 case PFREE:
+	  me->p_status = PDEAD;
+	  me->p_explode = 600;
+	  break;
+	 case PALIVE:
+	 case POBSERVE:
+	  me->p_ghostbuster = 0;
+	  break;
+	 case PDEAD:
+	  me->p_explode = 600;
+	  break;
+	 default:
+	  me->p_explode = 600;
+	  me->p_ghostbuster = 0;
+	  break;
+	}
+	sleep(5);
+	if (connectToClient(host, nextSocket))
+	  break;
+	if (i == 23)
+	{
+	  printf("Oh well, maybe I'm getting rusty!\n");
+	  switch (me->p_status)
+	  {
+	   case PFREE:
+	    break;
+	   case PALIVE:
+	   case POBSERVE:
+	    me->p_ghostbuster = 100000;
+	    break;
+	   case PDEAD:
+	    me->p_explode = 0;
+	    break;
+	   default:
+	    me->p_explode = 0;
+	    me->p_ghostbuster = 100000;
+	    break;
+	  }
+	  exitGame();
+	}
+      }
+      printf("A miracle!  He's alive!\n");
+      teamPick = -1;
+      updateSelf();
+      updateShips();
+      flushSockBuf();
+    }
+    if (teamPick != -1)
+    {
+      if (teamPick < 0 || teamPick > 3)
+      {
+	warning("Get real!");
+	sendPickokPacket(0);
+	teamPick = -1;
+	continue;
+      }
+#if 1
+      if (!(tournamentMask(me->p_team) & (1 << teamPick)))
+      {
+	warning("I cannot allow that.  Pick another team");
+	sendPickokPacket(0);
+	teamPick = -1;
+	continue;
+      }
+#endif
+
+      if (((1 << teamPick) != me->p_team) &&
+	  (me->p_team != ALLTEAM))	/* switching teams 7/27/91 TC */
+	if ((switching != teamPick)
+	    && (me->p_whydead != KGENOCIDE)
+#ifdef LEAGUE_SUPPORT
+	    && !status2->league
+#endif
+	  )
+	{
+	  switching = teamPick;
+	  warning("Please confirm change of teams.  Select the new team again.");
+	  sendPickokPacket(0);
+	  teamPick = -1;
+	  continue;
+	}
+      /* His team choice is ok. */
+      if (shipPick < 0 || shipPick >= NUM_TYPES)
+      {
+	warning("That is an illegal ship type.  Try again.");
+	sendPickokPacket(0);
+	teamPick = -1;
+	continue;
+      }
+      if (!allowed_ship(1 << teamPick, mystats->st_rank, mystats->st_royal, shipPick))
+      {
+	sendPickokPacket(0);
+	teamPick = -1;
+	continue;
+      }
+      if (shipvals[shipPick].s_nflags & SFNMASSPRODUCED)
+      {
+	warning("o)utpost, u)tility, or s)tandard?");
+	sendPickokPacket(0);
+	tmpPick = shipPick;
+	continue;
+      }
+      break;
+    }
+#if 1
+    if (me->p_status == PTQUEUE)
+    {
+      if (status->tourn)
+	detourneyqueue();
+      /* You don't time out on the tourney queue */
+      me->p_ghostbuster = 0;
+    }
+#endif
+  }
+  *team = teamPick;
+  if ((shipvals[tmpPick].s_nflags & SFNMASSPRODUCED) &&
+      ((shipvals[shipPick].s_numports) || (shipPick == SCOUT)))
+  {
+
+    *stype = tmpPick;
+    tmpPick = CRUISER;
+  }
+  else
+  {
+    *stype = shipPick;
+    tmpPick = CRUISER;
+  }
+  sendPickokPacket(1);
+  flushSockBuf();
+}
+
+
+
+
+/*------------------------------TOURNAMENTMASK----------------------------*/
+/*
+ * This function takes the players current team and returns a mask of the
+ * teams that the player can join.
+ */
+
+int
+leaguemask(ishome, idx)
+  int ishome;			/* team index */
+  int idx;
+{
+#ifdef LEAGUE_SUPPORT
+  if (status2->league == 1)
+    return idx_to_mask(ishome);
+  else
+#endif
+    return idx_to_mask(idx);
+}
+
+int
+tournamentMask(team)
+  int team;			/* players current team */
+{
+  int i;			/* looping var */
+  int team1, team2;		/* for getting two possible teams */
+  int num1, num2;		/* to hold num players on teams */
+
+  if (!blk_flag)		/* not a paradise client */
+    return (0);
+  if (status->gameup == 0)	/* if game over, can join no team */
+    return (0);
+  if (overload)			/* if tester slot then can join */
+    return (ALLTEAM);		/* any team */
+  if (mustexit)			/* should we force player out */
+    return (0);
+  if (!time_access())		/* if server closed then can join */
+    return (0);			/* no team */
+
+#ifdef LEAGUE_SUPPORT
+  /* league stuff */
+  if (status2->league)
+  {
+    if (me->p_homeaway == AWAY)
+      return leaguemask(1, status2->away.index);
+    else if (me->p_homeaway == HOME)
+      return leaguemask(0, status2->home.index);
+    else
+    {
+      warning("You have connected to a league server but aren't on a side.");
+      me->p_homeaway = (lrand48() & 1) + 1;	/* dangerous int->enum cast */
+      return 0;
+    }
+    /* NOTREACHED */
+  }
+#endif
+  if (me->p_homeaway != NEITHER)
+  {
+    warning("You have connected to a non-league server with a league ntserv.");
+    me->p_homeaway = NEITHER;
+  }
+
+  if (!status->tourn)
+  {
+    return status2->nontteamlock;
+  }
+
+  if (team != ALLTEAM && deadTeam(team))	/* if former team dead */
+    team = ALLTEAM;		/* then check all others */
+  for (i = 0; i < NUMTEAM; i++)
+  {				/* go through all teams and eliminate */
+    if ((team & (1 << i)) && (deadTeam(1 << i)))	/* from team var all
+							 * teams */
+      team &= ~(1 << i);	/* that are dead */
+  }
+  team1 = 0;			/* no team in team 1 */
+  num1 = 0;			/* 0 players on team 1 */
+  team2 = 0;			/* no team in team 2 */
+  num2 = 0;			/* 0 players on team 2 */
+  for (i = 0; i < NUMTEAM; i++)
+  {				/* go through all teams */
+    if (deadTeam(1 << i))	/* if team is dead then */
+      continue;			/* disregard it */
+    if (realNumShips(1 << i) >= configvals->tournplayers)
+    {				/* enough players */
+      if (!team1)		/* if no team in team1 yet */
+	team1 = (1 << i);	/* then this will be team 1 */
+      else
+      {				/* otherwise its team2 */
+	team2 = (1 << i);
+	num1 = realNumShips(team1);	/* get num players on two teams */
+	num2 = realNumShips(team2);
+	if (num1 == num2)
+	{			/* if teams same size then */
+	  if (team & (team1 | team2))	/* if player on one team */
+	    return (team & (team1 | team2));	/* let him join same team */
+	  return (team1 | team2);	/* otherwise, he can join either */
+	}
+	else if ((num1 > num2) && (team != team1))
+	  return (team2);	/* if slight imabalance */
+	else if ((num1 < num2) && (team != team2))
+	  return (team1);	/* if slight imbalance */
+	else
+	{
+	  if (ABS(num1 - num2) < 2 || (((num1 > num2) && (team == team2)) ||
+				       (num2 > num1 && team == team1)))
+	    return (team);
+	  else
+	    return (team1 | team2);
+	}
+      }
+    }
+  }				/* end of for loop */
+  return (team);		/* just in case */
+}
+
+
+
+
+/*--------------------------------REALNUMSHIPS-----------------------------*/
+/*
+ * Count the real number of ships on a team.  This function returns a count
+ * of all the ships on a team that are not PFREE.
+ */
+
+int
+realNumShips(owner)
+  int owner;			/* the team to check for */
+{
+  int i;			/* looping var */
+  int num;			/* to hold ship count */
+  struct player *p;		/* to point to players */
+
+  num = 0;			/* initialize count */
+  for (i = 0, p = players; i < MAXPLAYER; i++, p++)
+  {
+    if ((p->p_status != PFREE) &&
+	!(p->p_flags & (PFSNAKE | PFBIRD)) &&
+	(p->p_team == owner))
+    {
+      num++;			/* if ship not free and on our team */
+    }
+  }
+  return (num);			/* retun number of ships */
+}
+
+
+
+
+/*----------------------------------DEADTEAM-------------------------------*/
+/*
+ * This function counts the number of planets that a team owns.  It returns a
+ * 1 if the team has no planets, and a 0 if they have at least one planet.
+ */
+
+int
+deadTeam(owner)
+  int owner;			/* team to check for */
+{
+  int i;			/* looping var */
+  struct planet *p;		/* to point to a planets */
+
+  for (i = 0, p = planets; i < NUMPLANETS; i++, p++)
+  {
+    if (p->pl_owner & owner)	/* if planet owned by team then */
+      return (0);		/* found one planet owned by team */
+  }
+  return (1);			/* no planets found, team is dead */
+}
+
+/*-------------------------------------------------------------------------*/
+
+
+
+
+
+/*---------END OF FILE--------*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/getname.c	Sat Dec 06 04:37:03 1997 +0000
@@ -0,0 +1,287 @@
+/*--------------------------------------------------------------------------
+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/stat.h>
+#include <sys/file.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <sys/time.h>
+#ifndef ULTRIX
+#include <sys/fcntl.h>
+#endif
+#include <errno.h>
+#include <pwd.h>
+#include <string.h>
+#include <ctype.h>
+#include <time.h>
+#include "defs.h"
+#include "struct.h"
+#include "data.h"
+#include "packets.h"
+#include "path.h"
+#include "shmem.h"
+
+#define crypt(a, b) (a)
+
+void handleLogin();
+extern int exitGame();
+extern int isClientDead();
+extern int socketPause();
+extern int readFromClient();
+int lockout();
+extern int sendClientLogin();
+extern int flushSockBuf();
+#ifdef BAD_SVR4_HACKS
+int updateMOTD();
+#else
+extern int updateMOTD();
+#endif
+#ifndef	IRIX
+extern int printf();
+#endif
+extern int read();
+extern int close();
+extern off_t lseek();
+extern int write();
+extern time_t time();
+
+/* replace non-printable characters in string with spaces */
+static void
+remove_ctl(str)
+  char *str;
+{
+  while (*str)
+  {
+    if (!isgraph(*str))		/* not a printable character */
+      *str = ' ';		/* replace it with space */
+    str++;
+  }
+}
+
+void
+getname()
+/* Let person identify themselves from w */
+{
+  *(me->p_name) = 0;
+  while (*(me->p_name) == 0)
+  {
+    handleLogin();
+  }
+}
+
+void
+handleLogin()
+{
+  static struct statentry player;
+  static int position = -1;
+  int plfd;
+  int entries;
+  struct stat buf;
+  char *paths;
+
+  paths = build_path(PLAYERFILE);
+  *namePick = '\0';
+  inputMask = CP_LOGIN;
+  while (*namePick == '\0')
+  {
+    /* Been ghostbusted? */
+    if (me->p_status == PFREE)
+      exitGame();
+    if (isClientDead())
+      exitGame();
+    socketPause();
+    readFromClient();
+  }
+#ifdef REMOVE_CTL		/* untested */
+  /* Change those annoying control characters to spaces */
+  remove_ctl(namePick);
+#endif
+  if ((strcmp(namePick, "Guest") == 0 || strcmp(namePick, "guest") == 0) &&
+      !lockout())
+  {
+    hourratio = 5;
+    memset(&player.stats, 0, sizeof(struct stats));
+    player.stats.st_tticks = 1;
+    player.stats.st_flags = ST_INITIAL;
+    /*
+     * If this is a query on Guest, the client is screwed, but I'll send him
+     * some crud anyway.
+     */
+    if (passPick[15] != 0)
+    {
+      sendClientLogin(&player.stats);
+      flushSockBuf();
+      return;
+    }
+    sendClientLogin(&player.stats);
+
+    updateMOTD();		/* added here 1/19/93 KAO */
+
+    flushSockBuf();
+    strcpy(me->p_name, namePick);
+    me->p_pos = -1;
+    memcpy(&(me->p_stats), &player.stats, sizeof(struct stats));
+    return;
+  }
+  hourratio = 1;
+  /* We look for the guy in the stat file */
+  if (strcmp(player.name, namePick) != 0)
+  {
+    for (;;)
+    {				/* so I can use break; */
+      plfd = open(paths, O_RDONLY, 0644);
+      if (plfd < 0)
+      {
+	printf("I cannot open the player file!\n");
+	strcpy(player.name, namePick);
+	position = -1;
+	printf("Error number: %d\n", errno);
+	break;
+      }
+      position = 0;
+      while (read(plfd, (char *) &player, sizeof(struct statentry)) ==
+	     sizeof(struct statentry))
+      {
+#ifdef REMOVE_CTL		/* untested */
+	/*
+	 * this is a temporary thing to remove control chars from existing
+	 * entries in the player db
+	 */
+	remove_ctl(player.name);
+#endif
+	if (strcmp(namePick, player.name) == 0)
+	{
+	  close(plfd);
+	  break;
+	}
+	position++;
+      }
+      if (strcmp(namePick, player.name) == 0)
+	break;
+      close(plfd);
+      position = -1;
+      strcpy(player.name, namePick);
+      break;
+    }
+  }
+  /* Was this just a query? */
+  if (passPick[15] != 0)
+  {
+    if (position == -1)
+    {
+      sendClientLogin(NULL);
+    }
+    else
+    {
+      sendClientLogin(&player.stats);
+    }
+    flushSockBuf();
+    return;
+  }
+  /* A new guy? */
+  if ((position == -1) && !lockout())
+  {
+    strcpy(player.name, namePick);
+    strcpy(player.password, crypt(passPick, namePick));
+    memset(&player.stats, 0, sizeof(struct stats));
+    player.stats.st_tticks = 1;
+    player.stats.st_flags = ST_INITIAL;
+    player.stats.st_royal = 0;
+    plfd = open(paths, O_RDWR | O_CREAT, 0644);
+    if (plfd < 0)
+    {
+      sendClientLogin(NULL);
+    }
+    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));
+      strcpy(me->p_name, namePick);
+      sendClientLogin(&player.stats);
+      updateMOTD();		/* added here 1/19/93 KAO */
+    }
+    flushSockBuf();
+    return;
+  }
+  /* An actual login attempt */
+  if ((strcmp(player.password, crypt(passPick, player.password)) != 0) ||
+      lockout())
+  {
+    sendClientLogin(NULL);
+  }
+  else
+  {
+    strcpy(me->p_name, namePick);
+    me->p_pos = position;
+    memcpy(&(me->p_stats), &player.stats, sizeof(struct stats));
+
+    sendClientLogin(&player.stats);
+
+    updateMOTD();		/* st_flags&ST_NOBITMAPS */
+  }
+  flushSockBuf();
+
+#if 1
+  /* Try to make the first person in the player database an Emperor */
+  if (position == 0)
+    me->p_stats.st_royal = NUMROYALRANKS - 1;
+#endif
+
+  return;
+}
+
+void
+savestats()
+{
+  int fd;
+  char *paths;
+
+  if (me->p_pos < 0)
+    return;
+
+  paths = build_path(PLAYERFILE);
+
+  fd = open(paths, 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);
+  }
+}
+
+/* return true if we want a lockout */
+int
+lockout()
+{
+  return (
+  /*
+   * (strncmp (login, "bozo", 4) == 0) ||
+   */
+	  0
+  );
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/getship.c	Sat Dec 06 04:37:03 1997 +0000
@@ -0,0 +1,114 @@
+/*--------------------------------------------------------------------------
+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"
+
+
+
+
+/*-------------------------------INTERNAL FUNCTONS------------------------*/
+
+/*----------------------------------GETSHIP--------------------------------*/
+/*
+ * This function gets the particular ship type the player wants.  It takes
+ * the ship values from the shipvals array.
+ */
+
+void
+getship(shipp, s_type)
+  struct ship *shipp;		/* the ship structure to load */
+  int s_type;			/* the type of ship to get */
+{
+  memcpy((char *) shipp, (char *) &(shipvals[s_type]), sizeof(struct ship));
+}
+
+
+
+/*------------------------------------------------------------------------*/
+
+
+
+
+
+void
+get_ship_for_player(me, s_type)
+  struct player *me;
+  int s_type;
+{
+  getship(&me->p_ship, s_type);
+
+  me->p_shield = me->p_ship.s_maxshield;	/* shields are at max */
+  me->p_damage = 0;		/* no damage to ship */
+  me->p_subdamage = 0;		/* no fractional damage either */
+  me->p_subshield = 0;		/* no fractional damage to shield */
+
+  me->p_fuel = me->p_ship.s_maxfuel;	/* fuel is at max */
+  me->p_etemp = 0;		/* engines are ice cold */
+  me->p_etime = 0;		/* not counting down for E-temp */
+  me->p_warptime = 0;		/* we are not preparing for warp */
+  me->p_wtemp = 0;		/* weapons cool too */
+  me->p_wtime = 0;		/* not counting down for W-temp */
+
+  if (allows_docking(me->p_ship))
+  {				/* if ship can be docked to */
+    int i;
+    me->p_docked = 0;		/* then set all ports as */
+    for (i = 0; i < MAXPORTS; i++)	/* vacant */
+      me->p_port[i] = VACANT;
+  }
+  if (weaponsallowed[WP_MISSILE] &&
+      (me->p_ship.s_missilestored > 0) &&
+      (me->p_kills >= configvals->mskills))
+  {
+    me->p_ship.s_nflags |= SFNHASMISSILE;	/* arm ship with missile
+						 * launcher */
+  }
+  if (!(me->p_ship.s_nflags & SFNHASMISSILE))
+  {
+    me->p_ship.s_missilestored = 0;	/* no missiles if no launcher */
+  }
+  if (weaponsallowed[WP_PLASMA] &&
+      (me->p_ship.s_plasma.cost > 0) &&
+      (me->p_kills >= configvals->plkills))
+  {
+    me->p_ship.s_nflags |= SFNPLASMAARMED;	/* arm ship with plasma
+						 * launcher */
+  }
+  me->p_specweap = 0;
+
+  /*
+   * fix this now since we can't do it right in a conf.sysdef/default/pl_gen
+   * ordering... sigh.
+   */
+  if (!configvals->warpdrive)
+    me->p_ship.s_nflags &= ~SFNCANWARP;
+}
+
+
+/*----------END OF FILE-----*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/getship.h	Sat Dec 06 04:37:03 1997 +0000
@@ -0,0 +1,30 @@
+/*--------------------------------------------------------------------------
+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 initshipvals();
+int getship();
+/*------------------------------------------------------------------------*/
+
+
+
+
+
+/*-------END OF FILE-------*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/getstats.c	Sat Dec 06 04:37:03 1997 +0000
@@ -0,0 +1,104 @@
+/*--------------------------------------------------------------------------
+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 <stdlib.h>
+
+struct stats
+{
+  int st_genocides;		/* number of genocides participated in */
+  float st_tmaxkills;		/* max kills ever */
+  float st_di;			/* total destruction inflicted for all time */
+  int st_tkills;		/* Kills in tournament play */
+  int st_tlosses;		/* Losses in tournament play */
+  int st_tarmsbomb;		/* Tournament armies bombed */
+  int st_tresbomb;		/* resources bombed off */
+  int st_tdooshes;		/* armies killed while being carried */
+  int st_tplanets;		/* Tournament planets conquered */
+  int st_tticks;		/* Tournament ticks */
+  /* SB/WB/JS stats are entirely separate */
+  int st_sbkills;		/* Kills as starbase */
+  int st_sblosses;		/* Losses as starbase */
+  int st_sbticks;		/* Time as starbase */
+  float st_sbmaxkills;		/* Max kills as starbase */
+  int st_wbkills;		/* Kills as warbase */
+  int st_wblosses;		/* Losses as warbase */
+  int st_wbticks;		/* Time as warbase */
+  float st_wbmaxkills;		/* Max kills as warbase */
+  int st_jsplanets;		/* planets assisted with in JS */
+  int st_jsticks;		/* ticks played as a JS */
+  long st_lastlogin;		/* Last time this player was played */
+  int st_flags;			/* Misc option flags */
+  char st_keymap[96];		/* keymap for this player */
+  int st_rank;			/* Ranking of the player */
+  int st_royal;			/* royaly, specialty, rank */
+};
+
+struct statentry
+{
+  char name[16];		/* player's name */
+  char password[16];		/* player's password */
+  struct stats stats;		/* player's stats */
+};
+
+
+main(argn, argv)
+  int argn;
+  char **argv;
+{
+  FILE *f;
+  struct statentry s;
+
+  f = fopen(argv[1], "r");
+  if (f == NULL)
+  {
+    printf("Cannot open players file\n");
+    exit(1);
+  }
+  while (fread(&s, sizeof(struct statentry), 1, f) == 1)
+  {
+    printf("\nPlayer: %s\n", s.name);
+    printf("Genocides: %d\n", s.stats.st_genocides);
+    printf("Maxkills: %f\n", s.stats.st_tmaxkills);
+    printf("DI: %f\n", s.stats.st_di);
+    printf("Kills: %d\n", s.stats.st_tkills);
+    printf("Losses: %d\n", s.stats.st_tlosses);
+    printf("Armies bombed: %d\n", s.stats.st_tarmsbomb);
+    printf("Resources bombed: %d\n", s.stats.st_tresbomb);
+    printf("Dooshes: %d\n", s.stats.st_tdooshes);
+    printf("Planets: %d\n", s.stats.st_tplanets);
+    printf("Time: %f\n", (float) s.stats.st_tticks / 36000.0);
+    printf("Rank: %d\n", s.stats.st_rank);
+    printf("Royalty: %d\n", s.stats.st_royal);
+
+    printf("SB kills: %d\n", s.stats.st_sbkills);
+    printf("SB losses: %d\n", s.stats.st_sblosses);
+    printf("SB time: %f\n", (float) s.stats.st_sbticks / 36000.0);
+    printf("SB maxkills: %f\n", s.stats.st_sbmaxkills);
+
+    printf("WB kills: %d\n", s.stats.st_wbkills);
+    printf("WB losses: %d\n", s.stats.st_wblosses);
+    printf("WB time: %f\n", (float) s.stats.st_wbticks / 36000.0);
+    printf("WB maxkills: %f\n", s.stats.st_wbmaxkills);
+
+    printf("JS planets: %f\n", s.stats.st_jsplanets);
+    printf("JS time: %f\n", (float) s.stats.st_jsticks / 36000.0);
+  }
+  fclose(f);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/gppackets.h	Sat Dec 06 04:37:03 1997 +0000
@@ -0,0 +1,191 @@
+/*--------------------------------------------------------------------------
+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 gppackets_h_
+#define gppackets_h_
+
+/* the definitions of {INT,CARD}{8,16,32} are in packets.h */
+#include "packets.h"
+
+struct gameparam_spacket
+{
+  INT8 type;
+  INT8 subtype;			/* this packet is not real */
+  /* generic game parameter packet */
+  INT16 pad;
+};
+
+struct gp_sizes_spacket
+{
+  INT8 type;
+  INT8 subtype;			/* =0 */
+
+  CARD8 nplayers;
+  CARD8 nteams;			/* max of 8 */
+
+  CARD8 nshiptypes;
+  CARD8 nranks;			/* number of ranks */
+  CARD8 nroyal;			/* number of royalties */
+  CARD8 nphasers;
+
+  CARD8 ntorps;
+  CARD8 nplasmas;
+  CARD8 nthingies;		/* per-player */
+  CARD8 gthingies;		/* auxiliary thingies */
+
+  CARD32 gwidth;		/* galaxy width */
+  /* 16 bytes */
+  CARD32 flags;			/* some game parameter flags */
+#define	GP_WRAPVERT	(1<<0)
+#define	GP_WRAPHORIZ	(1<<1)
+#define GP_WRAPALL	(GP_WRAPVERT|GP_WRAPHORIZ)
+
+  /*
+   * The following bytes are room for growth. The size of this packet is
+   * unimportant because it only gets sent once.  hopefully we've got plenty
+   * of room.
+   */
+  CARD16 nplanets;
+  INT16 ext1;
+
+  INT32 ext2;
+  INT32 ext3;
+  /* 32 bytes */
+
+  INT32 ext4;
+  INT32 ext5;
+  INT32 ext6;
+  INT32 ext7;
+
+  INT32 ext8;
+  INT32 ext9;
+  INT32 ext10;
+  INT32 ext11;			/* 16 ints, 64 bytes */
+};
+
+struct gp_team_spacket
+{
+  INT8 type;
+  INT8 subtype;			/* =1 */
+
+  CARD8 index;			/* team index */
+  CARD8 letter;			/* team letter 'F' */
+
+  CARD8 shortname[3];		/* non-null-terminated 3-letter abbrev 'FED' */
+  CARD8 pad;
+  /* 8 bytes */
+  CARD8 teamname[56];		/* padding to 64 byte packet */
+};
+
+struct gp_teamlogo_spacket
+{
+  /*
+   * This packet contains several adjacent rows of a team's logo bitmap Data
+   * is in raw XBM format (scanline-padded to 8 bits). Maximum bitmap size is
+   * 99x99, which takes 1287 (99x13) bytes.
+   */
+  INT8 type;
+  INT8 subtype;			/* =2 */
+
+  INT8 logowidth;		/* <= 99 */
+  INT8 logoheight;		/* <= 99 */
+
+  INT8 y;			/* y coord of the start of this packets info */
+  INT8 thisheight;		/* the height of this packet's info */
+  INT8 teamindex;		/* which team's logo this is */
+
+  CARD8 data[768 - 7];		/* pad packet to 768 bytes. */
+};
+
+struct gp_shipshape_spacket
+{
+  INT8 type;
+  INT8 subtype;			/* =3 */
+
+  CARD8 shipno;
+  INT8 race;			/* -1 is independent */
+  CARD8 nviews;			/* typically 16 */
+
+  CARD8 width, height;
+  CARD8 pad1;
+};
+
+struct gp_shipbitmap_spacket
+{
+  INT8 type;
+  INT8 subtype;			/* =4 */
+
+  CARD8 shipno;
+  INT8 race;			/* -1 is independent */
+  CARD8 thisview;		/* 0..nviews-1 */
+
+  CARD8 bitmapdata[999];
+};
+
+struct gp_rank_spacket
+{
+  INT8 type;
+  INT8 subtype;			/* =5 */
+
+  INT8 rankn;			/* rank number */
+
+  CARD8 name[-3 + 64 - 20];	/* name of the rank */
+
+  INT32 genocides;
+  INT32 milliDI;		/* DI*1000 */
+  INT32 millibattle;		/* battle*1000 */
+  INT32 millistrat;		/* strategy*1000 */
+  INT32 millispec;		/* special ships*1000 */
+};
+
+struct gp_royal_spacket
+{
+  INT8 type;
+  INT8 subtype;			/* =6 */
+
+  CARD8 rankn;			/* rank number */
+
+  CARD8 name[-3 + 64];		/* name of the rank */
+};
+
+struct gp_teamplanet_spacket
+{
+  INT8 type;
+  INT8 subtype;			/* =7 */
+
+  INT8 teamn;			/* 0..7 */
+  CARD8 pad1;
+
+  INT32 ext1;			/* extensions? */
+
+  /*
+   * Bitmaps of the team logo and masks.  The bitmap of the planet will be
+   * constructed with (mask ? logo : planet), applied bitwise. This
+   * calculation is equivalent to (logo&mask)|(planet&~mask)
+   */
+
+  /* bitmap 30x30, X bitmap format (scanline padded to 8 bits) */
+  CARD8 tactical[120];
+  CARD8 tacticalM[120];
+
+  /* bitmap 16x16, X bitmap format (scanline padded to 8 bits) */
+  CARD8 galactic[32];
+  CARD8 galacticM[32];
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/grid.c	Sat Dec 06 04:37:03 1997 +0000
@@ -0,0 +1,98 @@
+/*--------------------------------------------------------------------------
+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 "struct.h"
+#include "shmem.h"
+
+/*
+ * This function should be called any time a planet is relocated. It is in
+ * charge of updating the space grid.
+ */
+void
+move_planet(pno, x, y, isold)
+  int pno;			/* planet number */
+  int x, y;
+  int isold;			/* 0 if the planet has not yet been entered
+				 * into the grid */
+{
+  struct planet *pl = &planets[pno];
+
+  if (isold)
+  {
+    /* remove from previous space grid position */
+  }
+  pl->pl_x = x;
+  pl->pl_y = y;
+
+  /* enter into space grid */
+}
+
+void
+move_player(pno, x, y, isold)
+  int pno;			/* player number */
+  int x, y;
+  int isold;			/* 0 if the player has not yet been entered
+				 * into the grid */
+{
+  struct player *pl = &players[pno];
+
+  if (isold)
+  {
+  }
+  pl->p_x = x;
+  pl->p_y = y;
+
+  /* enter into space grid */
+}
+
+void
+move_torp(tno, x, y, isold)
+  int tno;			/* torp number */
+  int x, y;
+  int isold;			/* 0 if the torp has not yet been entered
+				 * into the grid */
+{
+  struct torp *t = &torps[tno];
+
+  if (isold)
+  {
+  }
+  t->t_x = x;
+  t->t_y = y;
+
+  /* enter into space grid */
+}
+
+void
+move_missile(dno, x, y, isold)
+  int dno;			/* missile number */
+  int x, y;
+  int isold;			/* 0 if the missile has not yet been entered
+				 * into the grid */
+{
+  struct missile *d = &missiles[dno];
+
+  if (isold)
+  {
+  }
+  d->ms_x = x;
+  d->ms_y = y;
+
+  /* enter into space grid */
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/grid.h	Sat Dec 06 04:37:03 1997 +0000
@@ -0,0 +1,32 @@
+/*--------------------------------------------------------------------------
+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 grid_h_
+#define grid_h_
+
+/* specifying an x,y of -1,-1 removes the item from the space grid */
+
+/* the current coordinates of the object in question are not relevant */
+
+void move_planet( /* pno, x, y, isold */ );
+void move_player( /* pno, x, y, isold */ );
+
+void move_torp( /* tno, x, y, isold */ );
+void move_missile( /* dno, x, y, isold */ );
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/imath.c	Sat Dec 06 04:37:03 1997 +0000
@@ -0,0 +1,226 @@
+/*--------------------------------------------------------------------------
+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
+--------------------------------------------------------------------------*/
+
+/* collection of integer math routines. [BDyess] */
+
+/*
+ * Based on (n+1)^2 = n^2 + 2n + 1 given that	1^2 = 1, then 2^2 = 1 + (2 +
+ * 1) = 1 + 3 = 4 3^2 = 4 + (4 + 1) = 4 + 5 = 1 + 3 + 5 = 9 4^2 = 9 + (6 + 1)
+ * = 9 + 7 = 1 + 3 + 5 + 7 = 16 ... In other words, a square number can be
+ * express as the sum of the series n^2 = 1 + 3 + ... + (2n-1)
+ * 
+ * Note that NO multiplication or floating point math is needed. [BDyess]
+ */
+int
+isqrt(n)
+  int n;
+{
+  int result = 0, sum = 1, prev = 1;
+
+  while (sum <= n)
+  {
+    prev += 2;
+    sum += prev;
+    ++result;
+  }
+  return result;
+}
+
+/*
+ * Calculates the distance directly using a lookup table. Very fast, esp.
+ * compared to hypot(), but less accurate.
+ * 
+ * Produces results exactly as (int) hypot( (double)x, (double)y) up to
+ * hypot(HYPOTMIN,HYPOTMIN), and then loses accuracy in the trailing digits.
+ * With HYPOTMIN = 1000, error is .01% at 200000,200000.
+ * 
+ * Bill Dyess
+ */
+
+#define HYPOTMIN 1000
+int hypotlookup[] = {
+  1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000,
+  1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000,
+  1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000,
+  1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000,
+  1000, 1000, 1000, 1000, 1000, 1001, 1001, 1001, 1001, 1001,
+  1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001,
+  1001, 1001, 1001, 1001, 1002, 1002, 1002, 1002, 1002, 1002,
+  1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1003, 1003,
+  1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003,
+  1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004,
+  1004, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005,
+  1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1007,
+  1007, 1007, 1007, 1007, 1007, 1007, 1007, 1008, 1008, 1008,
+  1008, 1008, 1008, 1008, 1008, 1009, 1009, 1009, 1009, 1009,
+  1009, 1009, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1011,
+  1011, 1011, 1011, 1011, 1011, 1011, 1012, 1012, 1012, 1012,
+  1012, 1012, 1013, 1013, 1013, 1013, 1013, 1013, 1014, 1014,
+  1014, 1014, 1014, 1014, 1015, 1015, 1015, 1015, 1015, 1015,
+  1016, 1016, 1016, 1016, 1016, 1016, 1017, 1017, 1017, 1017,
+  1017, 1018, 1018, 1018, 1018, 1018, 1019, 1019, 1019, 1019,
+  1019, 1020, 1020, 1020, 1020, 1020, 1020, 1021, 1021, 1021,
+  1021, 1022, 1022, 1022, 1022, 1022, 1023, 1023, 1023, 1023,
+  1023, 1024, 1024, 1024, 1024, 1025, 1025, 1025, 1025, 1025,
+  1026, 1026, 1026, 1026, 1027, 1027, 1027, 1027, 1027, 1028,
+  1028, 1028, 1028, 1029, 1029, 1029, 1029, 1030, 1030, 1030,
+  1030, 1031, 1031, 1031, 1031, 1032, 1032, 1032, 1032, 1032,
+  1033, 1033, 1033, 1034, 1034, 1034, 1034, 1035, 1035, 1035,
+  1035, 1036, 1036, 1036, 1036, 1037, 1037, 1037, 1037, 1038,
+  1038, 1038, 1039, 1039, 1039, 1039, 1040, 1040, 1040, 1040,
+  1041, 1041, 1041, 1042, 1042, 1042, 1042, 1043, 1043, 1043,
+  1044, 1044, 1044, 1044, 1045, 1045, 1045, 1046, 1046, 1046,
+  1046, 1047, 1047, 1047, 1048, 1048, 1048, 1049, 1049, 1049,
+  1049, 1050, 1050, 1050, 1051, 1051, 1051, 1052, 1052, 1052,
+  1053, 1053, 1053, 1053, 1054, 1054, 1054, 1055, 1055, 1055,
+  1056, 1056, 1056, 1057, 1057, 1057, 1058, 1058, 1058, 1059,
+  1059, 1059, 1060, 1060, 1060, 1061, 1061, 1061, 1062, 1062,
+  1062, 1063, 1063, 1063, 1064, 1064, 1064, 1065, 1065, 1065,
+  1066, 1066, 1066, 1067, 1067, 1068, 1068, 1068, 1069, 1069,
+  1069, 1070, 1070, 1070, 1071, 1071, 1071, 1072, 1072, 1072,
+  1073, 1073, 1074, 1074, 1074, 1075, 1075, 1075, 1076, 1076,
+  1077, 1077, 1077, 1078, 1078, 1078, 1079, 1079, 1080, 1080,
+  1080, 1081, 1081, 1081, 1082, 1082, 1083, 1083, 1083, 1084,
+  1084, 1085, 1085, 1085, 1086, 1086, 1086, 1087, 1087, 1088,
+  1088, 1088, 1089, 1089, 1090, 1090, 1090, 1091, 1091, 1092,
+  1092, 1092, 1093, 1093, 1094, 1094, 1094, 1095, 1095, 1096,
+  1096, 1096, 1097, 1097, 1098, 1098, 1099, 1099, 1099, 1100,
+  1100, 1101, 1101, 1101, 1102, 1102, 1103, 1103, 1104, 1104,
+  1104, 1105, 1105, 1106, 1106, 1107, 1107, 1107, 1108, 1108,
+  1109, 1109, 1110, 1110, 1110, 1111, 1111, 1112, 1112, 1113,
+  1113, 1114, 1114, 1114, 1115, 1115, 1116, 1116, 1117, 1117,
+  1118, 1118, 1118, 1119, 1119, 1120, 1120, 1121, 1121, 1122,
+  1122, 1122, 1123, 1123, 1124, 1124, 1125, 1125, 1126, 1126,
+  1127, 1127, 1128, 1128, 1128, 1129, 1129, 1130, 1130, 1131,
+  1131, 1132, 1132, 1133, 1133, 1134, 1134, 1135, 1135, 1136,
+  1136, 1136, 1137, 1137, 1138, 1138, 1139, 1139, 1140, 1140,
+  1141, 1141, 1142, 1142, 1143, 1143, 1144, 1144, 1145, 1145,
+  1146, 1146, 1147, 1147, 1148, 1148, 1149, 1149, 1150, 1150,
+  1151, 1151, 1152, 1152, 1153, 1153, 1154, 1154, 1155, 1155,
+  1156, 1156, 1157, 1157, 1158, 1158, 1159, 1159, 1160, 1160,
+  1161, 1161, 1162, 1162, 1163, 1163, 1164, 1164, 1165, 1165,
+  1166, 1166, 1167, 1167, 1168, 1168, 1169, 1169, 1170, 1170,
+  1171, 1171, 1172, 1172, 1173, 1173, 1174, 1175, 1175, 1176,
+  1176, 1177, 1177, 1178, 1178, 1179, 1179, 1180, 1180, 1181,
+  1181, 1182, 1182, 1183, 1184, 1184, 1185, 1185, 1186, 1186,
+  1187, 1187, 1188, 1188, 1189, 1189, 1190, 1191, 1191, 1192,
+  1192, 1193, 1193, 1194, 1194, 1195, 1195, 1196, 1197, 1197,
+  1198, 1198, 1199, 1199, 1200, 1200, 1201, 1202, 1202, 1203,
+  1203, 1204, 1204, 1205, 1205, 1206, 1207, 1207, 1208, 1208,
+  1209, 1209, 1210, 1210, 1211, 1212, 1212, 1213, 1213, 1214,
+  1214, 1215, 1216, 1216, 1217, 1217, 1218, 1218, 1219, 1220,
+  1220, 1221, 1221, 1222, 1222, 1223, 1224, 1224, 1225, 1225,
+  1226, 1226, 1227, 1228, 1228, 1229, 1229, 1230, 1231, 1231,
+  1232, 1232, 1233, 1233, 1234, 1235, 1235, 1236, 1236, 1237,
+  1238, 1238, 1239, 1239, 1240, 1241, 1241, 1242, 1242, 1243,
+  1244, 1244, 1245, 1245, 1246, 1247, 1247, 1248, 1248, 1249,
+  1250, 1250, 1251, 1251, 1252, 1253, 1253, 1254, 1254, 1255,
+  1256, 1256, 1257, 1257, 1258, 1259, 1259, 1260, 1260, 1261,
+  1262, 1262, 1263, 1263, 1264, 1265, 1265, 1266, 1266, 1267,
+  1268, 1268, 1269, 1270, 1270, 1271, 1271, 1272, 1273, 1273,
+  1274, 1275, 1275, 1276, 1276, 1277, 1278, 1278, 1279, 1280,
+  1280, 1281, 1281, 1282, 1283, 1283, 1284, 1285, 1285, 1286,
+  1286, 1287, 1288, 1288, 1289, 1290, 1290, 1291, 1291, 1292,
+  1293, 1293, 1294, 1295, 1295, 1296, 1297, 1297, 1298, 1298,
+  1299, 1300, 1300, 1301, 1302, 1302, 1303, 1304, 1304, 1305,
+  1305, 1306, 1307, 1307, 1308, 1309, 1309, 1310, 1311, 1311,
+  1312, 1313, 1313, 1314, 1315, 1315, 1316, 1316, 1317, 1318,
+  1318, 1319, 1320, 1320, 1321, 1322, 1322, 1323, 1324, 1324,
+  1325, 1326, 1326, 1327, 1328, 1328, 1329, 1330, 1330, 1331,
+  1332, 1332, 1333, 1334, 1334, 1335, 1336, 1336, 1337, 1338,
+  1338, 1339, 1340, 1340, 1341, 1342, 1342, 1343, 1344, 1344,
+  1345, 1346, 1346, 1347, 1348, 1348, 1349, 1350, 1350, 1351,
+  1352, 1352, 1353, 1354, 1354, 1355, 1356, 1356, 1357, 1358,
+  1358, 1359, 1360, 1360, 1361, 1362, 1362, 1363, 1364, 1364,
+  1365, 1366, 1366, 1367, 1368, 1369, 1369, 1370, 1371, 1371,
+  1372, 1373, 1373, 1374, 1375, 1375, 1376, 1377, 1377, 1378,
+  1379, 1380, 1380, 1381, 1382, 1382, 1383, 1384, 1384, 1385,
+  1386, 1386, 1387, 1388, 1388, 1389, 1390, 1391, 1391, 1392,
+  1393, 1393, 1394, 1395, 1395, 1396, 1397, 1398, 1398, 1399,
+  1400, 1400, 1401, 1402, 1402, 1403, 1404, 1405, 1405, 1406,
+  1407, 1407, 1408, 1409, 1409, 1410, 1411, 1412, 1412, 1413,
+  1414
+};
+
+int 
+ihypot(x, y)
+  int x, y;
+{
+  int max, min;
+
+  x = (x < 0) ? -x : x;
+  y = (y < 0) ? -y : y;
+  if (x > y)
+  {
+    max = x;
+    min = y;
+  }
+  else
+  {
+    max = y;
+    min = x;
+  }
+  if (max == 0)
+    return 0;
+  /* if(max < 32768) return isqrt(max*max+min*min); */
+  return hypotlookup[HYPOTMIN * min / max] * max / HYPOTMIN;
+}
+
+#if 0
+/* code to calculate the lookup table. */
+#include<math.h>
+
+int 
+main(int argc, char **argv)
+{
+  int i, j, max;
+
+  if (argc != 2)
+  {
+    printf("Usage: %s <size of ihypot() lookup table>\n", argv[0]);
+    return 0;
+  }
+  max = atoi(argv[1]);
+  printf("#define HYPOTMIN %d\nint hypotlookup[] = {\n  %d", max, max);
+  for (i = 1, j = 1; i <= max; i++, j++)
+  {
+    if (j % 10 == 0)
+      printf(",\n  ");
+    else
+      printf(", ");
+    printf("%d", (int) hypot((double) i, (double) max));
+  }
+  printf("\n};\n");
+  return 0;
+}
+#endif				/* 0 */
+
+#if 0
+/* code to test various routines */
+int 
+main(int argc, char **argv)
+{
+  if (argc != 3)
+  {
+    printf("Usage: %s <x> <y>\n", argv[0]);
+    return 0;
+  }
+  printf("hypot = %d\n", ihypot(atoi(argv[1]), atoi(argv[2])));
+  return 0;
+}
+#endif				/* 0 */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/input.c	Sat Dec 06 04:37:03 1997 +0000
@@ -0,0 +1,163 @@
+/*--------------------------------------------------------------------------
+NETREK II -- Paradise
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any NON-COMMERCIAL purpose (following the terms of
+the GNU General Public License (read the file 'COPYING')) 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
+
+    Comprehensive credits are available in the file "CREDITS"
+--------------------------------------------------------------------------*/
+
+#include "config.h"
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <signal.h>
+#include <errno.h>
+#include "defs.h"
+#include "struct.h"
+#include "data.h"
+#include "shmem.h"
+
+static int sendflag = 0;
+
+extern int intrupt();
+extern void start_interruptor();
+extern int isClientDead();
+int reconnect();
+extern int readFromClient();
+extern void stop_interruptor();
+extern int exitGame();
+extern int closeUdpConn();
+extern unsigned int sleep();
+extern int connectToClient();
+extern void (*r_signal()) ();
+
+void
+setflag()
+{
+  sendflag = 1;
+}
+
+
+void
+input()
+{
+  fd_set readfds;
+
+  start_interruptor();
+
+  /* Idea:  read from client often, send to client not so often */
+  while (me->p_status == PALIVE ||
+	 me->p_status == PEXPLODE ||
+	 me->p_status == PDEAD ||
+	 me->p_status == POBSERVE)
+  {
+    if (isClientDead())
+    {
+      if (!reconnect())
+	exit(0);
+    }
+    FD_ZERO(&readfds);
+    FD_SET(sock, &readfds);
+    if (udpSock >= 0)
+      FD_SET(udpSock, &readfds);
+
+    /*
+     * blocks indefinitely unless client input or timerDelay SIGALRM causes
+     * EINTR
+     */
+
+    if (socketWait() > 0)
+    {
+      readFromClient();
+    }
+    if (sendflag)
+    {
+      intrupt();
+      sendflag = 0;
+    }
+
+    /* statements below are executed once per timerDelay */
+    if (me->p_updates > delay)
+    {
+      me->p_flags &= ~(PFWAR);
+    }
+    if (me->p_updates > rdelay)
+    {
+      me->p_flags &= ~(PFREFITTING);
+    }
+
+    /*
+     * this will ghostbust a player if no ping has been received in
+     * ping_ghostbust_interval seconds
+     */
+
+    if (configvals->ping_allow_ghostbust
+	&& (me->p_status == PALIVE || me->p_status == POBSERVE)
+	&& ping_ghostbust > configvals->ping_ghostbust_interval)
+      me->p_ghostbuster = 100000;	/* ghostbusted */
+    else
+      /* Keep self from being nuked... */
+      me->p_ghostbuster = 0;
+  }
+  stop_interruptor();
+}
+
+int
+reconnect()
+{
+  int i;
+
+  if (noressurect)
+    exitGame();
+  stop_interruptor();
+
+  r_signal(SIGIO, SIG_IGN);
+#ifdef DEBUG
+  printf("Ack!  The client went away!\n");
+  printf("I will attempt to resurrect him!\n");
+  fflush(stdout);
+#endif
+  commMode = COMM_TCP;
+  if (udpSock >= 0)
+    closeUdpConn();
+
+  /* For next two minutes, we try to restore connection */
+  shutdown(sock, 2);
+  sock = -1;
+  for (i = 0;; i++)
+  {
+    me->p_ghostbuster = 0;
+    sleep(5);
+    if (connectToClient(host, nextSocket))
+      break;
+    if (i == 23)
+    {
+#ifdef DEBUG
+      printf("Oh well, maybe I'm getting rusty!\n");
+      fflush(stdout);
+#endif
+      return 0;
+    }
+  }
+  start_interruptor();
+#ifdef DEBUG
+  printf("A miracle!  He's alive!\n");
+  fflush(stdout);
+#endif
+  return 1;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interface.c	Sat Dec 06 04:37:03 1997 +0000
@@ -0,0 +1,1236 @@
+/*--------------------------------------------------------------------------
+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 "defs.h"
+#include "struct.h"
+#include "data.h"
+#include "shmem.h"
+
+void cloak_off();
+void cloak_on();
+int numShips();
+void sendwarn();
+extern int pmessage2();
+int allowed_ship();
+int numPlanets();
+void suspendPrep();
+void unsuspendPrep();
+
+/*-----------------------------VISIBLE FUNCTIONS---------------------------*/
+
+/*--------------------------------SETSPEED---------------------------------*/
+/*
+ * This function takes the desired speed from the client and translates it
+ * into impulse, afterburners, or warp.  99 = warp.  98 = afterburners. 97 =
+ * suspend warp prep, 96 = resume warp prep, 0-x = impulse.  This function is
+ * used for both requests to set a ships speed from the client and from the
+ * server.  The client requests are requests that are received directly from
+ * the client.  A speed of 99 is treated as a request for warp speed.  A
+ * request of 98 is a request for afterburners.
+ */
+
+
+
+void
+set_speed(speed, type)
+  int speed;			/* the desired speed */
+  int type;			/* type of request. 0=server 1=client */
+{
+  if (me->p_flags & PFDOCK)
+  {				/* if docked then */
+    if (players[me->p_docked].p_speed > 4)
+    {				/* you cannot get off >= 4 */
+      warning("You are going too fast to disengage safely");
+      return;
+    }
+    else
+      undock_player(me);
+  }
+  speed = (speed < 0) ? 0 : speed;	/* no negative speeds */
+  /* suspend warp  [BDyess] */
+  if (speed == 97 && configvals->warpprep_suspendable)
+  {				/* suspend warp */
+    suspendPrep();
+  }
+  else if (speed == 96 && configvals->warpprep_suspendable)
+  {
+    /* unsuspend warp [BDyess] */
+    unsuspendPrep();
+  }
+  else if ((speed == 98) && (configvals->afterburners))
+  {				/* afterburners */
+    /* turn off warp, warpprep, and warp suspended flags */
+    me->p_flags &= ~(PFWARP | PFWARPPREP | PFWPSUSPENDED);
+    me->p_warptime = 0;
+    me->p_flags |= PFAFTER;	/* turn on after burners */
+    me->p_desspeed = me->p_ship.s_after.maxspeed;	/* set speed of
+							 * afterburn */
+    /*
+     * go to warp if speed 99 is sent, OR if the speed sent is greater than
+     * max impulse and the VARIABLE_WARP sysdef is set, AND the ship can warp
+     * [BDyess]
+     */
+  }
+  else if ((speed == 99
+	    || (configvals->variable_warp
+		&& speed > me->p_ship.s_imp.maxspeed
+		&& me->p_flags & (PFWARPPREP | PFWARP | PFWPSUSPENDED))
+	    )
+	   && (me->p_ship.s_nflags & SFNCANWARP))
+  {
+    int maxspeed = me->p_ship.s_warp.maxspeed;
+    int preptime = myship->s_warpinittime;	/* timer before warping */
+
+    if (configvals->warpzone)
+    {
+      if (me->p_zone < 0)
+      {
+	warning("The enemy is neutralizing our warp field, sir!");
+	return;
+      }
+      else if (me->p_zone > 0)
+      {
+	maxspeed = maxspeed * 3 / 2;	/* can go faster with boost [BDyess] */
+	if (maxspeed > 99)
+	  maxspeed = 99;
+	preptime /= 2;		/* takes less time to build up when you have
+				 * help */
+	if (preptime == 0)
+	  preptime = 1;
+	warning("warp boost!");
+      }
+    }
+
+    speed = (speed > maxspeed)
+      ? maxspeed
+      : speed;			/* cap the request at max warp */
+
+    me->p_warpdesspeed = speed;	/* remember how fast to warp for later
+				 * [BDyess] */
+    if (me->p_warptime > 0)
+    {
+      warning("Hold your horses, Speed Racer.  These things take time.");
+      return;
+    }
+    if (me->p_flags & PFWARP)
+    {
+      me->p_desspeed = speed;
+      return;
+    }
+    if (me->p_damage > me->p_ship.s_maxdamage / 2)
+    {
+      warning("We are too damaged to risk warp speeds, Captain.");
+      return;
+    }
+    if (me->p_fuel < me->p_ship.s_warpinitcost)
+    {
+      warning("Not enough fuel for warp, Captain!");
+      return;
+    }
+    me->p_desspeed = myship->s_warpprepspeed;	/* slow ship down */
+    me->p_flags |= PFWARPPREP;	/* set warp prep flag [BDyess] */
+    if (!configvals->cloakduringwarpprep)
+      cloak_off();
+
+    if (me->p_speed < me->p_desspeed)
+      me->p_speed = me->p_desspeed;
+
+    /* turn off after burners and warpprep suspended flag [BDyess] */
+    me->p_flags &= ~(PFAFTER | PFWPSUSPENDED);
+    me->p_warptime = preptime;	/* timer before warping */
+    me->p_fuel -= me->p_ship.s_warpinitcost;	/* subtract off fuel */
+    warning("Warp drive engaged!");	/* let him know its working */
+  }
+  else if (type == 0)
+  {				/* else if server request */
+    me->p_desspeed = speed;	/* grant speed request */
+  }
+  else
+  {				/* else client request for impulse */
+
+    if (!configvals->warpdecel)
+      me->p_flags &= ~(PFWARP | PFAFTER);
+
+    me->p_warptime = 0;
+    me->p_flags &= ~(PFWARPPREP | PFWPSUSPENDED);	/* turn off warpprep
+							 * flag [BDyess] */
+    speed = (speed > me->p_ship.s_imp.maxspeed) ? me->p_ship.s_imp.maxspeed :
+      speed;
+    me->p_desspeed = speed;	/* set the speed */
+  }
+#if 0
+  if (me->p_flags & PFORBIT)	/* if we were orbiting */
+    planets[me->p_planet].pl_torbit &= ~me->p_team;
+#endif
+  me->p_flags &= ~(PFREPAIR | PFBOMB | PFORBIT | PFDOCK | PFBEAMUP | PFBEAMDOWN);
+  me->p_lastman = 0;
+}
+
+
+
+
+/*--------------------------------SET_COURSE-------------------------------*/
+/*
+ * Set the players course.  This function takes a direction and sets the
+ * players direction to it.  Certain flags are cleared.
+ */
+
+void
+set_course(dir)
+  unsigned char dir;
+{
+  me->p_desdir = dir;		/* set the desired direction */
+  if (me->p_flags & PFDOCK)
+  {				/* if player is docked then he cannot */
+    if (players[me->p_docked].p_speed > 4)
+    {				/* undock if dockee going fast */
+      warning("It's unsafe to disengage from bases while moving more that warp 4.");
+      return;
+    }
+    else
+      undock_player(me);
+
+  }
+#if 0
+  if (me->p_flags & PFORBIT)	/* if in orbit then take */
+    planets[me->p_planet].pl_torbit &= ~me->p_team;	/* team out of orbit */
+#endif
+  me->p_flags &= ~(PFBOMB | PFORBIT | PFDOCK | PFBEAMUP | PFBEAMDOWN);
+  me->p_lastman = 0;		/* not beamin all armies up */
+}
+
+
+
+
+/*----------------------------------SHIELD_UP-----------------------------*/
+/* This function raises the players shields.  */
+
+void
+shield_up()
+{
+  me->p_flags |= PFSHIELD;	/* some flags go up and some down */
+  me->p_flags &= ~(PFBOMB | PFREPAIR | PFBEAMUP | PFBEAMDOWN);
+  me->p_lastman = 0;		/* not beaming up all armies */
+}
+
+
+
+
+/*---------------------------------SHIELD_DOWN----------------------------*/
+/* This function lowers the players shields.  */
+
+void
+shield_down()
+{
+  me->p_flags &= ~PFSHIELD;	/* shield flag clear */
+}
+
+
+
+
+/*--------------------------------SHIELD_TOGGLE---------------------------*/
+/* This function toggles the players shields on and off.  */
+
+void
+shield_tog()
+{
+  me->p_flags ^= PFSHIELD;	/* toggle shield flag */
+  me->p_flags &= ~(PFBOMB | PFREPAIR | PFBEAMUP | PFBEAMDOWN);
+  me->p_lastman = 0;
+}
+
+
+
+
+/*--------------------------------BOMB_PLANET------------------------------*/
+/*
+ * This function sets the bomb flag if certain conditions are met, such as
+ * you are bombing enemy planets.
+ */
+
+void
+bomb_planet()
+{
+  static int bombsOutOfTmode = 0;	/* confirm bomb out of t-mode */
+  int owner;			/* owner of planet */
+
+  owner = planets[me->p_planet].pl_owner;	/* get planet's owner */
+  if (!(me->p_flags & PFORBIT))
+  {				/* can't bomb anything in */
+    warning("Must be orbiting to bomb");	/* open space, now can you? */
+    return;
+  }
+  if (me->p_team == planets[me->p_planet].pl_owner)
+  {
+    warning("Can't bomb your own armies.  Have you been reading Catch-22 again?");	/* can't bomb own armies */
+    return;
+  }
+  if (!((me->p_swar | me->p_hostile) & owner) && (owner != 0))
+  {
+    warning("Must declare war first (no Pearl Harbor syndrome allowed here).");
+    return;			/* can't bomb friendlies */
+  }
+  if ((!status->tourn) && (bombsOutOfTmode == 0))
+  {
+    warning("Bomb out of T-mode?  Please verify your order to bomb.");
+    bombsOutOfTmode++;		/* warning about bombing out of T */
+    return;
+  }
+  if ((!status->tourn) && (bombsOutOfTmode == 1))
+  {
+    warning("Hoser!");		/* if he really wants to bomb, then */
+    bombsOutOfTmode++;		/* let him bomb out of T.  Hoser */
+  }				/* warning */
+  if (!numShips(planets[me->p_planet].pl_owner)
+      && (planets[me->p_planet].pl_owner != NOBODY))
+  {
+    warning("You can't break the peace treaty, Captain");
+    return;
+  }
+  if (status->tourn)		/* reset the bombs out of t-mode */
+    bombsOutOfTmode = 0;	/* variable */
+  me->p_flags |= PFBOMB;	/* set the bomb flag */
+#if 1
+  planets[me->p_planet].pl_hostile |= me->p_team;
+#else
+  planets[me->p_planet].pl_torbit |= (me->p_team) << 4;
+#endif
+  me->p_flags &= ~(PFSHIELD | PFREPAIR | PFBEAMUP | PFBEAMDOWN);
+}
+
+
+
+
+/*---------------------------------BEAM_UP---------------------------------*/
+/* This function set the beam up flag if it is allowable to beam men up.  */
+
+void
+beam_up()
+{
+  if (!status2->starttourn && configvals->nopregamebeamup)
+  {
+    warning("You can't beam up armies before a game starts");
+    return;
+  }
+  if (!(me->p_flags & (PFORBIT | PFDOCK)))
+  {
+    warning("Must be orbiting or docked to beam up.");
+    return;			/* have to be orbiting or docked */
+  }
+  if (me->p_flags & PFORBIT)
+  {				/* if orbiting and not owner */
+    if (me->p_team != planets[me->p_planet].pl_owner)
+    {
+      warning("Those aren't our men.");
+      return;
+    }
+    if (me->p_lastman == 0)	/* if we have not signalled to pick */
+      me->p_lastman = 1;	/* up all armies */
+    else if (planets[me->p_planet].pl_armies <= 4)
+    {				/* else if less than 5 */
+      if (numPlanets((int) me->p_team && configvals->beamlastarmies) == 1)
+      {
+	warning("You can't take those armies, they're on your only planet!");
+	return;
+      }
+      me->p_lastman = 2;	/* set status to beaming up all */
+    }
+  }
+  else if (me->p_flags & PFDOCK)
+  {				/* if docked must be to own team ship */
+    if (me->p_team != players[me->p_docked].p_team)
+    {
+      warning("Comm Officer: Uhhh, they aren't our men!");
+      return;
+    }
+  }
+  me->p_flags |= PFBEAMUP;	/* set the beam up flag */
+  me->p_flags &= ~(PFSHIELD | PFREPAIR | PFBOMB | PFBEAMDOWN);
+}
+
+
+
+
+/*--------------------------------BEAM_DOWN--------------------------------*/
+/* This function sets the beam up flag if certain conditions are met */
+
+void
+beam_down()
+{
+  int i;			/* looping var */
+  struct planet *pl;		/* to access planets */
+  int total;			/* for total number of planets */
+  char buf[80];
+
+  if (!(me->p_flags & (PFORBIT | PFDOCK)))
+  {
+    warning("Must be orbiting or docked to beam down.");
+    return;			/* have to be docked or orbiting */
+  }
+  if ((!((me->p_swar | me->p_hostile) & planets[me->p_planet].pl_owner))
+      && (me->p_team != planets[me->p_planet].pl_owner)
+      && (planets[me->p_planet].pl_owner != NOBODY))
+  {
+    warning("You can't beam down, you have not declared war");
+    return;			/* no beaming down if not hostile */
+  }
+  if (!numShips(planets[me->p_planet].pl_owner)
+      && (planets[me->p_planet].pl_owner != NOBODY))
+  {
+    warning("You can't break the peace treaty, Captain");
+    return;
+  }
+  if (me->p_flags & PFDOCK)
+  {
+    if (me->p_team != players[me->p_docked].p_team)
+    {
+      warning("Comm Officer: Starbase refuses permission to beam our troops over.");	/* no beaming to foreign
+											 * bases */
+      return;
+    }
+  }
+
+  else if (configvals->planetlimittype)
+  {				/* new planet limit */
+    total = numPlanets(me->p_team);
+
+    if (total >= configvals->planetsinplay
+	&& planets[me->p_planet].pl_owner == NOBODY
+	&& planets[me->p_planet].pl_armies)
+    {
+      sprintf(buf, "You may only take enemy planets when your team has %d or more planets.",
+	      configvals->planetsinplay);
+      warning(buf);
+      me->p_flags &= ~(PFBOMB);
+      return;
+    }
+  }
+  else
+  {
+    int ns[MAXTEAM];
+    for (i = 0; i < NUMTEAM; i++)
+      ns[1 << i] = numShips(1 << i);
+
+    total = 0;
+    for (i = 0, pl = &planets[i]; i < NUMPLANETS; i++, pl++)
+    {
+      if (pl->pl_owner && ns[pl->pl_owner] > configvals->tournplayers - 1)
+	total++;
+    }
+    if ((total >= configvals->planetsinplay)
+	&& (!(me->p_flags & PFDOCK))
+	&& (planets[me->p_planet].pl_owner == NOBODY))
+    {
+      sprintf(buf, "Sorry, there are already %d planets in play.",
+	      configvals->planetsinplay);
+      warning(buf);
+      me->p_flags &= ~(PFBOMB);
+      return;
+    }
+  }
+  me->p_flags |= PFBEAMDOWN;	/* set beam down flag */
+  me->p_flags &= ~(PFSHIELD | PFREPAIR | PFBOMB | PFBEAMUP);
+  me->p_lastman = 0;
+}
+
+
+
+
+/*---------------------------------REPAIR---------------------------------*/
+/*
+ * This function sets the reapair flag and turns off other flags.  You cannot
+ * repair while in warp.
+ */
+
+void
+repair()
+{
+#if !defined(AEDILE) || !defined(REPAIR_IN_WARP)
+  if (me->p_flags & PFWARP)
+  {				/* no repairing in warp */
+    warning("You cannot repair while in warp!");
+    return;
+  }
+#endif
+  me->p_desspeed = 0;		/* speed goes to zero */
+  me->p_warptime = 0;		/* turn off warp prep */
+  me->p_flags |= PFREPAIR;	/* reair flag goes up */
+  me->p_flags &= ~(PFSHIELD | PFBOMB | PFBEAMUP | PFBEAMDOWN | PFPLOCK | PFPLLOCK | PFWARP | PFAFTER | PFWARPPREP | PFWPSUSPENDED);
+  me->p_lastman = 0;		/* not beaming all armies */
+}
+
+
+
+
+/*--------------------------------REPAIR_OFF------------------------------*/
+/* This function takes the repair flag off.  */
+
+void
+repair_off()
+{
+  me->p_flags &= ~PFREPAIR;
+}
+
+
+
+
+/*---------------------------------REPEAT---------------------------------*/
+/* This function repeats the last message.  */
+
+void
+repeat_message()
+{
+  if (++lastm == MAXMESSAGE)	/* go to next message */
+    lastm = 0;			/* account for rollover */
+}
+
+
+
+
+/*---------------------------------CLOAK----------------------------------*/
+/*
+ * This function toggles the cloak flag.  Tractors and pressor are turned
+ * off.
+ */
+
+void
+cloak()
+{
+  if (me->p_flags & PFCLOAK)
+    cloak_off();
+  else
+    cloak_on();
+}
+
+
+
+
+/*---------------------------------CLOAK_ON-------------------------------*/
+/* This function turns cloak on.  Tractors and pressors are turned off.  */
+
+void
+cloak_on()
+{
+  if (me->p_warptime && !configvals->cloakduringwarpprep)
+  {
+    warning("Can't cloak during warp preparation.");
+    return;
+  }
+  if (me->p_flags & PFWARP && !configvals->cloakwhilewarping)
+  {
+    warning("Can't cloak while warp engines are engaged.");
+    return;
+  }
+  me->p_flags |= PFCLOAK;
+  me->p_flags &= ~(PFTRACT | PFPRESS);
+}
+
+
+
+
+/*---------------------------------CLOAK_OFF------------------------------*/
+/* This function turns the cloak off.  */
+
+void
+cloak_off()
+{
+  me->p_flags &= ~PFCLOAK;
+}
+
+
+
+
+/*-------------------------------LOCK_PLANET-----------------------------*/
+/* This function locks the player onto a planet.  */
+
+void
+lock_planet(planet)
+  int planet;			/* planet locking onto */
+{
+  char buf[80];			/* to sprintf into */
+
+  if ((planet < 0) || (planet >= NUMPLANETS))	/* bad planet number? */
+    return;
+
+  if (me->p_status == POBSERVE)
+  {
+    if (planets[planet].pl_owner != me->p_team)
+    {
+      warning("Unable to observe enemy planets.");
+      me->p_flags &= ~(PFPLLOCK | PFPLOCK);
+      return;
+    }
+    else if (!(planets[planet].pl_owner & me->p_teamspy))
+    {
+      warning("That team has barred you from observing.");
+      me->p_flags &= ~(PFPLLOCK | PFPLOCK);
+      return;
+    }
+  }
+
+  me->p_flags |= PFPLLOCK;	/* turn on the lock */
+#if 0
+  if (me->p_flags & PFORBIT)	/* if orbiting then leave torbit var */
+    planets[me->p_planet].pl_torbit &= ~me->p_team;
+#endif
+  me->p_flags &= ~(PFPLOCK | PFORBIT | PFBEAMUP | PFBEAMDOWN | PFBOMB);
+  me->p_lastman = 0;
+  me->p_planet = planet;	/* set planet locked onto */
+  sprintf(buf, "Locking onto %s", planets[planet].pl_name);
+  warning(buf);			/* send message to player */
+}
+
+
+
+
+/*-------------------------------LOCK_PLAYER-------------------------------*/
+/* This function locks the player onto another player.  */
+
+void
+lock_player(player)
+  int player;			/* player locking onto */
+{
+  char buf[80];
+
+  if ((player < 0) || (player >= MAXPLAYER))	/* bad planet num? */
+    return;
+  if (players[player].p_status != PALIVE)	/* player not alive? */
+    return;
+  if (players[player].p_flags & PFCLOAK)	/* player is cloaked */
+    return;
+
+  if (me->p_status == POBSERVE && players[player].p_team != me->p_team)
+  {
+    sprintf(buf, "Unable to observe enemy players.");
+    warning(buf);
+    me->p_flags &= ~(PFPLLOCK | PFPLOCK);
+    return;
+  }
+
+  me->p_flags |= PFPLOCK;	/* set player lock flag */
+#if 0
+  if (me->p_flags & PFORBIT)	/* if in orbit take team out */
+    planets[me->p_planet].pl_torbit &= ~me->p_team;	/* of torbit */
+#endif
+  me->p_flags &= ~(PFPLLOCK | PFORBIT | PFBEAMUP | PFBEAMDOWN | PFBOMB);
+  me->p_lastman = 0;		/* turn off taking all armies */
+  me->p_playerl = player;	/* set player loked oto */
+  /* player locking onto own base */
+  if ((players[player].p_team == me->p_team) &&
+      allows_docking(players[player].p_ship))
+    sprintf(buf, "Locking onto %s (%s) (docking is %s)",
+	    players[player].p_name, twoletters(&players[player]),
+	    (players[player].p_flags & PFDOCKOK) ? "enabled" : "disabled");
+  else				/* message for locking onto player */
+    sprintf(buf, "Locking onto %s (%s)", players[player].p_name,
+	    twoletters(&players[player]));
+  warning(buf);
+}
+
+
+
+
+/*-------------------------------TRACTOR_PLAYER----------------------------*/
+/*
+ * This function does the tractoring for the player.  There are a few times
+ * when the tractor cannot be used.
+ */
+
+void
+tractor_player(player)
+  int player;
+{
+  struct player *victim;
+
+  if (weaponsallowed[WP_TRACTOR] == 0)	/* tractors allowed?  */
+    return;
+  if ((player < 0) || (player > MAXPLAYER))
+  {				/* out of bounds = cancel */
+    me->p_flags &= ~(PFTRACT | PFPRESS);
+    return;
+  }
+  if (me->p_flags & PFCLOAK)	/* no tractoring while */
+    return;			/* cloaked */
+  if (player == me->p_no)	/* can't tractor yourself */
+    return;
+  victim = &players[player];	/* get player number */
+  if (victim->p_flags & PFCLOAK)
+    return;
+  if (ihypot(me->p_x - victim->p_x, me->p_y - victim->p_y) <
+      (TRACTDIST) * me->p_ship.s_tractrng)
+  {
+    if (me->p_flags & PFDOCK && players[me->p_docked].p_speed > 4)
+    {
+      warning("It's unsafe to tractor while docked and base is moving more then warp 4.");
+      return;
+    }
+#if 0
+    undock_player(victim);	/* harmless if not docked, handles js */
+    undock_player(me);
+
+#if 0
+    if (me->p_flags & PFORBIT)	/* are we orbiting */
+      planets[me->p_planet].pl_torbit &= ~me->p_team;
+    if (victim->p_flags & PFORBIT)	/* is victim orbiting */
+      planets[victim->p_planet].pl_torbit &= ~victim->p_team;
+    victim->p_flags &= ~(PFORBIT | PFDOCK);	/* clear DOCK/ORBIT flags */
+#endif
+    me->p_flags &= ~(PFORBIT | PFDOCK);
+#endif
+    me->p_tractor = player;	/* set victim number */
+    me->p_flags |= PFTRACT;	/* set tractor flag */
+  }
+}
+
+
+
+
+/*---------------------------------PRESSOR--------------------------------*/
+/*
+ * This function activates the tractors for the player.  There are a number
+ * of conditions where tractors will not work.
+ */
+
+void
+pressor_player(player)
+  int player;			/* the player to presoor */
+{
+  int target;
+  struct player *victim;
+
+  if (weaponsallowed[WP_TRACTOR] == 0)
+  {				/* tractors allowed? */
+    warning("Pressor beams haven't been invented yet.");
+    return;
+  }
+  target = player;		/* save target */
+  if ((target < 0) || (target > MAXPLAYER))
+  {				/* out of bounds = cancel */
+    me->p_flags &= ~(PFTRACT | PFPRESS);
+    return;
+  }
+  if (me->p_flags & PFPRESS)	/* already pressoring? */
+    return;
+  if (me->p_flags & PFCLOAK)
+  {				/* cloaked? */
+    warning("Weapons's Officer:  Cannot pressor while cloaked, sir!");
+    return;
+  }
+  victim = &players[target];	/* get victim's struct */
+  if (victim->p_flags & PFCLOAK)/* victim cloaked */
+    return;
+  if (ihypot(me->p_x - victim->p_x, me->p_y - victim->p_y) <
+      (TRACTDIST) * me->p_ship.s_tractrng)
+  {
+    if (me->p_flags & PFDOCK && players[me->p_docked].p_speed > 4)
+    {
+      warning("It's unsafe to pressor while docked and base is moving more then warp 4.");
+      return;
+    }
+#if 0
+    undock_player(victim);
+    undock_player(me);
+
+#if 0
+    if (me->p_flags & PFORBIT)	/* are we orbiting */
+      planets[me->p_planet].pl_torbit &= ~me->p_team;
+    if (victim->p_flags & PFORBIT)	/* is victim orbiting */
+      planets[victim->p_planet].pl_torbit &= ~victim->p_team;
+#endif
+    victim->p_flags &= ~(PFORBIT | PFDOCK);	/* clear orbit and dock flags */
+    me->p_flags &= ~(PFORBIT | PFDOCK);
+#endif
+    me->p_tractor = target;	/* set the target */
+    me->p_flags |= (PFTRACT | PFPRESS);	/* set the tract and press */
+  }
+  /* flags */
+  else
+    warning("Weapon's Officer:  Vessel is out of range of our pressor beam.");
+}
+
+
+
+
+/*-------------------------------DECLARE_WAR-----------------------------*/
+/* This function changes the war mask of a player.  */
+
+void
+declare_war(mask)
+  int mask;			/* who are we declaring war against */
+{
+  int changes;			/* to hold changes in war mask */
+  int i;			/* looping var */
+
+  mask &= ALLTEAM;		/* mask off extraneous bits */
+  mask &= ~me->p_team;		/* mask out our team bit */
+  mask |= me->p_swar;
+  changes = mask ^ me->p_hostile;	/* determine changes */
+  if (changes == 0)		/* if no changes then we are done */
+    return;
+  if (changes & FED)		/* if Fed status changed then warn them */
+    sendwarn("Federation", mask & FED, FED);
+  if (changes & ROM)		/* if Rom status changed then warn them */
+    sendwarn("Romulans", mask & ROM, ROM);
+  if (changes & KLI)		/* if Kli status changed then warn them */
+    sendwarn("Klingons", mask & KLI, KLI);
+  if (changes & ORI)		/* if Orion status changed then warn them */
+    sendwarn("Orions", mask & ORI, ORI);
+  if (me->p_flags & PFDOCK)
+  {				/* if docked and now at war with */
+    if (players[me->p_docked].p_team & mask)
+    {				/* dockee then undock */
+      undock_player(me);
+    }
+  }
+  else if (allows_docking(me->p_ship))
+  {				/* if ship is dockable then */
+    if (me->p_docked > 0)
+    {				/* go through ports and */
+      for (i = 0; i < me->p_ship.s_numports; i++)
+      {				/* kick off warring ships */
+	if (me->p_port[i] >= 0 &&
+	    (mask & players[me->p_port[i]].p_team))
+	{
+	  base_undock(me, i);
+	}
+      }
+    }
+  }
+  if (mask & ~me->p_hostile)
+  {				/* no sudden changing of */
+    me->p_flags |= PFWAR;	/* war status */
+    delay = me->p_updates + 100;
+    warning("Pausing ten seconds to re-program battle computers.");
+  }
+  me->p_hostile = mask;		/* new hostile mask */
+}
+
+
+
+
+/*-----------------------------------SENDWARN------------------------------*/
+/*
+ * This function sends the warning message to the other players when a player
+ * switches his war status with that team.
+ */
+
+void
+sendwarn(string, atwar, team)
+  char *string;			/* the name of the team changing status
+				 * towards */
+  int atwar;			/* 1 if declarig war 0 if decalring peace */
+  int team;			/* name of team we are switching in regards
+				 * to */
+{
+  char buf[BUFSIZ];		/* to hold sprintfed message */
+  char addrbuf[10];		/* to hold ship number and team letter */
+
+  if (atwar)
+  {				/* if decalring war */
+    (void) sprintf(buf, "%s (%s) declaring war on the %s",
+		   me->p_name, twoletters(me), string);
+  }
+  else
+  {				/* else decalring peace */
+    (void) sprintf(buf, "%s (%s) declaring peace with the %s",
+		   me->p_name, twoletters(me), string);
+  }
+  (void) sprintf(addrbuf, " %s->%-3s", twoletters(me), teams[team].shortname);
+  pmessage2(buf, team, MTEAM, addrbuf, me->p_no);
+}
+
+
+/* switches the special weapon of the player */
+
+void
+switch_special_weapon()
+{
+  int mask = 0;
+  int currflag;
+  int i, j;
+
+  mask = me->p_ship.s_nflags & (SFNHASMISSILE | SFNPLASMAARMED);
+
+  if (!mask)
+  {
+    warning("This ship is not armed with any special weapons");
+    me->p_specweap = 0;
+    return;
+  }
+  for (i = 0; i < sizeof(int) * 8; i++)
+  {
+    currflag = 1 << i;
+    if (!mask & currflag)
+      continue;
+    if (me->p_specweap & currflag)
+    {
+      i++;
+      break;
+    }
+  }
+
+  for (j = 0; j < sizeof(int) * 8; i++, j++)
+  {
+    if (i > sizeof(int) * 8)
+      i = 0;
+    currflag = 1 << i;
+    if (mask & currflag)
+    {
+      me->p_specweap = currflag;
+      break;
+    }
+  }
+
+  if (me->p_specweap & SFNHASMISSILE)
+  {
+    if (me->p_ship.s_nflags & SFNHASFIGHTERS)
+      warning("Fighters ready");
+    else
+      warning("Missiles armed");
+  }
+  else if (me->p_specweap & SFNPLASMAARMED)
+  {
+    warning("Plasmas armed");
+  }
+}
+
+/*-------------------------------DO_REFIT---------------------------------*/
+/*
+ * This function will attempt to refit a player to another ship.  There are
+ * all sorts of nasty reasons why it might fail.
+ */
+
+void
+do_refit(type)
+  int type;			/* type of ship to refit to */
+{
+  int i;			/* looping var */
+
+  if (type < 0 || type >= NUM_TYPES)	/* ship type select out of range */
+    return;
+  if (me->p_flags & PFORBIT)
+  {				/* if orbiting must be a shipyard */
+    if (!(planets[me->p_planet].pl_flags & PLSHIPYARD))
+    {
+      warning("You can change ships at a planet with a shipyard on it.");
+      return;
+    }
+#if 0
+    if (planets[me->p_planet].pl_owner != me->p_team)
+    {
+      warning("You can only refit on planets that your team owns.");
+      return;
+    }
+#endif
+  }
+  else if (me->p_flags & PFDOCK)
+  {				/* if docked then */
+    if (allows_docking(shipvals[type]))
+    {				/* cannot refit to a starbase */
+      warning("Can only refit to a base in a shipyard");
+      return;
+    }
+    if (players[me->p_docked].p_team != me->p_team)
+    {
+      warning("You must dock with YOUR base to apply for command reassignment!");	/* no refitting on enemy
+											 * SB's */
+      return;
+    }
+    if (!(players[me->p_docked].p_ship.s_nflags & SFNCANREFIT))
+    {
+      warning("This base can not provide you with a new ship.");
+      return;
+    }
+  }
+  else
+  {				/* planet does not have shipyard */
+    warning("Must orbit a shipyard or dock with your base to apply for command reassignment!");
+    return;
+  }
+  if ((me->p_damage > ((float) me->p_ship.s_maxdamage) * .75) ||
+      (me->p_shield < ((float) me->p_ship.s_maxshield) * .75) ||
+      (me->p_fuel < ((float) me->p_ship.s_maxfuel) * .75))
+  {
+    warning("Central Command refuses to accept a ship in this condition!");
+    return;			/* ship must be in good condition */
+  }
+  if ((me->p_armies > 0))
+  {				/* no refitting with armies on board */
+    warning("You must beam your armies down before moving to your new ship");
+    return;
+  }
+
+  {
+    int oldt, oldd, oldp, allowed;
+    oldt = me->p_ship.s_type;
+    oldd = me->p_ship.s_numdefn;
+    oldp = me->p_ship.s_numplan;
+    me->p_ship.s_type = -1;
+    me->p_ship.s_numdefn = 0;
+    me->p_ship.s_numplan = 0;
+    allowed = allowed_ship(me->p_team, me->p_stats.st_rank,
+			   me->p_stats.st_royal, type);
+    me->p_ship.s_type = oldt;
+    me->p_ship.s_numdefn = oldd;
+    me->p_ship.s_numplan = oldp;
+    if (!allowed)
+      return;
+  }
+
+  if (me->p_ship.s_type == STARBASE ||
+      me->p_ship.s_type == WARBASE ||
+      me->p_ship.s_type == CARRIER)
+    me->p_kills = 0;		/* reset kills to zero if coming */
+  /* from a base */
+
+  if (allows_docking(me->p_ship))
+  {				/* if ship dockable then */
+    for (i = 0; i < me->p_ship.s_numports; i++)
+    {				/* dump all ship out of dock */
+      base_undock(me, i);
+    }
+  }
+  get_ship_for_player(me, type);/* place ship in player strct */
+
+  switch_special_weapon();
+
+  if (me->p_flags & PFORBIT)
+  {
+    char buf[120];
+    me->p_lastrefit = me->p_planet;
+    sprintf(buf, "%s is now your home port", planets[me->p_lastrefit].pl_name);
+    warning(buf);
+  }
+
+  me->p_flags &= ~(PFREFIT);
+  me->p_flags |= PFREFITTING;
+  rdelay = me->p_updates + 50;
+  warning("You are being transported to your new vessel .... ");
+}
+
+
+/*
+ * Is a person with this rank on this team able to requisition a ship of this
+ * type?
+ */
+int
+allowed_ship(team, rank, royal, type)
+  int team;
+  int rank;
+  int royal;
+  int type;
+{
+  struct ship *tempship;
+  int shipcount;
+  int used_teamstr;		/* people required to support flying bases */
+  int used_planstr;		/* planets required to support flying bases */
+  int i, maxrank = 0;
+
+  if (!shipsallowed[type])
+  {
+    warning("That ship hasn't been designed yet.");
+    return 0;
+  }
+  tempship = &shipvals[type];
+
+#ifdef LEAGUE_SUPPORT
+  if (status2->league == 1)
+    return 1;
+
+  if (!status2->league)
+  {
+#endif
+    if (configvals->baserankstyle)
+    {
+      for (i = 0; i < MAXPLAYER; i++)
+	if ((players[i].p_status == PALIVE ||
+	     players[i].p_status == POUTFIT)
+	    && players[i].p_team == team)
+	  maxrank = MAX(rank, players[i].p_stats.st_rank);
+    }
+    else
+      maxrank = NUMRANKS;
+
+    if ((rank < MIN(tempship->s_rank, maxrank) && !(royal > GODLIKE)) &&
+	!(shipvals[tmpPick].s_nflags & SFNMASSPRODUCED))
+    {
+      char buf[100];
+      sprintf(buf, "Sorry %s, a rank of %s is required to command that ship.",
+	      ranks[rank].name, ranks[tempship->s_rank].name);
+      warning(buf);
+      return 0;
+    }
+#ifdef LEAGUE_SUPPORT
+  }
+#endif
+  used_teamstr = used_planstr = 0;
+  shipcount = 0;		/* How many ships of that type */
+  /* are on our team already? */
+  for (i = 0; i < MAXPLAYER; i++)
+  {
+    if (players[i].p_status == PALIVE && players[i].p_team == team)
+    {
+      if (players[i].p_ship.s_type == type)
+	shipcount++;
+      used_teamstr += players[i].p_ship.s_numdefn;
+      used_planstr += players[i].p_ship.s_numplan;
+    }
+  }
+  /*
+   * if you are in a base, and near the limits, you will sometimes have to
+   * switch into a normal ship before changing into another base
+   */
+
+  if ((shipcount >= tempship->s_maxnum) && !(shipvals[tmpPick].s_nflags & SFNMASSPRODUCED))
+  {
+    char buf[100];
+    sprintf(buf, "We already have %d %ss.", shipcount, tempship->s_name);
+    warning(buf);
+    return 0;
+  }
+  if ((teams[team].s_turns[type] >
+       (tempship->s_maxnum - shipcount - 1) * tempship->s_timer) &&
+      !(shipvals[tmpPick].s_nflags & SFNMASSPRODUCED))
+  {
+    char buf[100];
+    int turnsleft = teams[team].s_turns[type] -
+    (tempship->s_maxnum - shipcount - 1) * tempship->s_timer;
+    if (teams[team].s_turns[type] > 1)
+    {
+      sprintf(buf, "We are still building that ship (%d minutes until finished.)", turnsleft);
+      warning(buf);
+    }
+    else
+      warning("We are still building that ship (1 minute until finished.)");
+    return 0;
+  }
+  if ((tempship->s_numdefn &&
+       numShips(team) < tempship->s_numdefn + used_teamstr) &&
+      !(shipvals[tmpPick].s_nflags & SFNMASSPRODUCED))
+  {
+    char buf[100];
+    sprintf(buf, "Your team is not strong enough to defend a %s (%d+%d players needed).",
+	    tempship->s_name, tempship->s_numdefn, used_teamstr);
+    warning(buf);
+    return 0;
+  }
+  if ((tempship->s_numplan &&
+       numPlanets(team) < tempship->s_numplan + used_planstr) &&
+      !(shipvals[tmpPick].s_nflags & SFNMASSPRODUCED))
+  {
+    char buf[100];
+    sprintf(buf, "Your team's struggling economy cannot support a %s (%d+%d planets needed).", tempship->s_name, tempship->s_numplan, used_planstr);
+    warning(buf);
+    return 0;			/* have enough planets? */
+  }
+  return 1;
+}
+
+
+/*----------------------------------NUMSHIPS------------------------------*/
+/* This function counts the number of players on a team.  */
+
+int
+numShips(owner)
+  int owner;			/* the team to count for */
+{
+  int i;			/* looping var */
+  int num;			/* to hold player count */
+  struct player *p;		/* to point to players */
+
+  num = 0;			/* zero the count */
+  for (i = 0, p = players; i < MAXPLAYER; i++, p++)
+  {				/* go throgh players */
+    if (p->p_status != PFREE && p->p_team == owner)	/* if alive then */
+      num++;			/* inc player count */
+  }
+  return (num);			/* return number of ships */
+}
+
+
+
+
+/*------------------------------NUMPLANETS--------------------------------*/
+/* This function counts the number of planets a team has.  */
+
+int
+numPlanets(owner)
+  int owner;			/* the team to check for */
+{
+  int i;			/* looping var */
+  int num;			/* to hold count */
+  struct planet *p;		/* to point to a planet */
+
+  num = 0;			/* no planets found yet */
+  for (i = 0, p = planets; i < MAXPLANETS; i++, p++)
+  {
+    if (p->pl_owner == owner)	/* if planet owned by team then inc */
+      num++;
+  }
+  return (num);			/* return number of planets */
+}
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * Suspends warp prep [BDyess]
+ */
+void
+suspendPrep()
+{
+  /* check to see if the server allows warp prep to be suspended [BDyess] */
+  if (!configvals->warpprep_suspendable)
+    return;
+  if (me->p_flags & PFWARPPREP)
+  {
+    me->p_flags |= PFWPSUSPENDED;	/* turn on suspended flag */
+    warning("Warp prep suspended.");
+  }
+  else
+  {
+    warning("Not in warp prep!");
+  }
+}
+
+/*
+ * Unsuspends warp prep [BDyess]
+ */
+void
+unsuspendPrep()
+{
+  /* check to see if the server allows warp prep to be suspended [BDyess] */
+  if (!configvals->warpprep_suspendable)
+    return;
+  if (me->p_flags & PFWARPPREP)
+  {
+    me->p_flags &= ~PFWPSUSPENDED;	/* turn off suspended flag */
+    warning("Warp prep continued.");
+  }
+  else
+  {
+    warning("Not in warp prep!");
+  }
+}
+
+/*-------END OF LINE----*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/listen.c	Sat Dec 06 04:37:03 1997 +0000
@@ -0,0 +1,634 @@
+/*--------------------------------------------------------------------------
+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
+--------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------
+Startup program for netrek.  Listens for connections, then forks off
+servers.  Based on code written by Brett McCoy, but heavily modified.
+
+Note that descriptor 2 is duped to descriptor 1, so that stdout and
+stderr go to the same file.
+--------------------------------------------------------------------------*/
+
+#ifndef apollo
+#include <unistd.h>
+#endif
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#ifdef SVR4
+#include <sys/termios.h>
+#endif				/* SVR4 */
+#include <netdb.h>
+#include <errno.h>
+#include <time.h>
+#include <netinet/in.h>
+#include <fcntl.h>
+#include <varargs.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <string.h>
+#ifdef SYSV
+#include <fcntl.h>
+#endif
+#ifdef hpux
+#include <sys/ptyio.h>
+#endif
+#include "defs.h"
+#include "path.h"
+#include "data.h"
+
+/* #define DEF_PORT	2592	/* port to listen on */
+/*
+ * #define NTSERV		"bin/ntserv"
+ * 
+ * #define METASERVER	"metaserver.ecst.csuchico.edu"
+ */
+/*
+ * Since the metaserver address is a nameserver alias, we can't just compare
+ * the peer hostname with the setting of METASERVER.  The peer hostname
+ * returned by gethostbyaddr() will be the machine's real name, which will be
+ * different (and could change).
+ * 
+ * So, we'll do a gethostbyname() on METASERVER to get an IP address, then we
+ * can compare that with the connecting peer.
+ * 
+ * It'd be overkill to get the metaserver's IP address with every connection;
+ * and it may be inadequate to get it just once at startup, since listen can
+ * exist for long periods of time, and the metaserver's IP address could be
+ * changed in that time.
+ * 
+ * So, we'll grab the IP address at least every META_UPDATE_TIME seconds
+ */
+#define META_UPDATE_TIME (5*60*60)	/* five hours */
+
+void printlistenUsage();
+void set_env();
+int listenSock;
+short port = PORT;
+char *program;
+int meta_addr;
+
+char *dateTime();
+void detach();
+void getConnections();
+void getListenSock();
+void multClose();
+void reaper();
+void terminate();
+
+/*
+ * Error reporting functions ripped from my library.
+ */
+void syserr();
+void warnerr();
+void fatlerr();
+void err();
+char *lasterr();
+void print_pid();
+
+struct hostent *gethostbyaddr();
+char *inet_ntoa();
+int metaserverflag;
+char *leagueflag = 0;
+char *observerflag = 0;
+
+#define NEA	10
+char *extraargs[NEA];
+int extraargc = 0;
+
+char *ntserv_binary = NTSERV;
+
+/*
+ * the System-V signal() function provides the older, unreliable signal
+ * semantics.  So, this is an implementation of signal using sigaction.
+ */
+
+void (*
+      r_signal(sig, func)) ()
+  int sig;
+  void (*func) ();
+{
+  struct sigaction act, oact;
+
+  act.sa_handler = func;
+
+  sigemptyset(&act.sa_mask);
+  act.sa_flags = 0;
+#ifdef SA_RESTART
+  act.sa_flags |= SA_RESTART;
+#endif
+
+  if (sigaction(sig, &act, &oact) < 0)
+    return (SIG_ERR);
+
+  return (oact.sa_handler);
+}
+
+
+int
+main(argc, argv)
+  int argc;
+  char *argv[];
+{
+  int i, key;
+  int nogo = 0;
+  struct hostent *he;
+  struct timeval tv;
+  time_t stamp, now;
+
+  metaserverflag = 0;
+#ifndef apollo
+  nice(-20);
+  nice(-20);
+  nice(-20);
+#endif
+
+  for (i = 1; i < argc; i++)
+  {
+    if (*argv[i] == '-')
+    {
+      switch (argv[i][1])
+      {
+       case 'p':
+	port = atoi(argv[i + 1]);
+	break;
+       case 'k':
+	if (++i < argc && sscanf(argv[i], "%d", &key) > 0 && key > 0)
+	  set_env("TREKSHMKEY", argv[i]);
+	else
+	  nogo++;
+	break;
+       case 'b':
+	ntserv_binary = argv[++i];
+	break;
+       case 'h':
+       case 'u':		/* for old times sake, the others don't do
+				 * this, but this one does so it doesn't pass
+				 * to ntserv */
+       case '-':		/* same with this */
+	nogo++;
+	break;
+       default:
+	/* all unknown arguments are passed through to ntserv. */
+	extraargs[extraargc++] = argv[i];
+      }
+    }
+    /* else just ignore non flags */
+  }
+
+  if ((program = strrchr(argv[0], '/')))
+    ++program;
+  else
+    program = argv[0];		/* let err functions know our name */
+
+  if (nogo)
+    printlistenUsage(program);
+
+  detach();			/* detach from terminal, close files, etc. */
+  print_pid();			/* log the new PID */
+  getListenSock();
+  r_signal(SIGCHLD, reaper);
+  r_signal(SIGTERM, terminate);
+  r_signal(SIGHUP, SIG_IGN);
+
+  meta_addr = 0;
+  stamp = 0;
+  tv.tv_sec = 1;
+  tv.tv_usec = 0;
+
+  while (1)
+  {
+    now = time(0);
+    if (now - stamp > META_UPDATE_TIME)
+    {
+      he = gethostbyname(METASERVER);
+      if (he)
+	meta_addr = *((int *) he->h_addr);
+      stamp = now;
+    }
+    getConnections();
+    select(0, 0, 0, 0, &tv);	/* wait one sec between each connection */
+  }
+}
+
+/***********************************************************************
+ * Detach process in various ways.
+ */
+
+void
+detach()
+{
+  int fd, rc, mode;
+  char *fname;
+
+  mode = S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR;
+  /* fname = build_path("startup.log"); */
+  fname = build_path("logs/startup.log");
+  if ((fd = open(fname, O_WRONLY | O_CREAT | O_APPEND, mode)) == -1)
+    syserr(1, "detach", "couldn't open log file. [%s]", dateTime());
+  dup2(fd, 2);
+  dup2(fd, 1);
+  multClose(1, 2, -1);		/* close all other file descriptors */
+  warnerr(0, "started at %s on port %d.", dateTime(), port);
+
+  /* fork once to escape the shells job control */
+  if ((rc = fork()) > 0)
+    exit(0);
+  else if (rc < 0)
+    syserr(1, "detach", "couldn't fork. [%s]", dateTime());
+
+  /* now detach from the controlling terminal */
+
+#ifdef _SEQUENT_
+  if ((fd = open("/dev/tty", O_RDWR | O_NOCTTY, 0)) >= 0)
+  {
+    (void) close(fd);
+  }
+#else
+  if ((fd = open("/dev/tty", O_RDWR, 0)) == -1)
+  {
+    warnerr("detach", "couldn't open tty, assuming still okay. [%s]",
+	    dateTime());
+    return;
+  }
+#if defined(SYSV) && defined(TIOCTTY)
+  {
+    int zero = 0;
+    ioctl(fd, TIOCTTY, &zero);
+  }
+#else
+  ioctl(fd, TIOCNOTTY, 0);
+#endif
+  close(fd);
+#endif				/* _SEQUENT_ */
+
+  setsid();			/* make us a new process group/session */
+}
+
+/***********************************************************************
+ */
+
+void
+getListenSock()
+{
+  struct sockaddr_in addr;
+
+  if ((listenSock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
+    syserr(1, "getListenSock", "can't create listen socket. [%s]",
+	   dateTime());
+
+  addr.sin_family = AF_INET;
+  addr.sin_addr.s_addr = INADDR_ANY;
+  addr.sin_port = htons(port);
+  {
+    /* added this so we could handle nuking listen. KAO 3/26/93 */
+    int foo = 1;
+    if (setsockopt(listenSock, SOL_SOCKET, SO_REUSEADDR, (char *) &foo,
+		   sizeof(foo)) == -1)
+    {
+      fprintf(stderr, "Error setting socket options in listen.\n");
+      exit(1);
+    }
+  }
+  if (bind(listenSock, (struct sockaddr *) & addr, sizeof(addr)) < 0)
+    syserr(1, "getListenSock", "can't bind listen socket. [%s]",
+	   dateTime());
+
+  if (listen(listenSock, 5) != 0)
+    syserr(1, "getListenSock", "can't listen to socket. [%s]", dateTime());
+}
+
+/***********************************************************************
+ */
+
+void
+getConnections()
+{
+  int len, sock, pid, pa;
+  struct sockaddr_in addr;
+  struct hostent *he;
+  char host[100];
+
+  len = sizeof(addr);
+  while ((sock = accept(listenSock, (struct sockaddr *) & addr, &len)) < 0)
+  {
+    /* if we got interrupted by a dying child, just try again */
+    if (errno == EINTR)
+      continue;
+    else
+      syserr(1, "getConnections",
+	     "accept() on listen socket failed. [%s]", dateTime());
+  }
+
+  /* get the host name */
+  he = gethostbyaddr((char *) &addr.sin_addr.s_addr,
+		     sizeof(addr.sin_addr.s_addr), AF_INET);
+  if (he != 0)
+  {
+    strcpy(host, he->h_name);
+    pa = *((int *) he->h_addr);
+  }
+  else
+  {
+    strcpy(host, inet_ntoa(addr.sin_addr));
+    pa = (int) addr.sin_addr.s_addr;
+  }
+
+  if (pa == meta_addr)
+    metaserverflag = 1;
+  /* else */
+  warnerr(0, "connect: %-33s[%s][%d]", host, dateTime(), metaserverflag);
+
+  /* fork off a server */
+  if ((pid = fork()) == 0)
+  {
+    char *newargv[10];
+    int newargc = 0;
+    int i;
+    char *binname;
+    binname = build_path(ntserv_binary);
+    dup2(sock, 0);
+    multClose(0, 1, 2, -1);	/* close everything else */
+
+    newargv[newargc++] = "ntserv";
+    if (metaserverflag == 1)
+      newargv[newargc++] = "-M";
+    for (i = 0; i < extraargc; i++)
+      newargv[newargc++] = extraargs[i];
+    newargv[newargc++] = host;
+    newargv[newargc] = 0;
+
+    execv(binname, newargv);
+
+    syserr(1, "getConnections",
+	   "couldn't execv %s as the server. [%s]",
+	   binname, dateTime());
+    exit(1);
+  }
+  else if (pid < 0)
+    syserr(1, "getConnections", "can't fork. [%s]", dateTime());
+
+  close(sock);
+  metaserverflag = 0;
+}
+
+/***********************************************************************
+ * Adds "var=value" to environment list
+ */
+
+void
+set_env(var, value)
+  char *var, *value;
+{
+  char *buf;
+#if defined(SYSV) || defined(sparc)
+  buf = malloc(strlen(var) + strlen(value) + 2);
+  if (!buf)
+    syserr(1, "set_env", "malloc() failed. [%s]", dateTime());
+
+  strcpy(buf, var);
+  strcat(buf, "=");
+  strcat(buf, value);
+
+  putenv(buf);
+#else
+  /* don't need to malloc space, setenv() does it for us */
+  setenv(var, value, 1);
+#endif
+}
+
+
+/***********************************************************************
+ * Returns a string containing the date and time.  String area is static
+ * and reused.
+ */
+
+char *
+dateTime()
+{
+  time_t t;
+  char *s;
+
+  time(&t);
+  s = ctime(&t);
+  s[24] = '\0';			/* wipe-out the newline */
+  return s;
+}
+
+/***********************************************************************
+ * Handler for SIGTERM.  Closes and shutdowns everything.
+ */
+
+void
+terminate()
+{
+  int s;
+
+  fatlerr(1, "terminate", "killed. [%s]", dateTime());
+#ifdef SYSV
+  s = sysconf(_SC_OPEN_MAX);
+  if (s < 0)			/* value for OPEN_MAX is indeterminate, */
+    s = 32;			/* so make a guess */
+#else
+  s = getdtablesize();
+#endif
+  /* shutdown and close everything */
+  for (; s >= 0; s--)
+  {
+    shutdown(s, 2);
+    close(s);
+  }
+}
+
+/***********************************************************************
+ * Waits on zombie children.
+ */
+
+void
+reaper()
+{
+#ifndef SVR4
+  while (wait3(0, WNOHANG, 0) > 0);
+#else
+  while (waitpid(0, 0, WNOHANG) > 0);
+#endif				/* SVR4 */
+}
+
+/***********************************************************************
+ * Close all file descriptors except the ones specified in the argument list.
+ * The list of file descriptors is terminated with -1 as the last arg.
+ */
+
+void
+multClose(va_alist) va_dcl
+{
+  va_list args;
+  int fds[100], nfds, fd, ts, i, j;
+
+  /* get all descriptors to be saved into the array fds */
+  va_start(args);
+  for (nfds = 0; nfds < 99; nfds++)
+  {
+    if ((fd = va_arg(args, int)) == -1)
+      break;
+    else
+      fds[nfds] = fd;
+  }
+
+#ifdef SYSV
+  ts = sysconf(_SC_OPEN_MAX);
+  if (ts < 0)			/* value for OPEN_MAX is indeterminate, */
+    ts = 32;			/* so make a guess */
+#else
+  ts = getdtablesize();
+#endif
+
+  /*
+   * close all descriptors, but first check the fds array to see if this one
+   * is an exception
+   */
+  for (i = 0; i < ts; i++)
+  {
+    for (j = 0; j < nfds; j++)
+      if (i == fds[j])
+	break;
+    if (j == nfds)
+      close(i);
+  }
+}
+
+/***********************************************************************
+ * Error reporting functions taken from my library.
+ */
+
+extern int sys_nerr;
+#ifndef FreeBSD
+extern char *sys_errlist[];
+#endif
+extern int errno;
+
+void
+syserr(va_alist) va_dcl
+{
+  va_list args;
+  int rc;
+
+  va_start(args);
+  rc = va_arg(args, int);
+  err(args);
+  if (errno < sys_nerr)
+    fprintf(stderr, "     system message: %s\n", sys_errlist[errno]);
+
+  exit(rc);
+}
+
+void
+warnerr(va_alist) va_dcl
+{
+  va_list args;
+
+  va_start(args);
+  err(args);
+}
+
+void
+fatlerr(va_alist) va_dcl
+{
+  va_list args;
+  int rc;
+
+  va_start(args);
+  rc = va_arg(args, int);
+  err(args);
+
+  exit(rc);
+}
+
+void
+err(args)
+  va_list args;
+{
+
+  char *func, *fmt;
+
+  if (program != 0)
+    fprintf(stderr, "%s", program);
+  func = va_arg(args, char *);
+  if (func != 0 && strcmp(func, "") != 0)
+    fprintf(stderr, "(%s)", func);
+  fprintf(stderr, ": ");
+
+  fmt = va_arg(args, char *);
+  vfprintf(stderr, fmt, args);
+  fputc('\n', stderr);
+  fflush(stderr);
+}
+
+char *
+lasterr()
+{
+  if (errno < sys_nerr)
+    return sys_errlist[errno];
+  else
+    return "No message text for this error.";
+}
+
+/*---------------------[ prints the usage of listen ]---------------------*/
+
+void 
+printlistenUsage(char name[])
+{
+  int x;
+  char message[][255] = {
+    "\n\t'%s [options]'\n\n",
+    "Options:\n",
+    "\t-h      help (this usage message)\n",
+    "\t-p      port other than default port\n",
+    "\t-k n    use n as shared memory key number\n\n",
+    "Any unrecognized options are passed through to ntserv. For an up\n",
+    "to date listing of available ntserv options check the binary.\n",
+    "\nNOTE: in league play you must start up two listen processes, ",
+    "one for each port.\n\n",
+    "\0"
+  };
+
+  fprintf(stderr, "-- NetrekII (Paradise), %s --\n", PARAVERS);
+  for (x = 0; *message[x] != '\0'; x++)
+    fprintf(stderr, message[x], name);
+
+  exit(1);
+}
+
+/*--------------------------[ printlistenUsage ]--------------------------*/
+
+/* set the pid logfile (BG) */
+void 
+print_pid()
+{
+  char *fname;
+  FILE *fptr;
+
+  fname = build_path("logs/listen.pid");
+  fptr = fopen(fname, "w+");
+  fprintf(fptr, "%d", getpid());
+  fclose(fptr);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main.c	Sat Dec 06 04:37:03 1997 +0000
@@ -0,0 +1,1211 @@
+/*--------------------------------------------------------------------------
+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[] = "@(#)ntserv";
+
+#include "config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <signal.h>
+#include <setjmp.h>
+#include <pwd.h>
+#include <sys/time.h>
+#include <sys/wait.h>
+#include <sys/resource.h>
+#include <unistd.h>
+
+#include "defs.h"
+#include "struct.h"
+#include "data.h"
+#include "packets.h"
+#include "shmem.h"
+#include "path.h"
+
+#if 0
+#define D(s) do { s } while(0)
+#else
+#define D(s)
+#endif
+
+
+#if 0
+jmp_buf env;
+#endif
+
+int startTkills, startTlosses, startTarms, startTplanets, startTticks;
+char start_login[16];		/* change 1/25/91 TC */
+char start_name[16];		/* change 1/25/91 TC */
+int goAway = 0;			/* change 4/14/91 TC */
+int ignored[MAXPLAYER];		/* change 7/24/91 TC */
+
+int overload = 0;		/* global 7/31/91 TC */
+/* overload indicates a request for a reserved slot */
+
+int indie = 0;			/* always be indie 8/28/91 TC */
+
+
+extern void load_time_access();
+void printntservUsage();
+extern pid_t getpid();
+extern int connectToClient();
+extern int checkSocket();
+extern int initClientData();
+extern int socketPause();
+extern int readFromClient();
+extern int checkVersion();
+extern int findslot();
+extern void updateSelf();
+extern void updateShips();
+extern void updatePlanets();
+extern void updateTerrain();
+extern void flushSockBuf();
+extern int getname();
+extern int sendShipCap();
+extern int logEntry();
+extern int getEntry();
+void printStats();
+void exitGame();
+#if defined(sparc) && !defined(SVR4)
+int atexitfunc( /* int, caddr_t */ );
+#else
+void atexitfunc();
+#endif
+extern void (*r_signal()) ();
+extern int enter();
+extern int input();
+extern int setitimer();
+extern int pmessage2();
+extern int savestats();
+extern void move_player();
+extern int sendMotdLine();
+extern int time_access();
+void doMotdPics();
+extern int numPlanets();
+extern int sendMotdPic();
+extern int ParseXbmFile();
+
+int
+main(argc, argv)
+  int argc;
+  char **argv;
+{
+  int intrupt();
+  char *getenv();
+  int team, s_type;
+  int pno;
+  int usage = 0;		/* Flag saying tell usage */
+  int errorc = 0;		/* Error count */
+  char *errorv[5];		/* Error Vector (cannot have more than 5) */
+  char *name, *ptr;
+  int reaper();
+  int callHost = 0;
+  long starttime;
+  enum HomeAway homeaway = NEITHER;
+  int observer = 0;
+
+  argv0 = argv[0];
+
+  pno = time(NULL);
+
+
+  /* load_time_acess - read in the hours file, Larry's. */
+
+  load_time_access();
+
+  name = *argv++;
+  argc--;
+  if ((ptr = strrchr(name, '/')) != NULL)
+    name = ptr + 1;
+  while (*argv)
+  {
+    if (**argv == '-')
+      ++* argv;
+    else
+      break;
+
+    argc--;
+    ptr = *argv++;
+    while (*ptr)
+    {
+      switch (*ptr)
+      {
+       case 'u':		/* for old times sake */
+       case '-':		/* this will help the --help people */
+       case 'h':
+	usage++;
+	break;
+       case 'i':
+	indie++;
+	break;			/* 8/28/91 TC */
+       case 'R':
+	if (getuid() == geteuid())
+	  overload++;
+	break;
+       case 's':
+	xtrekPort = atoi(*argv);
+	callHost = 1;
+	argv++;
+	argc--;
+	break;
+       case 'M':
+	blk_metaserver = 1;
+	break;
+       case 'd':
+	host = *argv;
+	argc--;
+	argv++;
+	break;
+	/* netrek league stuff */
+       case 'O':
+	observer = 1;
+	break;
+       case 'H':
+	homeaway = HOME;
+	break;
+       case 'A':
+	homeaway = AWAY;
+	break;
+       default:
+	{
+	  char buffer[100];
+	  sprintf(buffer, "Unknown option '%c'\n", *ptr);
+	  errorv[errorc++] = buffer;
+	  break;
+	}
+      }
+      if (usage)
+	break;
+      ptr++;
+    }
+  }
+
+  if (usage || errorc)
+  {
+    int x;
+    char message[][255] = {
+      "\n\t'%s [options] -s <socket number> <display address>'\n\n",
+      "Options:\n",
+      "\t-h   Help (this usage message)\n",
+      "\t-i   Team independant\n",
+      "\t-R   Reserved slot\n",
+      "\t-s   Socket number\n",
+      "\t-M   Metaserver\n",
+      "\t-d   Display\n",
+      "\t-O   Observer\n",
+      "\t-H   Home (League Play)\n",
+      "\t-A   Away (League Play)\n",
+      "\nNOTE: %s is designed to be launched by the startup process\n\n",
+      "\0"
+    };
+
+    fprintf(stderr, "-- NetrekII (Paradise), %s --\n", PARAVERS);
+    for (x = 0; x < errorc; x++)
+      fprintf(stderr, "\n%s: %s", argv0, errorv[x]);
+    for (x = 0; *message[x] != '\0'; x++)
+      fprintf(stderr, message[x], argv0);
+
+    exit(1);
+  }
+
+  openmem(1, homeaway != NEITHER);
+
+  /* compatability */
+  if (argc > 0)
+    host = argv[0];
+  srand48(getpid() + time((time_t *) 0));
+  /* this finds the shared memory information */
+
+#if 0
+  if (blk_metaserver)
+  {
+    FILE *ptr;
+    char *buf;
+    buf = build_path("logs/metaserver.log");
+    ptr = fopen(buf, "a");
+    fprintf(ptr, "Connection from meta-server\n");
+    fclose(ptr);
+  }
+#endif
+
+
+  me = NULL;			/* UDP fix (?) */
+  if (callHost)
+  {
+    if (!connectToClient(host, xtrekPort))
+    {
+      exit(0);
+    }
+  }
+  else
+  {
+    sock = 0;			/* Because we were forked by inetd! */
+    checkSocket();
+    initClientData();		/* "normally" called by connectToClient() */
+  }
+
+  starttime = time(NULL);
+  while (userVersion == 0)
+  {
+    /*
+     * Waiting for user to send his version number. We give him ten seconds
+     * to do so...
+     */
+    if (starttime + 10 < time(NULL))
+    {
+      exit(1);
+    }
+    socketPause();
+    readFromClient();
+  }
+  if (!checkVersion())
+    exit(1);
+
+  pno = findslot(overload, homeaway);
+  if (pno < 0)
+  {
+    /* print some appropriate message */
+    exit(1);
+  }
+
+#if defined(sparc) && !defined(SVR4)
+  on_exit(atexitfunc, (caddr_t) 0);
+#else
+  atexit(atexitfunc);		/* register a function to execute at exit */
+#endif
+
+  me = &players[pno];
+  me->p_no = pno;
+  me->p_team = NOBODY;
+  me->p_stats.st_royal = 0;
+#ifdef	RC_DISTRESS
+  me->gen_distress = 0;		/* default to RCD off */
+#endif
+  me->p_ntspid = getpid();
+  myship = &me->p_ship;
+  mystats = &me->p_stats;
+  lastm = mctl->mc_current;
+  me->p_lastrefit = -1;
+  me->p_spyable = 1;
+  me->p_teamspy = ~0;
+#if 0
+  me->p_planfrac = 0;		/* reset fractional parts */
+  me->p_bombfrac = 0;		/* reset fractional parts */
+#endif
+
+  /* --------------------------[ CLUECHECK stuff ]-------------------------- */
+#ifdef CLUECHECK1
+  me->p_cluedelay = 10;
+  me->p_cluecountdown = 0;
+#endif
+
+#ifdef CLUECHECK2
+  me->p_cluedelay = lrand48() % 1000;	/* so it doesn't ask them immediately */
+  me->p_cluecountdown = 0;
+#endif
+  /* ----------------------------------------------------------------------- */
+
+#ifndef AUTHORIZE
+  strcpy(RSA_client_type, "server doesn't support RSA");
+#endif
+
+  (void) r_signal(SIGINT, SIG_IGN);
+  (void) r_signal(SIGCHLD, reaper);
+
+  /*
+   * We set these so we won't bother updating him on the location of the
+   * other players in the galaxy which he is not near.  There is no real harm
+   * to doing this, except that he would then get more information than he
+   * deserves. It is kind of a hack, but should be harmless.
+   */
+  me->p_x = -100000;
+  me->p_y = -100000;
+  me->p_homeaway = homeaway;
+  me->p_observer = observer;
+
+#if 0
+  updateGameparams();
+#endif
+
+  updateSelf();			/* so he gets info on who he is */
+  updateShips();		/* put this back so maybe something will work */
+  /* with Andy's meta-server */
+
+  if (!blk_metaserver)
+  {
+    updateStatus();
+    updatePlanets();
+    updateTerrain();
+  }
+#if 1
+  updateGameparams();
+#endif
+
+  flushSockBuf();
+
+  /* Get login name */
+
+#if 0
+  if ((pwent = getpwuid(getuid())) != NULL)
+    (void) strncpy(login, pwent->pw_name, sizeof(login));
+  else
+#endif
+    (void) strncpy(login, "Bozo", sizeof(login));
+  login[sizeof(login) - 1] = '\0';
+
+  strcpy(pseudo, "Guest");
+
+  strcpy(me->p_name, pseudo);
+  me->p_team = ALLTEAM;
+  getname();
+  if (me->p_stats.st_rank >= NUMRANKS)
+    me->p_stats.st_rank = NUMRANKS - 1;
+  if (me->p_stats.st_royal >= NUMROYALRANKS)
+    me->p_stats.st_royal = NUMROYALRANKS - 1;
+  strcpy(pseudo, me->p_name);
+  strcpy(start_name, me->p_name);	/* change 1/25/91 TC */
+
+  sendShipCap();		/* KAO 1/25/93 */
+
+  keeppeace = (me->p_stats.st_flags & ST_KEEPPEACE) == ST_KEEPPEACE;
+
+  /*
+   * Set p_hostile to hostile, so if keeppeace is on, the guy starts off
+   * hating everyone (like a good fighter should)
+   */
+  me->p_hostile = (FED | ROM | KLI | ORI);
+  s_type = CRUISER;
+  me->p_planets = 0;
+  me->p_armsbomb = 0;
+  me->p_dooshes = 0;
+  me->p_resbomb = 0;
+  /* Set up a reasonable default */
+  me->p_whydead = KQUIT;
+
+  (void) strncpy(me->p_login, login, sizeof(me->p_login));
+  me->p_login[sizeof(me->p_login) - 1] = '\0';
+  strcpy(start_login, login);	/* change 1/25/91 TC */
+  {
+    int i;
+    for (i = 0; i < MAXPLAYER; i++)
+      ignored[i] = 0;
+  }
+
+  (void) strncpy(me->p_monitor, host, sizeof(me->p_monitor));
+  me->p_monitor[sizeof(me->p_monitor) - 1] = '\0';
+
+  /* assume this is only place p_monitor is set, and mirror accordingly */
+  /* 4/13/92 TC */
+  (void) strncpy(me->p_full_hostname, host, sizeof(me->p_full_hostname));
+  me->p_full_hostname[sizeof(me->p_full_hostname) - 1] = '\0';
+
+  logEntry();			/* moved down to get login/monitor 2/12/92
+				 * TMC */
+
+  me->p_avrt = -1;		/* ping stats */
+  me->p_stdv = -1;
+  me->p_pkls = -1;
+
+  startTkills = me->p_stats.st_tkills;
+  startTlosses = me->p_stats.st_tlosses;
+  startTarms = me->p_stats.st_tarmsbomb;
+  startTplanets = me->p_stats.st_tplanets;
+  startTticks = me->p_stats.st_tticks;
+
+  r_signal(SIGHUP, exitGame);	/* allows use of HUP to force a clean exit */
+
+
+
+  me->p_status = POUTFIT;
+  repCount = 0;
+
+  while (1)
+  {
+    switch (me->p_status)
+    {
+     case POUTFIT:
+     case PTQUEUE:
+      /* give the player the motd and find out which team he wants */
+      if (me->p_status != PALIVE)
+      {
+	me->p_x = -100000;
+	me->p_y = -100000;
+	updateSelf();
+	updateShips();
+	teamPick = -1;
+	flushSockBuf();
+	getEntry(&team, &s_type);
+      }
+      if (goAway)
+      {				/* change 4/14/91 TC */
+	printStats();
+	exit(0);
+      }
+      if (team == -1)
+      {
+	exitGame();
+      }
+
+      if (indie)
+	team = 4;		/* force to independent 8/28/91 TC */
+      inputMask = -1;		/* Allow all input now */
+      enter(team, 0, pno, s_type, -1);
+      /* for (i = 0; i < NSIG; i++) { r_signal(i, SIG_IGN); } */
+
+      me->p_status = me->p_observer ? POBSERVE : PALIVE;	/* Put player in game */
+      me->p_ghostbuster = 0;
+      break;
+     case PALIVE:
+     case PEXPLODE:
+     case PDEAD:
+     case POBSERVE:
+      /* Get input until the player quits or dies */
+
+
+      input();
+      break;
+     default:
+      if (tmpPick != PATROL)
+      {
+	printf("player status = %d.  exiting\n", me->p_status);
+	exitGame();
+      }
+    }
+  }
+
+  /* NOTREACHED */
+  return 1;
+}
+
+extern int setflag();		/* input.c */
+
+int interrupting = 0;
+
+void
+stop_interruptor()
+{
+  struct itimerval udt;
+
+  if (!interrupting)
+    return;
+
+  r_signal(SIGALRM, SIG_IGN);	/* set up signals */
+  udt.it_interval.tv_sec = 0;
+  udt.it_interval.tv_usec = 0;
+  udt.it_value.tv_sec = 0;
+  udt.it_value.tv_usec = 0;
+  setitimer(ITIMER_REAL, &udt, 0);
+
+  interrupting = 0;
+}
+
+void
+start_interruptor()
+{
+  struct itimerval udt;
+
+  if (interrupting)
+    return;
+
+  {
+    int min_delay = me->p_observer
+    ? configvals->min_observer_upd_delay
+    : configvals->min_upd_delay;
+
+    if (timerDelay < min_delay)
+      timerDelay = min_delay;
+  }
+
+  r_signal(SIGALRM, SIG_IGN);	/* set up signals */
+  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);
+
+  r_signal(SIGALRM, setflag);
+
+  interrupting = 1;
+}
+
+#if 0
+
+/*
+ * this is TOTALLY untested.  It probably doesn't belong in this file,
+ * either.  When I figure out all the mechanisms, this will replace the while
+ * loop in main().  RF
+ */
+
+void
+inputloop()
+{
+  static int switching = -1;	/* is the player changing teams? */
+
+  int status = me->p_status;
+
+  while (1)
+  {
+    switch (status)
+    {
+     case PFREE:
+      status = me->p_status = PDEAD;
+      me->p_explode = 600;
+      stop_interruptor();
+      break;
+
+     case POUTFIT:
+     case PTQUEUE:
+      updateSelf();
+      updateShips();
+      sendMaskPacket(tournamentMask(me->p_team));
+      briefUpdateClient();
+      teamPick = -1;
+      socketPause();
+      break;
+
+     case PEXPLODE:
+     case PDEAD:
+      inputMask = 0;
+     case PALIVE:
+      socketWait();
+      delay_interrupt();	/* don't let client read be interrupted by
+				 * the interval timer */
+      /*
+       * ^-- won't work.. delay_interrupt doesn't stop ALRMs from happening
+       * (HAK 9/21)
+       */
+      break;
+    }
+
+    /* me->p_status could change in here. */
+    readFromClient();
+
+    if (isClientDead())
+    {
+      if (!reconnect())
+      {
+	/* me->p_status=PFREE; should this be done?  RF */
+	exit(0);
+      }
+    }
+    switch (status)
+    {
+     case POUTFIT:
+     case PTQUEUE:
+      if (teamPick == -1)
+	break;
+
+      if (teamPick < 0 || teamPick > 3 /* XXX */ )
+      {
+	warning("That is not a valid team.");
+	sendPickokPacket(0);
+      }
+      else if (!(tournamentMask(me->p_team) & (1 << teamPick)))
+      {
+	warning("I cannot allow that.  Pick another team");
+	sendPickokPacket(0);
+      }
+      else if (((1 << teamPick) != me->p_team) &&
+	       (me->p_team != ALLTEAM) &&
+	       switching != teamPick &&
+	       me->p_whydead != KGENOCIDE)
+      {				/* switching teams */
+	switching = teamPick;
+	warning("Please confirm change of teams.  Select the new team again.");
+	sendPickokPacket(0);
+      }
+      else if (shipPick < 0 || shipPick >= NUM_TYPES)
+      {
+	/* His team choice is ok. */
+	warning("That is an illegal ship type.  Try again.");
+	sendPickokPacket(0);
+      }
+      else if (!allowed_ship(1 << teamPick, mystats->st_rank, mystats->st_royal, shipPick))
+      {
+	sendPickokPacket(0);
+      }
+      else
+      {
+
+	if (goAway)
+	{			/* what does this do ? */
+	  printStats();
+	  exit(0);
+	}
+	if (indie)
+	  me->p_team = 4;
+
+	inputMask = -1;
+
+	enter(teamPick, 0, me->p_no, shipPick, -1);
+
+	status = me->p_status = me->p_observer ? POBSERVER : PALIVE;
+	start_interruptor();	/* since we're alive, we need regular
+				 * interrupts now */
+
+	me->p_ghostbuster = 0;
+
+	repCount = 0;
+
+      }
+      break;
+     case PALIVE:
+     case PEXPLODE:
+     case PDEAD:
+      if (0 /* sendflag */ )
+      {				/* this is still busted, ugh */
+	check_authentication();
+	if (me->p_status == PFREE)
+	{
+	  me->p_ghostbuster = 0;
+	  me->p_status = PDEAD;
+	}
+	if ((me->p_status == PDEAD || me->p_status == POUTFIT)
+	    && (me->p_ntorp <= 0)
+	    && (me->p_nplasmatorp <= 0))
+	{
+	  stop_interruptor();
+	  death();
+	  status = POUTFIT;
+	}
+	auto_features();
+	updateClient();
+
+	/* sendflag=0;   ugh, broke */
+      }
+      reenable_interrupt();
+    }
+  }
+}
+
+#endif
+
+
+void
+exitGame()
+{
+  char buf[80];
+  char addrbuf[20];
+
+  if (me != NULL && me->p_team != ALLTEAM)
+  {
+    sprintf(buf, "%s %s (%s) leaving game (%.16s@%.32s)",
+	    ((me->p_stats.st_royal) ? royal[me->p_stats.st_royal].name
+	     : ranks[me->p_stats.st_rank].name),
+	    me->p_name,
+	    twoletters(me),
+	    me->p_login,
+	    me->p_full_hostname
+      );
+    sprintf(addrbuf, " %s->ALL", twoletters(me));
+    pmessage2(buf, 0, MALL | MLEAVE, addrbuf, me->p_no);
+    me->p_stats.st_flags &= ~ST_CYBORG;	/* clear this flag 8/27/91 TC */
+    savestats();
+    printStats();
+  }
+  me->p_status = PFREE;
+  move_player(me->p_no, -1, -1, 1);
+  exit(0);
+}
+
+#if defined(sparc) && !defined(SVR4)
+int
+atexitfunc(status, arg)
+  int status;
+  caddr_t arg;
+#else
+void
+atexitfunc()
+#endif
+{
+  me->p_ntspid = 0;
+  me->p_status = PFREE;
+}
+
+#define	PLURAL(n)	(((n)==1)?"":"s")
+
+static char *weapon_types[WP_MAX] = {
+  "Plasma torpedos",
+  "Tractors",
+  "Missiles",
+  "Fighters",
+};
+
+void
+sendSysDefs()
+{
+  char buf[200], buf2[200];
+  int i;
+
+  sendMotdLine("\t@@@");
+
+  if (!time_access())
+  {
+    sendMotdLine("** WE ARE CLOSED, CHECK HOURS **");
+    sendMotdLine("");
+  }
+
+  sendMotdLine("Available ship types:");
+  buf[0] = 0;
+  for (i = 0; i < NUM_TYPES; i++)
+  {
+    struct ship *s = &shipvals[i];
+    if (!shipsallowed[i])
+      continue;
+    sprintf(buf2, "   %c) %s/%c%c", s->s_letter, s->s_name,
+	    s->s_desig1, s->s_desig2);
+    if (strlen(buf) + strlen(buf2) > 80)
+    {
+      sendMotdLine(buf);
+      strcpy(buf, buf2);
+    }
+    else
+    {
+      strcat(buf, buf2);
+    }
+  }
+  /* guaranteed to have stuff here */
+  sendMotdLine(buf);
+  sendMotdLine("");
+  sendMotdLine(
+	       "SHIP         REQUIRED RANK   BUILD TIME    LIMIT     NUM PLYRS  NUM PLNTS");
+
+  for (i = 0; i < NUM_TYPES; i++)
+  {
+    struct ship *s = &shipvals[i];
+    if (!shipsallowed[i])
+      continue;
+    buf2[0] = 0;
+    if (s->s_rank > 0 || s->s_timer > 0 || s->s_maxnum < 16 ||
+	s->s_numdefn || s->s_numplan)
+    {
+      sprintf(buf2, "%-13s%-16s", s->s_name,
+	      s->s_rank ? ranks[s->s_rank].name : "none");
+      if (s->s_timer > 0)
+	sprintf(buf, "%d minutes", s->s_timer);
+      else
+	strcpy(buf, "none");
+      sprintf(buf2 + strlen(buf2), "%-14s", buf);
+
+      if (s->s_maxnum < 16)
+	sprintf(buf, "%d/team", s->s_maxnum);
+      else
+	strcpy(buf, "none");
+      sprintf(buf2 + strlen(buf2), "%-12s  %-3d        %-3d", buf,
+	      s->s_numdefn, s->s_numplan);
+      sendMotdLine(buf2);
+    }
+  }
+  sendMotdLine("");
+
+
+  buf2[0] = 0;
+  for (i = 0; i < WP_MAX; i++)
+  {
+    if (weaponsallowed[i])
+    {
+      if (buf2[0])
+	strcat(buf2, ", ");
+      strcat(buf2, weapon_types[i]);
+    }
+  }
+  sprintf(buf, "Special weapons enabled: %s", buf2[0] ? buf2 : "none");
+  sendMotdLine(buf);
+
+  if (weaponsallowed[WP_PLASMA])
+  {
+    sprintf(buf, "You need %.1f kill%s to get plasma torpedos",
+	    configvals->plkills, PLURAL(configvals->plkills));
+    sendMotdLine(buf);
+  }
+  if (weaponsallowed[WP_MISSILE])
+  {
+    sprintf(buf, "You need %.1f kill%s to get missiles",
+	    configvals->mskills, PLURAL(configvals->mskills));
+    sendMotdLine(buf);
+  }
+  sendMotdLine("");
+
+  sprintf(buf, "Tournament mode requires %d player%s per team",
+	  configvals->tournplayers, PLURAL(configvals->tournplayers));
+  sendMotdLine(buf);
+  /* sendMotdLine(""); */
+
+  /* We don't blab about newturn */
+#if 0
+  sendMotdLine(configvals->hiddenenemy ?
+	       "Visibility is restricted during T-mode" :
+	       "Visibility is unlimited all the time");
+#endif
+  sendMotdLine(configvals->binconfirm ?
+	       "Only authorized binaries are allowed" :
+	       "Non-authorized binaries are detected but not rejected");
+
+  if (configvals->planetlimittype)
+  {
+    sprintf(buf, "Independent planets may be taken if your team has fewer than %d planets", configvals->planetsinplay);
+    sendMotdLine(buf);
+  }
+  else
+  {
+    sprintf(buf, "Only %d planets can be in play at once",
+	    configvals->planetsinplay);
+    sendMotdLine(buf);
+  }
+
+  if (configvals->planupdspd == 0)
+  {
+    sendMotdLine("Planets do not orbit their stars");
+  }
+  else
+  {
+    sprintf(buf, "Planets orbit their stars at a rate of %g",
+	    configvals->planupdspd);
+    sendMotdLine(buf);
+  }
+  sendMotdLine(configvals->warpdecel ?
+	       "New warp deceleration code is in effect" :
+	       "Old-style instant warp deceleration is in effect");
+  sprintf(buf, "The next galaxy will be generated using method #%d",
+	  configvals->galaxygenerator);
+  sendMotdLine(buf);
+  sendMotdLine
+    (configvals->affect_shiptimers_outside_T ?
+     "Ship deaths outside tournament mode affect construction timers" :
+     "Construction timers are not affected by ship deaths outside tournament mode");
+
+  sprintf(buf, "Cloaking during warp prep is %sallowed",
+	  configvals->cloakduringwarpprep ? "" : "not ");
+  sendMotdLine(buf);
+
+  sprintf(buf, "Cloaking during warp is %sallowed",
+	  configvals->cloakwhilewarping ? "" : "not ");
+  sendMotdLine(buf);
+
+  sprintf(buf, "Variable warp speed is %sabled",
+	  configvals->variable_warp ? "en" : "dis");
+  sendMotdLine(buf);
+
+  sprintf(buf, "Warp prep suspension is %sallowed",
+	  configvals->warpprep_suspendable ? "" : "not ");
+  sendMotdLine(buf);
+
+  switch (configvals->warpprepstyle)
+  {
+   case WPS_NOTRACT:
+    sendMotdLine("Tractors do not affect warp prep");
+    break;
+   case WPS_TABORT:
+    sendMotdLine("Tractors make warp fail to engage");
+    break;
+   case WPS_TPREVENT:
+    sendMotdLine("Tractors prevent entering warp");
+    break;
+   case WPS_TABORTNOW:
+    sendMotdLine("Tractors abort warp prep countdown");
+    break;
+   case WPS_TSUSPEND:
+    sendMotdLine("Tractors suspend warp prep countdown");
+    break;
+  }
+
+  sprintf(buf, "There is a %d%% chance that you'll orbit a planet CCW",
+	  (int) ((1.0 - configvals->orbitdirprob) * 100));
+  sendMotdLine(buf);
+
+  sprintf(buf, "Army growth: %d.  Pop choice: %d.  Pop speed: %d%%.",
+	configvals->popscheme, configvals->popchoice, configvals->popspeed);
+  sendMotdLine(buf);
+
+  if (configvals->warpzone)
+  {
+    sprintf(buf, "Warp zones are enabled with radius %d.",
+	    configvals->warpzone);
+  }
+  else
+  {
+    sprintf(buf, "Warp zones are disabled.");
+  }
+  sendMotdLine(buf);
+}
+
+void 
+sendMotd()
+{
+  FILE *motd;
+  char buf[100], buf2[30];	/* big enough... */
+  char *paths;
+
+  time_t curtime;
+  struct tm *tmstruct;
+  int hour, tacc;
+
+  time(&curtime);
+  tmstruct = localtime(&curtime);
+  if (!(hour = tmstruct->tm_hour % 12))
+    hour = 12;
+  sprintf(buf, "Netrek II (Paradise) server %s, connection established at %d:%02d%s.",
+	  PARAVERS,
+	  hour,
+	  tmstruct->tm_min,
+	  tmstruct->tm_hour >= 12 ? "pm" : "am");
+
+  /*
+   * if (!(tacc = time_access())) strcat(buf, "  WE'RE CLOSED, CHECK HOURS");
+   */
+  sendMotdLine(buf);
+  sendMotdLine(" ");
+
+  if (!blk_flag)
+  {
+    paths = build_path(WCMOTD);	/* Wrong client message */
+    if ((motd = fopen(paths, "r")) != NULL)
+    {
+      while (fgets(buf, sizeof(buf), motd) != NULL)
+      {
+	buf[strlen(buf) - 1] = '\0';
+	sendMotdLine(buf);
+      }
+      fclose(motd);
+    }
+    else
+    {				/* default message */
+      sendMotdLine(" ");
+      sendMotdLine(
+		   "      ****************************************************************");
+      sendMotdLine(" ");
+
+      sendMotdLine(
+		   "       This is a Paradise server; you need a Paradise client to play!");
+      sendMotdLine(" ");
+      sendMotdLine(
+		   "       Paradise clients can be had from");
+      sendMotdLine(
+		   "          ftp.cis.ufl.edu    pub/netrek.paradise/");
+      sendMotdLine(
+		   "          ftp.reed.edu       mirrors/netrek.paradise/");
+      sendMotdLine(" ");
+      sendMotdLine(
+		   "      ****************************************************************");
+    }
+    return;
+  }
+
+   /* if (blk_flag) */ 
+  {				/* added 1/19/93 KAO */
+    int i, first = 1;
+
+    strcpy(buf, "BLK: REFIT ");
+
+    for (i = 0; i < NUM_TYPES; i++)
+    {
+      struct ship *s = &shipvals[i];
+      if (!shipsallowed[i])
+	continue;
+
+      if (!first)
+	strcat(buf, ", ");
+      else
+	first = 0;
+
+      sprintf(buf2, "%c) %c%c", s->s_letter, s->s_desig1, s->s_desig2);
+      strcat(buf, buf2);
+    }
+    sendMotdLine(buf);
+  }
+  /* the following will read a motd */
+  if (!time_access())
+  {
+    paths = build_path(CLOSEDMOTD);
+    if ((motd = fopen(paths, "r")) == NULL)
+    {
+      paths = build_path(MOTD);
+      motd = fopen(paths, "r");
+    }
+  }
+  else
+  {
+    paths = build_path(MOTD);
+    motd = fopen(paths, "r");
+  }
+  if (motd != NULL)
+  {
+#ifdef CLUECHECK1
+    init_motdbuf(paths);
+#endif
+    while (fgets(buf, sizeof(buf), motd) != NULL)
+    {
+      buf[strlen(buf) - 1] = '\0';
+      sendMotdLine(buf);
+    }
+    (void) fclose(motd);
+  }
+  sendSysDefs();
+
+  /* wait till the end for the pictures */
+  if (!blk_metaserver)
+    doMotdPics();
+}
+
+int 
+reaper(sig)
+  int sig;
+{
+#ifndef SVR4
+  while (wait3((union wait *) 0, WNOHANG, (struct rusage *) 0) > 0);
+#else
+  while (waitpid(0, NULL, WNOHANG) > 0);
+#endif				/* SVR4 */
+  return 0;
+}
+
+void 
+printStats()
+{
+  FILE *logfile;
+#if defined(SVR4) || defined(sparc)
+  time_t curtime;
+#else
+  int curtime;
+#endif				/* SVR4 */
+  char *paths;			/* added 1/18/93 KAO */
+
+  paths = build_path(LOGFILENAME);
+  logfile = fopen(paths, "a");
+  if (!logfile)
+    return;
+  curtime = time(NULL);
+
+#ifdef LOG_LONG_INFO		/*-[  Long info printed to logfiles and startup.log ]-*/
+  fprintf(logfile, "Leaving: %-16s (%s) %3dP %3dA %3dW/%3dL %3dmin %drtt %dsdv %dls %dplan <%s@%s> %s",
+	  me->p_name,
+	  twoletters(me),
+	  me->p_stats.st_tplanets - startTplanets,
+	  me->p_stats.st_tarmsbomb - startTarms,
+	  me->p_stats.st_tkills - startTkills,
+	  me->p_stats.st_tlosses - startTlosses,
+	  (me->p_stats.st_tticks - startTticks) / 600,
+	  me->p_avrt, me->p_stdv, me->p_pkls,
+	  numPlanets(me->p_team),
+
+#else
+
+  fprintf(logfile, "Leaving: %s <%s@%s> %s",
+	  me->p_name,
+#endif
+	  me->p_login,
+	  me->p_full_hostname,
+	  ctime(&curtime));
+
+  /* #endif /*-[ LOG_LONG_INFO ]- */
+
+  if (goAway)
+    fprintf(logfile, "^^^ 2 players/1 slot.  was %s (%s)\n",
+	    start_name, start_login);
+  fclose(logfile);
+}
+
+
+/*
+ * .pics file format:
+ * 
+ * name x y page name x y page etc
+ */
+
+void
+doMotdPics()
+{
+  FILE *ptr, *ftemp;
+  char buf[128], fname[128];
+  unsigned char *bits;
+  char *result;
+  int x, y, page, w, h;
+  int bytesperline;		/* pad the width to a byte */
+  int linesperblock;		/* how many lines in 1016 bytes? */
+  int i;
+  char *paths;
+
+  paths = build_path(PICS);
+  ptr = fopen(paths, "r");
+  if (ptr == NULL)
+    return;
+  while (1)
+  {
+    result = fgets(fname, 125, ptr);
+    if (result == NULL)
+      /* must fclose ptr */
+      break;
+
+    if (fname[strlen(fname) - 1] == '\n')
+      fname[strlen(fname) - 1] = 0;
+
+    paths = build_path(fname);
+    ftemp = fopen(paths, "r");
+    bits = 0;
+    if (ftemp == 0)
+    {
+      fprintf(stderr, "ntserv: couldn't open file %s.  skipping\n", paths);
+    }
+    else
+    {
+      ParseXbmFile(ftemp, &w, &h, &bits);	/* parsexbm.c */
+
+      bytesperline = (w - 1) / 8 + 1;
+      linesperblock = 1016 /* packets.h */ / bytesperline;
+    }
+
+    fgets(buf, 125, ptr);
+
+    if (3 != sscanf(buf, "%d %d %d", &x, &y, &page))
+    {
+      printf("Format error in .pics file\n");
+      if (bits)
+	free(bits);
+      bits = NULL;
+    }
+
+    if (bits)
+    {
+      if (me != 0 && (me->p_stats.st_flags & ST_NOBITMAPS))
+      {
+	sendMotdNopic(x, y, page, w, h);
+      }
+      else
+	for (i = 0; i * linesperblock < h; i++)
+	{
+	  int nlines;
+	  if ((i + 1) * linesperblock > h)
+	    nlines = h - i * linesperblock;
+	  else
+	    nlines = linesperblock;
+#if 0
+	  printf("Sending MotdPics: %s %d %d %d %d %d\n",
+		 fname, x, y + i * linesperblock, page, w, nlines);
+#endif
+	  sendMotdPic(x, y + i * linesperblock,
+		      bits + bytesperline * linesperblock * i,
+		      page, w, nlines);
+	}
+      free(bits);
+    }
+  }
+  fclose(ptr);
+}
+
+
+#undef D
Binary file src/mes has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/message.c	Sat Dec 06 04:37:03 1997 +0000
@@ -0,0 +1,2513 @@
+/*--------------------------------------------------------------------------
+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
+--------------------------------------------------------------------------*/
+
+/* was control_mess.c, but changed to message.c for a smaller filename (BG) */
+
+/*
+ * Ugh, this code is in the middle of a rewrite.
+ * 
+ * It used to use a tokenizer with a global dictionary to split the input into
+ * words.  The tokenizer accepted abbreviations as long as these were unique.
+ * However, adding a new word to the dictionary would often cause old
+ * abbreviations to be invalidated.
+ * 
+ * I wrote a new parser that was called as each token needed to be extracted.
+ * This used a dictionary that was local to each submenu. This localizes
+ * changes to the menu structure so that effects of adding new commands are
+ * minimized.
+ * 
+ * Some of the file is converted to use this, but not all.  Eventually the
+ * entire module will use the context-sensitive tokenizer.
+ * 
+ */
+
+
+#include "config.h"
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+#include <ctype.h>
+#include <fcntl.h>
+
+#include "defs.h"
+#include "data.h"
+#include "struct.h"
+#include "shmem.h"
+
+enum token_names_e
+{
+  HELPTOK = 128,
+  CONTROLTOK,
+  VERSIONTOK,
+  QUEUETOK,
+  LEAGUETOK,
+  PARAMTOK,
+  INFOTOK,
+  OBSERVETOK,
+  CLUECHECKTOK,
+
+  NUKEGAMETOK,
+  FREESLOTTOK,
+  ROBOTTOK,
+  TOURNTOK,
+  NEWGALAXY,
+  SHIPTIMERTOK,
+
+  REFITTOK,
+  PLAYERTOK,
+  EJECTTOK,
+  DIETOK,
+  ARMIESTOK,
+  PLASMATOK,
+  MISSILETOK,
+  PLANETTOK,
+  RANKTOK,
+  MOVETOK,
+
+  PASSWDTOK,
+  RATINGSTOK,
+
+  TIMETOK,
+  CAPTAINTOK,
+  RESTARTTOK,
+  STARTTOK,
+  PASSTOK,
+  TIMEOUTTOK,
+  TEAMNAMETOK,
+  AWAYTOK,
+  HOMETOK,
+  PAUSETOK,
+  CONTINUETOK,
+  MAXPLAYERTOK,
+
+  TEAMTOK,
+
+  INDTOK,			/* these need to be adjacent and in order */
+  FEDTOK,			/* these need to be adjacent and in order */
+  ROMTOK,			/* these need to be adjacent and in order */
+  KLITOK,			/* these need to be adjacent and in order */
+  ORITOK,			/* these need to be adjacent and in order */
+
+  SHIPTOK,
+
+  SCOUTTOK,			/* these need to be adjacent and in order */
+  DESTROYERTOK,			/* these need to be adjacent and in order */
+  CRUISERTOK,			/* these need to be adjacent and in order */
+  BATTLESHIPTOK,		/* these need to be adjacent and in order */
+  ASSAULTTOK,			/* these need to be adjacent and in order */
+  STARBASETOK,			/* these need to be adjacent and in order */
+  ATTTOK,			/* these need to be adjacent and in order */
+  JUMPSHIPTOK,			/* these need to be adjacent and in order */
+  FRIGATETOK,			/* these need to be adjacent and in order */
+  WARBASETOK,			/* these need to be adjacent and in order */
+  LIGHTCRUISERTOK,
+  CARRIERTOK,
+  UTILITYTOK,
+  PATROLTOK,
+
+  PLUSTOK,
+  MINUSTOK,
+  ROYALTOK,
+  QUIETTOK,
+  KILLSTOK,
+  HOSETOK,
+  SUPERTOK,
+  ALLOWTOK,			/* control allow [teams] */
+
+  ERRORTOK = 255
+};
+
+#ifdef GOD_CONTROLS
+static int god_silent = 0;
+#endif
+
+/* static char *con_shipnos = "0123456789abcdefghijklmnopqrstuvwxyz"; */
+
+extern int pmessage2();
+extern int pmessage();
+#ifndef linux
+extern int atoi();
+#endif				/* linux */
+extern int detourneyqueue();
+extern void compute_ratings();
+
+static void respond();
+
+#if 0
+static enum token_names_e tokstring[128];	/* list of tokens */
+static char *thestrings[128];	/* list of corresponding strings */
+static char *therest[128];	/* list of pointers to the original text
+				 * starting with token i */
+static int sizetokstring;
+
+struct token
+{
+  char string[32];
+  int token;
+};
+
+
+
+struct token tstrings[] = {
+  {"0", 0}, {"1", 1}, {"2", 2}, {"3", 3},
+  {"4", 4}, {"5", 5}, {"6", 6}, {"7", 7},
+  {"8", 8}, {"9", 9}, {"a", 10}, {"b", 11},
+  {"c", 12}, {"d", 13}, {"e", 14}, {"f", 15},
+  {"g", 16}, {"h", 17}, {"i", 18}, {"j", 19},
+  {"k", 20}, {"l", 21}, {"m", 22}, {"n", 23},
+  {"o", 24}, {"p", 25}, {"q", 26}, {"r", 27},
+  {"s", 28}, {"t", 29}, {"u", 30}, {"v", 31},
+  {"w", 32}, {"x", 33}, {"y", 34}, {"z", 35},
+  {"help", HELPTOK},
+  {"control", CONTROLTOK},
+  {"con", CONTROLTOK},		/* popular abbrev */
+  {"version", VERSIONTOK},
+  {"tq", QUEUETOK},		/* popular abbrev */
+  {"queue", QUEUETOK},
+  {"league", LEAGUETOK},
+  {"params", PARAMTOK},
+  {"observe", OBSERVETOK},
+  {"info", INFOTOK},
+  {"cluecheck", CLUECHECKTOK},
+
+  {"shiptimers", SHIPTIMERTOK},
+
+  {"refit", REFITTOK},
+  {"player", PLAYERTOK},
+  {"pl", PLAYERTOK},		/* popular abbrev */
+  {"planet", PLANETTOK},
+  {"eject", EJECTTOK},
+  {"die", DIETOK},
+  {"rank", RANKTOK},
+  {"royalty", ROYALTOK},
+  {"move", MOVETOK},
+  {"armies", ARMIESTOK},
+  {"plasma", PLASMATOK},
+  {"missile", MISSILETOK},
+  {"team", TEAMTOK},
+  {"ship", SHIPTOK},
+  {"quiet", QUIETTOK},
+  {"kills", KILLSTOK},
+  {"hose", HOSETOK},
+  {"super", SUPERTOK},
+  {"allow", ALLOWTOK},
+  {"+", PLUSTOK},
+  {"-", MINUSTOK},
+
+  {"robot", ROBOTTOK},
+  {"nukegame", NUKEGAMETOK},
+  {"freeslot", FREESLOTTOK},
+  {"tourn", TOURNTOK},
+  {"galaxy", NEWGALAXY},
+
+  /* player commands */
+  {"password", PASSWDTOK},
+  {"ratings", RATINGSTOK},
+
+  /* league commands */
+  {"time", TIMETOK},
+  {"captain", CAPTAINTOK},
+  {"restart", RESTARTTOK},
+  {"start", STARTTOK},
+  {"pass", PASSTOK},
+  {"timeout", TIMEOUTTOK},
+  {"teamname", TEAMNAMETOK},
+  {"away", AWAYTOK},
+  {"home", HOMETOK},
+  {"pause", PAUSETOK},
+  {"continue", CONTINUETOK},
+  {"maxplayers", MAXPLAYERTOK},
+
+  {"independent", INDTOK},
+  {"federation", FEDTOK}, {"romulan", ROMTOK},
+  {"klingon", KLITOK}, {"orion", ORITOK},
+
+  {"sc", SCOUTTOK}, {"dd", DESTROYERTOK},
+  {"ca", CRUISERTOK}, {"bb", BATTLESHIPTOK},
+  {"as", ASSAULTTOK}, {"sb", STARBASETOK},
+  {"at", ATTTOK}, {"js", JUMPSHIPTOK},
+  {"fr", FRIGATETOK}, {"wb", WARBASETOK},
+  {"cl", LIGHTCRUISERTOK}, {"cv", CARRIERTOK},
+  {"ut", UTILITYTOK}, {"pt", PATROLTOK},
+
+  {"", ERRORTOK}		/* I'm last. Keep it that way. */
+};
+
+static void
+dotokenize(input)
+  char *input;
+{
+  char *temp0, *temp1;
+  int done = 0;
+  static char internal[120];
+
+  sizetokstring = 0;
+
+  /* Convert string to lowercase. */
+
+  temp0 = strcpy(internal, input);
+  while (*temp0 != '\0')
+  {
+    if (isupper(*temp0))
+      *temp0 = tolower(*temp0);
+    temp0++;
+  }
+
+
+  temp0 = internal;
+
+  while (done == 0)
+  {
+    struct token *tptr;
+    int wordlen;
+    int potentialtok, ambiguous;
+
+    /* Eat leading spaces. */
+
+    while (*temp0 == ' ')
+      temp0++;
+
+    /* Find the next word and chop the rest of the string away. */
+
+    temp1 = temp0;
+    therest[sizetokstring] = input + (temp1 - internal);
+    while (*temp1 != '\0' && *temp1 != ' ')
+      temp1++;
+    if (*temp1 != '\0')
+      *temp1++ = '\0';
+    wordlen = strlen(temp0);
+
+    /* Go find out what they've typed. */
+
+    tptr = tstrings;
+    potentialtok = ERRORTOK;
+    ambiguous = 0;
+    while (tptr->token != ERRORTOK)
+    {
+      if (0 == strncmp(temp0, tptr->string, wordlen))
+      {
+	if (strlen(tptr->string) == wordlen)
+	{
+	  ambiguous = 0;
+	  potentialtok = tptr->token;
+	  break;		/* exact match */
+	}
+	if (potentialtok != ERRORTOK)
+	{
+	  ambiguous = 1;	/* this isn't the only match */
+	}
+	potentialtok = tptr->token;
+      }
+      tptr++;
+    }
+
+    thestrings[sizetokstring] = temp0;
+    tokstring[sizetokstring++] = ambiguous ? ERRORTOK : potentialtok;
+    temp0 = temp1;
+
+    /* If *temp0 == 0 then we're done. */
+
+    if (*temp0 == '\0')
+      done = 1;
+  }
+  thestrings[sizetokstring] = 0;
+}
+#endif
+
+/**********************************************************************/
+
+/* New parsing method. */
+
+struct control_cmd
+{
+  char *literal;		/* the command they should type */
+  enum token_names_e tok;	/* what the parser should return */
+  char *doc;			/* documentation to print for a help command */
+};
+
+/*
+ * Scans the string cmd for the first whitespace delimited string. Tries to
+ * match this string in a case-insensitive manner against the list in legals.
+ * Returns the appropriate token.  Alters the char* pointed to by after to be
+ * the beginning of the next whitespace-delimited string.
+ * 
+ * cmd:	unmodified legals:	unmodified after:	MODIFIED
+ * 
+ */
+
+enum token_names_e
+next_token(cmd, legals, after)
+  char *cmd;
+  struct control_cmd *legals;
+  char **after;
+{
+  char buf[80];			/* space for the token */
+  char *s;
+  int i;
+  int ambiguous = 0;
+  enum token_names_e potentialtok = ERRORTOK;
+
+  while (*cmd && isspace(*cmd))
+    cmd++;
+
+  if (!*cmd)
+    return ERRORTOK;
+
+  for (s = buf; *cmd && !isspace(*cmd); s++, cmd++)
+    *s = *cmd;
+  *s = 0;
+
+  while (*cmd && isspace(*cmd))
+    cmd++;
+
+  if (after)
+    *after = cmd;		/* so they can find the next token */
+
+  for (i = 0; legals[i].literal; i++)
+  {
+    int wordlen = strlen(buf);
+    if (0 == strncasecmp(buf, legals[i].literal, wordlen))
+    {
+      if (strlen(legals[i].literal) == wordlen)
+      {
+	ambiguous = 0;
+	potentialtok = legals[i].tok;
+	break;			/* exact match */
+      }
+      if (potentialtok != ERRORTOK)
+      {
+	ambiguous = 1;		/* this isn't the only match */
+	return ERRORTOK;
+      }
+      potentialtok = legals[i].tok;
+    }
+  }
+
+  return potentialtok;
+}
+
+int
+match_token(cmd, token, after)
+  char *cmd;
+  char *token;
+  char **after;
+{
+  struct control_cmd legals[2];
+  legals[0].literal = token;
+  legals[0].tok = HELPTOK;	/* pick any token but ERRORTOK */
+  legals[1].literal = 0;
+  return HELPTOK == next_token(cmd, legals, after);
+}
+
+/*
+ * Get a player slot number. Returns -1 on failure, slot number on success.
+ * Slot number is guaranteed to be <MAXPLAYER.
+ */
+
+int 
+get_slotnum(cmd, after)
+  char *cmd;
+  char **after;
+{
+  int rval;
+  while (*cmd && isspace(*cmd))
+    cmd++;
+
+  if (!*cmd)
+    return -1;			/* no token */
+
+  if (cmd[1] && !isspace(cmd[1]))
+    return -1;			/* token too long */
+
+  if (*cmd >= '0' && *cmd <= '9')
+    rval = *cmd - '0';
+  else if (*cmd >= 'a' && *cmd <= 'z')
+    rval = *cmd - 'a' + 10;
+  else if (*cmd >= 'A' && *cmd <= 'Z')
+    rval = *cmd - 'A' + 10;
+  else
+    return -1;
+
+  if (rval >= MAXPLAYER)
+    return -1;			/* there aren't that many players */
+
+  if (after)
+  {
+    /* scan to next token */
+    cmd++;
+    while (*cmd && isspace(*cmd))
+      cmd++;
+    *after = cmd;
+  }
+
+  return rval;
+}
+
+void 
+bad_slotnum(msg)
+  char *msg;
+{
+  char buf[256];
+  sprintf(buf, "`%s' requires player slot number", msg);
+  respond(buf, 1);
+}
+
+
+/*
+ * Get a single token. Returns 0 on failure, 1 on success. Token is returned
+ * in dst.
+ */
+
+int 
+get_one_token(cmd, dst, dstsize, after)
+  char *cmd;
+  char *dst;			/* destination */
+  int dstsize;
+  char **after;
+{
+  while (*cmd && isspace(*cmd))
+    cmd++;
+
+  if (!*cmd)
+    return 0;			/* no token */
+
+  while (dstsize > 1 && *cmd && !isspace(*cmd))
+  {
+    *(dst++) = *(cmd++);
+    dstsize--;
+  }
+  *dst = 0;
+
+  if (after)
+  {
+    /* scan to next token */
+    while (*cmd && isspace(*cmd))
+      cmd++;
+    *after = cmd;
+  }
+
+  return 1;
+}
+
+/*
+ * Get an integer Integer is returned in dst. Returns 0 on failure without
+ * modifying dst.
+ */
+
+int 
+get_int(cmd, dst, after)
+  char *cmd;
+  int *dst;
+  char **after;
+{
+  int rval, offset;
+
+  if (1 != sscanf(cmd, " %i%n", &rval, &offset))
+    return 0;
+
+  cmd += offset;
+  if (*cmd && !isspace(*cmd))
+    return 0;			/* token wasn't all digits */
+
+  *dst = rval;
+
+  if (after)
+  {
+    /* scan to next token */
+    while (*cmd && isspace(*cmd))
+      cmd++;
+    *after = cmd;
+  }
+
+  return 1;
+}
+
+/*
+ * Get a double Double is returned in dst. Returns 0 on failure without
+ * modifying dst.
+ */
+
+int 
+get_double(cmd, dst, after)
+  char *cmd;
+  double *dst;
+  char **after;
+{
+  double rval;
+  int offset;
+
+  if (1 != sscanf(cmd, " %lg%n", &rval, &offset))
+    return 0;
+
+  cmd += offset;
+  if (*cmd && !isspace(*cmd))
+    return 0;			/* token wasn't all digits */
+
+  *dst = rval;
+
+  if (after)
+  {
+    /* scan to next token */
+    while (*cmd && isspace(*cmd))
+      cmd++;
+    *after = cmd;
+  }
+
+  return 1;
+}
+
+int 
+get_teamid(cmd, team, after)
+  char *cmd;
+  int *team;
+  char **after;
+{
+  int i, j;
+
+  while (*cmd && isspace(*cmd))
+  {
+    cmd++;
+  }
+  if (cmd[3] && !isspace(cmd[3]))
+    return 0;			/* too long */
+
+  *team = NOBODY;
+
+  for (i = -1; i < NUMTEAM; i++)
+  {
+    j = idx_to_mask(i);
+    if (0 == strncasecmp(cmd, teams[j].shortname, 3))
+    {
+      *team = i;
+      cmd += 3;
+      break;
+    }
+  }
+
+  if (after)
+  {
+    /* scan to next token */
+    while (*cmd && isspace(*cmd))
+      cmd++;
+    *after = cmd;
+  }
+
+  return i < NUMTEAM;
+}
+
+int 
+get_shipid(cmd, shipn, after)
+  char *cmd;
+  int *shipn;
+  char **after;
+{
+  int i;
+
+  while (*cmd && isspace(*cmd))
+  {
+    cmd++;
+  }
+  *shipn = -1;
+
+  for (i = 0; i < NUM_TYPES; i++)
+  {
+    struct ship *ship = &shipvals[i];
+    int len;
+    len = strlen(ship->s_name);
+    if (0 == strncasecmp(cmd, ship->s_name, len) &&
+	(cmd[len] == 0 || isspace(cmd[len])))
+    {
+      *shipn = i;
+      cmd += len;
+      break;
+    }
+    else if (tolower(cmd[0]) == tolower(ship->s_desig1) &&
+	     tolower(cmd[1]) == tolower(ship->s_desig2) &&
+	     (cmd[2] == 0 || isspace(cmd[2])))
+    {
+      *shipn = i;
+      cmd += 2;
+      break;
+    }
+  }
+
+  if (after)
+  {
+    /* scan to next token */
+    while (*cmd && isspace(*cmd))
+      cmd++;
+    *after = cmd;
+  }
+
+  return i < NUM_TYPES;
+}
+
+/* writes a comma-separated list of help strings into the message window */
+
+void
+respond_with_help_string(legals)
+  struct control_cmd *legals;
+{
+  int i;
+  char buf[65];			/* leave space for the message prefix */
+
+  strcpy(buf, "Available commands: ");
+  for (i = 0; legals[i].literal; i++)
+  {
+    if (!(legals[i].doc && legals[i].doc[0]))
+      continue;
+    if (strlen(buf) + 3 + strlen(legals[i].doc) > sizeof(buf))
+    {
+      respond(buf, 0);
+      strcpy(buf, "    ");
+      if (!buf[0])
+      {				/* one of the help strings was just too long */
+	respond("ACK! programmer error: help string too long", 0);
+	return;
+      }
+      i--;			/* retry */
+      continue;
+    }
+    strcat(buf, legals[i].doc);
+    if (legals[i + 1].literal)
+      strcat(buf, ", ");
+  }
+  if (buf[0])
+    respond(buf, 0);
+}
+
+/**********************************************************************/
+
+static void
+respond(msg, type)
+  char *msg;
+  int type;
+{
+  if (type == 1)
+    warning(msg);
+  else
+    pmessage2(msg, me->p_no, MINDIV, MCONTROL, 255);
+}
+
+#ifdef GOD_CONTROLS
+
+/*
+ * Here we handle the controls on players. If you add something, make sure
+ * you place it in the help. Thanks, have a nice day.
+ */
+
+static int
+parse_control_player(cmd)
+  char *cmd;
+{
+  char buf[120];
+  int pnum;
+  struct player *victim;
+  int godliness = me->p_stats.st_royal - GODLIKE + 1;
+  char *arg;
+  static struct control_cmd available_cmds[] = {
+    {"help", HELPTOK, 0},
+    {"die", DIETOK, "die"},
+    {"eject", EJECTTOK, "eject"},
+    {"armies", ARMIESTOK, "armies [%d=5]"},
+    {"plasma", PLASMATOK, "plasma [%d]"},
+    {"missiles", MISSILETOK, "missiles [%d=max]"},
+    {"team", TEAMTOK, "team <teamstr>"},
+    {"ship", SHIPTOK, "ship <shiptype>"},
+    {"rank", RANKTOK, "rank (+|-|%d)"},
+    {"royal", ROYALTOK, "royal (+|-|%d)"},
+    {"kills", KILLSTOK, "kills (+|-|%d)"},
+    {"hose", HOSETOK, "hose"},
+    {"move", MOVETOK, "move %d %d"},
+    {0}
+  };
+
+  pnum = get_slotnum(cmd, &cmd);
+  if (pnum < 0)
+  {
+    bad_slotnum("control player");
+    return 0;
+  }
+  victim = &players[pnum];
+
+  if (victim->p_status == PFREE)
+  {
+    respond("Slot is not alive.", 1);
+    return 1;
+  }
+
+  /*
+   * These would probably work better as pointers to functions instead of a
+   * giant switch, but what the hell, I'm lazy. Maybe I'll change it later.
+   */
+
+  switch (next_token(cmd, available_cmds, &arg))
+  {
+   case DIETOK:
+    victim->p_ship.s_type = STARBASE;
+    victim->p_whydead = KPROVIDENCE;
+    victim->p_explode = 10;
+    victim->p_status = PEXPLODE;
+    victim->p_whodead = 0;
+    if (!god_silent)
+    {
+      sprintf(buf, "%s (%2s) was utterly obliterated by %s (%2s).",
+	      victim->p_name, twoletters(victim),
+	      me->p_name, twoletters(me));
+      pmessage(buf, 0, MALL, MCONTROL);
+    }
+    return 1;
+
+   case EJECTTOK:
+    victim->p_ship.s_type = STARBASE;
+    victim->p_whydead = KQUIT;
+    victim->p_explode = 10;
+    victim->p_status = PEXPLODE;
+    victim->p_whodead = 0;
+    if (!god_silent)
+    {
+      sprintf(buf,
+	      "%s (%2s) has been ejected from the game by %s (%2s).",
+	      victim->p_name, twoletters(victim),
+	      me->p_name, twoletters(me));
+      pmessage(buf, 0, MALL, MCONTROL);
+    }
+    return 1;
+
+   case ARMIESTOK:
+    {
+      int armies = 5;
+      if (*arg && !get_int(arg, &armies, (char **) 0))
+      {
+	respond("optional arg to `control player <slotnum> armies` must be integer", 0);
+	return 0;
+      }
+      victim->p_armies += armies;
+      if (!god_silent)
+      {
+	sprintf(buf, "%s (%2s) has been given %d armies by %s (%2s).",
+		victim->p_name, twoletters(victim), armies,
+		me->p_name, twoletters(me));
+	pmessage(buf, 0, MALL, MCONTROL);
+      }
+      return 1;
+    }
+
+   case PLASMATOK:
+    {
+      int yes = 1;
+      if (*arg && !get_int(arg, &yes, (char **) 0))
+      {
+	respond("optional arg to `control player <slotnum> plasma` must be integer", 0);
+	return 0;
+      }
+
+      if (yes)
+	victim->p_ship.s_nflags |= SFNPLASMAARMED;
+      else
+	victim->p_ship.s_nflags &= ~SFNPLASMAARMED;
+
+      if (!god_silent)
+      {
+	sprintf(buf, "%s (%2s) has been %s plasma torps by %s (%2s).",
+		victim->p_name, twoletters(victim),
+		yes ? "given" : "denied",
+		me->p_name, twoletters(me));
+	pmessage(buf, 0, MALL, MCONTROL);
+      }
+      return 1;
+    }
+
+   case MISSILETOK:
+    {
+      int yes = shipvals[victim->p_ship.s_type].s_missilestored;
+
+      if (*arg && !get_int(arg, &yes, (char **) 0))
+      {
+	respond("optional arg to `control player <slotnum> missile` must be integer", 0);
+	return 0;
+      }
+
+      if (yes)
+      {
+	victim->p_ship.s_nflags |= SFNHASMISSILE;
+	victim->p_ship.s_missilestored = yes;
+      }
+      else
+      {
+	victim->p_ship.s_nflags &= ~SFNHASMISSILE;
+      }
+
+      if (!god_silent)
+      {
+	sprintf(buf, "%s (%2s) has been %s %d missiles by %s (%2s).",
+		victim->p_name, twoletters(victim),
+		yes ? "given" : "denied",
+		yes, me->p_name, twoletters(me));
+	pmessage(buf, 0, MALL, MCONTROL);
+      }
+      return 1;
+    }
+
+   case TEAMTOK:
+    {
+      int team;
+
+      if (!get_teamid(arg, &team, (char **) 0))
+      {
+	respond("available teams: FED ORI ROM KLI IND", 0);
+	return 0;
+      }
+      team = idx_to_mask(team);
+
+      victim->p_hostile |= victim->p_team;
+      victim->p_team = team;
+      victim->p_hostile &= ~team;
+      victim->p_swar &= ~team;
+      sprintf(buf, "%s (%2s) has been changed to a %s by %s (%2s).",
+	      victim->p_name, twoletters(victim), teams[team].nickname,
+	      me->p_name, twoletters(me));
+      if (!god_silent)
+	pmessage(buf, 0, MALL, MCONTROL);
+      return 1;
+    }
+
+   case SHIPTOK:
+    {
+      int ship;
+      if (!get_shipid(arg, &ship, (char **) 0))
+      {
+	respond("available ships: SC DD CA AS BB SB AT JS FR WB CL CV SUPER", 0);
+	return 0;
+      }
+#if 0
+      if (tokstring[4] == SUPERTOK)
+      {
+	victim->p_ship.s_maxshield = 750;
+	victim->p_shield = 750;
+	victim->p_ship.s_maxdamage = 750;
+	victim->p_ship.s_maxegntemp = 5000;
+	sprintf(buf, "%s (%2s) has been supercharged by %s (%2s).",
+		victim->p_name, twoletters(victim),
+		me->p_name, twoletters(me));
+	if (!god_silent)
+	  pmessage(buf, 0, MALL, MCONTROL);
+	return 1;
+      }
+#endif
+      /* If others are docked, then kick them off */
+      if (allows_docking(victim->p_ship))
+      {
+	int i;
+	for (i = 0; i < victim->p_ship.s_numports; i++)
+	{
+	  base_undock(victim, i);
+	}
+      }
+      get_ship_for_player(victim, ship);
+      switch_special_weapon();
+      victim->p_flags &= ~PFENG;
+      sprintf(buf, "%s (%2s) has been changed to a %c%c by %s (%2s).",
+	      victim->p_name, twoletters(victim),
+	      victim->p_ship.s_desig1, victim->p_ship.s_desig2,
+	      me->p_name, twoletters(me));
+      if (!god_silent)
+	pmessage(buf, 0, MALL, MCONTROL);
+      return 1;
+    }
+
+   case RANKTOK:
+    {
+      int rank = victim->p_stats.st_rank;
+
+      if (match_token(arg, "+", (char **) 0))
+	rank++;
+      else if (match_token(arg, "-", (char **) 0))
+	rank--;
+      else if (!get_int(arg, &rank, (char **) 0))
+      {
+	respond("Try: control player %d rank [%d]+-", 0);
+	return 0;
+      }
+
+      if (rank < 0)
+	rank = 0;
+      if (rank >= NUMRANKS)
+	rank = NUMRANKS - 1;
+
+      victim->p_stats.st_rank = rank;
+      sprintf(buf, "%s (%2s) has been given a rank of %s by %s (%2s).",
+	      victim->p_name, twoletters(victim),
+	      ranks[victim->p_stats.st_rank].name,
+	      me->p_name, twoletters(me));
+      if (!god_silent)
+	pmessage(buf, 0, MALL, MCONTROL);
+      return 1;
+    }
+
+   case ROYALTOK:
+    {
+      int rank = victim->p_stats.st_royal;
+
+      if (match_token(arg, "+", (char **) 0))
+	rank++;
+      else if (match_token(arg, "-", (char **) 0))
+	rank--;
+      else if (!get_int(arg, &rank, (char **) 0))
+      {
+	respond("Try: control player %d royal [%d]+-", 0);
+	return 0;
+      }
+
+      if (rank < 0)
+	rank = 0;
+      if (rank >= NUMROYALRANKS)
+	rank = NUMROYALRANKS - 1;
+
+      if (rank >= GODLIKE && godliness < 2)
+      {
+	respond("You aren't powerful enough to grant godlike royalty.",
+		1);
+	return 1;
+      }
+      victim->p_stats.st_royal = rank;
+      sprintf(buf, "%s (%2s) has been given a rank of %s by %s (%2s).",
+	      victim->p_name, twoletters(victim),
+	      royal[victim->p_stats.st_royal].name,
+	      me->p_name, twoletters(me));
+      if (!god_silent)
+	pmessage(buf, 0, MALL, MCONTROL);
+      return 1;
+    }
+
+   case KILLSTOK:
+    {
+      double kills = victim->p_kills;
+
+      if (match_token(arg, "+", (char **) 0))
+	kills += 1;
+      else if (match_token(arg, "-", (char **) 0))
+      {
+	kills -= 1;
+	if (kills < 0)
+	  kills = 0;
+      }
+      else if (!get_double(arg, &kills, (char **) 0))
+      {
+	respond("Try: control player %d kills [%f]+-", 0);
+	return 0;
+      }
+
+      victim->p_kills = kills;
+      sprintf(buf, "%s (%2s) has been given %f kills by %s (%2s).",
+	      victim->p_name, twoletters(victim),
+	      kills, me->p_name, twoletters(me));
+      if (!god_silent)
+	pmessage(buf, 0, MALL, MCONTROL);
+      return 1;
+    }
+
+   case HOSETOK:
+    victim->p_shield = 0;
+    victim->p_damage = victim->p_ship.s_maxdamage / 2;
+    sprintf(buf, "%s (%2s) has been hosed by %s (%2s).",
+	    victim->p_name, twoletters(victim),
+	    me->p_name, twoletters(me));
+    if (!god_silent)
+      pmessage(buf, 0, MALL, MCONTROL);
+    return 1;
+
+   case MOVETOK:
+    {
+      int x, y;
+      char *s;
+      if (!(get_int(arg, &x, &s) && get_int(s, &y, (char **) 0)))
+      {
+	respond("Try: control player %d move %d %d", 0);
+	return 0;
+      }
+
+      if (x <= 0 || y <= 0 || x >= 200000 || y >= 200000)
+      {
+	respond("You want to move him where?", 0);
+	return 0;
+      }
+      victim->p_x = x;
+      victim->p_y = y;
+      sprintf(buf, "%s (%2s) has been moved to %d %d by %s (%2s).",
+	      victim->p_name, twoletters(victim),
+	      x, y,
+	      me->p_name, twoletters(me));
+      if (!god_silent)
+	pmessage(buf, 0, MALL, MCONTROL);
+      return 1;
+    }
+
+   case HELPTOK:		/* fall through */
+   default:
+#if 1
+    respond_with_help_string(available_cmds);
+#else
+    respond("player controls: die, eject, armies [%d], plasma [%d],", 0);
+    respond("player controls: missile [%d], team [team], ship [ship],", 0);
+    respond("player controls: rank [%d]+-, royal [%d]+-, kills [%d]+-", 0);
+    respond("player controls: hose, move %d %d", 0);
+#endif
+    return 0;
+  }
+}
+
+static int
+parse_control(str)
+  char *str;
+{
+  char buf[120];
+  struct player *victim;
+  int i;
+  int godliness = me->p_stats.st_royal - GODLIKE + 1;
+
+  static struct control_cmd available_cmds[] = {
+    {"help", HELPTOK, 0},
+    {"freeslot", FREESLOTTOK, "freeslot %p"},
+    {"player", PLAYERTOK, "player ..."},
+    {"robot", ROBOTTOK, "robot [args]"},
+    {"quiet", QUIETTOK, "quiet"},
+    {"nukegame", NUKEGAMETOK, "nukegame"},
+    {"restart", RESTARTTOK, "restart"},
+    {"galaxy", NEWGALAXY, "galaxy"},
+    {"shiptimer", SHIPTIMERTOK, "shiptimer (teamstr|shipstr)*"},
+    {"allow", ALLOWTOK, "allow [teams]"},
+    {0}
+  };
+  char *nexttoken;
+
+  if (godliness <= 0)
+  {
+#if 0
+    respond("Those commands are only available to server gods");
+#endif
+    return 0;			/* "fail" silently.  Don't advertise divine
+				 * powers to peasants. */
+  }
+
+
+  switch (next_token(str, available_cmds, &nexttoken))
+  {
+   case FREESLOTTOK:
+    {
+      int slot = get_slotnum(nexttoken, (char **) 0);
+      if (slot < 0)
+      {
+	respond("\"control freeslot\" requires slot number.", 0);
+	return 1;
+      }
+      victim = &players[slot];
+      if (victim->p_ntspid)
+	kill(victim->p_ntspid, SIGHUP);
+
+      victim->p_status = PFREE;
+      victim->p_ntspid = 0;
+
+      if (!god_silent)
+      {
+	sprintf(buf, "Player slot %s has been freed by %s (%2s).",
+		nexttoken, me->p_name, twoletters(me));
+	pmessage(buf, 0, MALL, MCONTROL);
+      }
+    }
+    return 1;
+
+   case ALLOWTOK:
+    {
+      int newlock = 0;
+      int team;
+      char *s;
+      if (0 == *nexttoken)
+      {
+	newlock = ALLTEAM;
+      }
+      else
+      {
+	for (s = nexttoken; get_teamid(s, &team, &s);)
+	{
+	  newlock |= idx_to_mask(team);
+	}
+	if (*s)
+	{
+	  respond("Usage: control allow [fed] [rom] [kli] [ori]", 0);
+	  return 1;
+	}
+      }
+
+      status2->nontteamlock = newlock;
+      strcpy(buf, "Allowed teams now set to:");
+      if (status2->nontteamlock == ALLTEAM)
+      {
+	strcat(buf, " <all teams>");
+      }
+      else
+      {
+	if (status2->nontteamlock & FED)
+	  strcat(buf, " fed");
+	if (status2->nontteamlock & ROM)
+	  strcat(buf, " rom");
+	if (status2->nontteamlock & KLI)
+	  strcat(buf, " kli");
+	if (status2->nontteamlock & ORI)
+	  strcat(buf, " ori");
+      }
+      respond(buf, 0);
+    }
+    return 1;
+   case PLAYERTOK:
+    return parse_control_player(nexttoken);
+
+   case ROBOTTOK:
+    {
+      int pid;
+      char *s;
+
+      pid = fork();
+      if (pid == 0)
+      {
+	char *argv[40];
+	argv[0] = build_path(ROBOT);
+
+	s = nexttoken;
+	for (i = 1; 1; i++)
+	{
+	  int size = 80;
+	  argv[i] = malloc(size);
+	  if (!get_one_token(s, argv[i], size, &s))
+	    break;
+	  realloc(argv[i], strlen(argv[i]) + 1);
+	}
+	free(argv[i]);
+	argv[i] = 0;
+
+	execvp(argv[0], argv);
+	fprintf(stderr, "Ack! Unable to exec %s\n", argv[0]);
+	exit(1);
+      }
+      else if (pid < 0)
+      {
+	respond("Unable to fork robot", 0);
+      }
+      else
+      {
+	sprintf(buf, "Robot forked (pid %d) with arguments %s",
+		pid, nexttoken);
+	respond(buf, 1);
+      }
+    }
+    return 1;
+
+   case QUIETTOK:
+    if (godliness < 2)
+    {
+      respond("No sneaking allowed", 0);
+      return 1;
+    }
+    sprintf(buf, "Switching to %s mode.", god_silent ? "loud" : "quiet");
+    respond(buf, 0);
+    god_silent = !god_silent;
+    return 1;
+   case NUKEGAMETOK:
+    warning("Nuking game.  Have a nice day.");
+    if (!god_silent)
+    {
+      sprintf(buf, "The game has been nuked by %s (%2s).",
+	      me->p_name, twoletters(me));
+      pmessage(buf, 0, MALL, MCONTROL);
+    }
+    kill(status->nukegame, 15);
+    return 1;
+   case RESTARTTOK:
+    warning("Attempting daemon restart.");
+    startdaemon(
+#ifdef LEAGUE_SUPPORT
+		status2->league
+#else
+		0
+#endif
+		,1);
+    return 1;
+   case NEWGALAXY:
+    explode_everyone(KPROVIDENCE, 0);
+    if (!god_silent)
+    {
+      sprintf(buf, "The galaxy has been reset by %s (%2s).",
+	      me->p_name, twoletters(me));
+      pmessage(buf, 0, MALL, MCONTROL);
+    }
+    status2->newgalaxy = 1;
+    warning("Creating new galaxy");
+    return 1;
+   case SHIPTIMERTOK:
+    {
+      int teammask = 0;
+      int shipmask = 0;
+      int i, j;
+      char *s = nexttoken;
+      while (1)
+      {
+	if (get_shipid(s, &j, &s))
+	  shipmask |= 1 << j;
+	else if (get_teamid(s, &j, &s))
+	  teammask |= idx_to_mask(j);
+	else if (*s)
+	{
+	  respond("Usage:", 0);
+	  respond("control shiptimers (fed|rom|kli|ori)* (sc|dd|ca|bb|as|sb|at|js|fr|wb)*", 0);
+	  respond("  resets the ship timers.", 0);
+	  return 0;
+	}
+	else
+	  break;
+      }
+      for (i = 0; i < NUMTEAM; i++)
+      {
+	int teammask = idx_to_mask(i);
+	if (teammask && !(teammask & (1 << i)))
+	  continue;
+
+	for (j = 0; j < NUM_TYPES; j++)
+	{
+	  if (shipmask && !(shipmask & (1 << j)))
+	    continue;
+
+	  if (teams[teammask].s_turns[j])
+	  {
+	    sprintf(buf, "%s %s reset", teams[teammask].name, shipvals[j].s_name);
+	    respond(buf, 0);
+	    teams[teammask].s_turns[j] = 0;
+	  }
+	}
+      }
+    }
+    return 1;
+   case HELPTOK:		/* fall through */
+   default:
+#if 1
+    respond_with_help_string(available_cmds);
+#else
+    respond("Available controls: player, quiet, nukegame, freeslot,", 0);
+    respond("  galaxy, restart, shiptimer", 0);
+#endif
+    return 0;
+  }
+}
+#endif
+
+/*
+ */
+
+static int
+parse_info(cmd)
+  char *cmd;
+{
+  char buf[120];
+  char *nexttoken;
+
+  static struct control_cmd available_cmds[] = {
+    {"help", HELPTOK, 0},
+    {"shiptimer", SHIPTIMERTOK, "shiptimer (teamstr|shipstr)*"},
+    {0}
+  };
+
+  switch (next_token(cmd, available_cmds, &nexttoken))
+  {
+   case SHIPTIMERTOK:
+    {
+      int race = 0;
+      int i, j;
+      int anydead = 0;
+#if 0
+      if (me->p_stats.st_royal < 2)
+	race = me->p_team;
+#endif
+      for (i = 0; i < NUMTEAM; i++)
+      {
+	int teammask = idx_to_mask(i);
+	if (race && !(race & (1 << i)))
+	  continue;
+	for (j = 0; j < NUM_TYPES; j++)
+	{
+	  if (teams[teammask].s_turns[j])
+	  {
+	    sprintf(buf, "%s %s: %d minutes", teams[teammask].name,
+		    shipvals[j].s_name, teams[teammask].s_turns[j]);
+	    anydead = 1;
+	    respond(buf, 0);
+	  }
+	}
+      }
+      if (!anydead)
+	respond("All ships are available", 0);
+    }
+    return 1;
+   case HELPTOK:
+   default:
+    respond("Available subcommands: shiptimer", 0);
+    return 1;
+  }
+}
+
+#define crypt(a, b) (a)
+
+static int
+parse_player(cmd)
+  char *cmd;
+{
+  static int passver = 0;
+  char buf[80];
+#if 0
+  static char newpass[16];
+#endif
+  char *nexttoken;
+
+  static struct control_cmd available_cmds[] = {
+    {"help", HELPTOK, 0},
+    {"password", PASSWDTOK, "password %s"},
+    {"passwd", PASSWDTOK, 0},
+    {"ratings", RATINGSTOK, "ratings"},
+    {"rank", RANKTOK, "rank"},
+    {0}
+  };
+
+  if (0 == *cmd)
+  {
+    if (passver)
+      respond("Password change cancelled.", 0);
+
+    passver = 0;
+    return 1;
+  }
+
+  switch (next_token(cmd, available_cmds, &nexttoken))
+  {
+   case PASSWDTOK:
+    {
+      static char newpass[16];
+      if (me->p_pos < 0)
+      {				/* guest login */
+	respond("You don't have a password!", 0);
+      }
+      else if (*nexttoken == 0)
+      {
+	respond("\"player password\" requires new password as argument.", 0);
+	respond("  example: \"player password lh4ern\"", 0);
+      }
+      else if (!passver)
+      {
+	strcpy(newpass, crypt(nexttoken, me->p_name));
+	respond("Repeat \"player password\" command to verify new password.", 0);
+	respond(" or send \"player\" (no arguments) to cancel.", 0);
+	passver = 1;
+      }
+      else
+      {
+	char *paths;
+	int fd;
+	if (!strcmp(newpass, crypt(nexttoken, me->p_name)))
+	{
+
+	  /* perhaps it'd be better to put this part in */
+	  /* a different place */
+	  paths = build_path(PLAYERFILE);
+	  fd = open(paths, O_WRONLY, 0644);
+	  if (fd >= 0)
+	  {
+	    lseek(fd, 16 + me->p_pos * sizeof(struct statentry), 0);
+	    write(fd, newpass, 16);
+	    close(fd);
+	    respond("Password changed.", 0);
+	  }
+	  else
+	  {
+	    respond("open() of playerfile failed, password not changed.", 0);
+	  }
+	}
+	else
+	  respond("Passwords did not match, password unchanged.", 0);
+	passver = 0;
+      }
+    }
+    return 1;
+   case RATINGSTOK:		/* print your ratings */
+    {
+      struct rating r;
+      compute_ratings(me, &r);
+
+      sprintf(buf, "Bomb:%5.2f   Plnts:%5.2f   Rsrcs:%5.2f    Dshs:%5.2f   Offns:%5.2f", r.bombrat, r.planetrat, r.resrat, r.dooshrat, r.offrat);
+      respond(buf, 0);
+
+      sprintf(buf, "  JS:%5.2f      SB:%5.2f      WB:%5.2f   Ratio:%5.2f", r.jsrat, r.sbrat, r.wbrat, r.ratio);
+      respond(buf, 0);
+
+      sprintf(buf, "Overall Ratings:  Battle:%5.2f   Strat:%5.2f   Spec. Ship:%5.2f", r.battle, r.strategy, r.special);
+      respond(buf, 0);
+    }
+    return 1;
+
+   case RANKTOK:		/* print the requirements for the next rank */
+    {
+      int rank;
+      rank = me->p_stats.st_rank;
+      strcpy(buf, "Your current rank is ");
+      strcat(buf, ranks[rank].name);
+      respond(buf, 0);
+      if (rank == NUMRANKS - 1)
+	return 1;
+
+      sprintf(buf, "To make the next rank (%s) you need:",
+	      ranks[rank + 1].name);
+      respond(buf, 0);
+
+      sprintf(buf, "    Genocides: %d   DI: %.2f   Battle: %.2f",
+	      ranks[rank + 1].genocides, ranks[rank + 1].di,
+	      ranks[rank + 1].battle);
+      respond(buf, 0);
+
+      sprintf(buf, "    Strategy: %.2f   Spec. Ships: %.2f",
+	      ranks[rank + 1].strategy, ranks[rank + 1].specship);
+      respond(buf, 0);
+    }
+    return 1;
+
+   case HELPTOK:
+   default:
+    respond_with_help_string(available_cmds);
+    return 1;
+  }
+}
+
+/*
+ */
+
+#ifdef LEAGUE_SUPPORT
+
+static void
+umpire_speak(msg)
+  char *msg;
+{
+  pmessage(msg, -1, MALL, UMPIRE);
+}
+
+static void
+talk_about_team(team, type)
+  struct league_team *team;
+  char *type;
+{
+  char buf[120];
+  struct player *captain;
+
+  if (team->captain >= 0)
+    captain = &players[team->captain];
+  else
+    captain = 0;
+
+  sprintf(buf, "The %s team is named `%s'.", type, team->name);
+  respond(buf, 0);
+
+  if (captain)
+    sprintf(buf, "  %s (%s) is their captain.", captain->p_name,
+	    twoletters(captain));
+  else
+    strcpy(buf, "  They have not chosen a captain yet.");
+  respond(buf, 0);
+
+  if (team->index >= 0)
+  {
+    sprintf(buf, "  They have chosen the %s",
+	    teams[idx_to_mask(team->index)].name);
+  }
+  else
+  {
+    strcpy(buf, "  They have not chosen an empire yet.");
+  }
+  respond(buf, 0);
+}
+
+static int
+team_really_ready(team)
+  struct league_team *team;
+{
+  if (team->index < 0)
+  {
+    respond("You haven't chosen an empire", 1);
+    return 0;
+  }
+  if (team->name[0] == 0)
+  {
+    respond("You haven't chosen a name", 1);
+    return 0;
+  }
+  return 1;
+}
+
+void
+trydefect(victim, dest, destname, from, fromname, actor)
+  struct player *victim;
+  enum HomeAway dest;
+  char *destname;
+  enum HomeAway from;
+  char *fromname;
+  struct player *actor;
+{
+  char buf[120];
+  struct league_team *fromteam =
+  (from == AWAY) ? &status2->away : &status2->home;
+
+  if (victim->p_status == PFREE)
+  {
+    respond("Uh, he's not in the game.", 1);
+    return;
+  }
+
+  if (victim->p_homeaway == dest)
+  {
+    sprintf(buf, "%s already belong to the %s team",
+	    actor == victim ? "You" : "They", destname);
+    respond(buf, 1);
+    return;
+  }
+  if (actor->p_homeaway != from)
+  {
+    sprintf(buf, "You don't belong to the %s team.  You can't kick him off.",
+	    fromname);
+    respond(buf, 1);
+    return;
+  }
+  if (fromteam->captain == actor->p_no)
+  {
+    if (victim == actor)
+    {
+      if (status2->league > 1 || status2->home.ready || status2->away.ready)
+      {
+	respond("You can't defect in the middle of the game.  You're the captain!", 1);
+	return;
+      }
+      sprintf(buf, "%s (%s), the captain of the %s team, has defected!",
+	      victim->p_name, twoletters(victim), fromname);
+      umpire_speak(buf);
+    }
+    else
+    {
+      sprintf(buf, "%s (%s) has kicked %s (%s) off his team.",
+	      actor->p_name, twoletters(actor),
+	      victim->p_name, twoletters(victim));
+      umpire_speak(buf);
+    }
+  }
+  else
+  {
+    if (victim == actor)
+    {
+      if (status2->league > 1 || status2->home.ready || status2->away.ready)
+      {
+	respond("Only the captain can kick you off now.", 1);
+	return;
+      }
+      sprintf(buf, "%s (%s) has defected to the %s team!",
+	      victim->p_name, twoletters(victim),
+	      destname);
+      umpire_speak(buf);
+    }
+    else
+    {
+      respond("Only the captain can kick other people off the team.", 1);
+      return;
+    }
+  }
+  victim->p_homeaway = dest;
+  victim->p_status = PEXPLODE;
+  victim->p_whydead = KPROVIDENCE;
+  victim->p_explode = 1;
+}
+
+static int
+parse_league(subcommand)
+  char *subcommand;
+{
+  struct league_team *myteam, *otherteam;
+  char *teamtype;
+  char buf[120];
+  int i;
+  int iscaptain;
+  char *nexttoken;
+  static char captain_only[] = "That command is reserved for team captains.";
+  static struct control_cmd available_cmds[] = {
+    {"help", HELPTOK, 0},
+    {"captain", CAPTAINTOK, "captain [%d]"},
+    {"time", TIMETOK, "time [%d %d]"},
+    {"pass", PASSTOK, "pass"},
+    {"start", STARTTOK, "start [%d]"},
+    {"restart", RESTARTTOK, "restart [%d]"},
+#if 0
+    {"timeout", TIMEOUTTOK, "timeout [%d]"},
+#endif
+    {"teamname", TEAMNAMETOK, "teamname %s"},
+    {"information", INFOTOK, "information"},
+#if 0
+    /* damn, these should be initialized from the current race list */
+    {"federation", FEDTOK, "fed"},
+    {"romulan", ROMTOK, "rom"},
+    {"klingon", KLITOK, "kli"},
+    {"orion", ORITOK, "ori"},
+#endif
+
+    {"away", AWAYTOK, "away [%d]"},
+    {"home", HOMETOK, "home [%d]"},
+    {"newgalaxy", NEWGALAXY, "newgalaxy [%d]"},
+    {"pause", PAUSETOK, "pause"},
+    {"continue", CONTINUETOK, "continue"},
+    {"maxplayer", MAXPLAYERTOK, "maxplayer [%d]"},
+    {"freeslot", FREESLOTTOK, "freeslot %d"},
+    {0}
+  };
+
+  switch (me->p_homeaway)
+  {
+   case HOME:
+    myteam = &status2->home;
+    otherteam = &status2->away;
+    teamtype = "home";
+    break;
+   case AWAY:
+    myteam = &status2->away;
+    otherteam = &status2->home;
+    teamtype = "away";
+    break;
+   default:
+    respond("WHOA! internal error.  You aren't on a team!", 0);
+    respond("I'm afraid I'm going to have to kill you", 0);
+    me->p_status = PEXPLODE;
+    me->p_explode = 1;
+    return 0;
+  }
+
+  iscaptain = (myteam->captain == me->p_no);
+
+  /********************/
+
+  if (get_teamid(subcommand, &i, (char **) 0))
+  {
+    if (!iscaptain)
+    {
+      respond(captain_only, 1);
+      return 1;
+    }
+    if (status2->league != 1)
+    {
+      respond("The game has started.  You can't change your mind now.", 1);
+      return 1;
+    }
+    if ((myteam->ready || otherteam->ready) && myteam->index >= 0)
+    {
+      respond("One of the teams is ready.  You can't change your mind now.", 1);
+      return 1;
+    }
+    if (otherteam->index >= 0)
+    {
+      if (i == otherteam->index)
+      {
+	respond("The other team has already chosen that empire", 1);
+	return 1;
+      }
+    }
+    else
+    {
+      if (me->p_homeaway == HOME)
+      {
+	if (!status2->awaypassed)
+	{
+	  respond("Away team gets first choice of empire.", 1);
+	  return 1;
+	}
+      }
+      else /* away */ if (myteam->index >= 0 && 0 == status2->awaypassed)
+      {
+	respond("Give the other team a chance to choose a side, will ya?", 1);
+	return 1;
+      }
+      else if (status2->awaypassed == 1)
+      {
+	respond("You passed the choice of empire.  You have to wait for their choice.", 1);
+	return 1;
+      }
+    }
+
+    if (i == myteam->index)
+    {
+      respond("That already IS your empire.", 1);
+      return 1;
+    }
+    if (i < 0)
+    {
+#if 0
+      sprintf(buf, "The %s team no longer wishes the %s for their empire.",
+	      teamtype, teams[idx_to_mask(myteam->index)].name);
+#else
+      respond("You can't change your mind without a reset.  Ask for one", 1);
+      return 1;
+#endif
+    }
+    else
+      sprintf(buf, "The %s team has chosen the %s for their empire.",
+	      teamtype, teams[idx_to_mask(i)].name);
+    umpire_speak(buf);
+
+    myteam->index = i;
+
+    return 1;
+  }
+  else
+    switch (next_token(subcommand, available_cmds, &nexttoken))
+    {
+     default:
+     case HELPTOK:		/********************/
+      if (iscaptain)
+      {
+	respond_with_help_string(available_cmds);
+      }
+      else
+      {
+	respond("Available commands: captain [ %d ], time, information, maxplayer.", 0);
+      }
+      return 1;
+
+     case CAPTAINTOK:		/********************/
+      {
+	int j;
+	i = !get_int(nexttoken, &j, (char **) 0) || j;
+      }
+      if (i)
+      {
+	if (myteam->captain < 0 ||
+	    players[myteam->captain].p_status != PALIVE ||
+	    players[myteam->captain].p_team != me->p_team)
+	{
+	  if (myteam->captain >= 0)
+	  {
+	    /*
+	     * safety valve in case the person is ghostbusted or on another
+	     * team
+	     */
+	    sprintf(buf, "%s has been overthrown as captain of the %s team",
+		    players[myteam->captain].p_name, teamtype);
+	    umpire_speak(buf);
+	  }
+	  respond("OK.  *POOF* you're a captain!", 1);
+	  sprintf(buf, "%s (%s) is now fearless leader of the %s team!",
+		  me->p_name, twoletters(me), teamtype);
+	  umpire_speak(buf);
+	  myteam->captain = me->p_no;
+	}
+	else if (iscaptain)
+	{
+	  respond("Listen, silly.  You already are captain.  No point in rubbing it in", 1);
+	}
+	else
+	{
+	  /* if myteam->captain were <0, we wouldn't get here */
+	  struct player *capn = &players[myteam->captain];
+	  sprintf(buf, "Sorry, %s (%s) is already captain of your team.",
+		  capn->p_name, twoletters(capn));
+	  respond(buf, 1);
+	}
+      }
+      else
+      {
+	if (iscaptain)
+	{
+	  respond("Wimp.  We didn't want you for captain anyway.", 1);
+	  sprintf(buf, "%s (%s) has chickened out.",
+		  me->p_name, twoletters(me));
+	  umpire_speak(buf);
+	  sprintf(buf, "Who now will lead the %s team?", teamtype);
+	  umpire_speak(buf);
+	  myteam->captain = -1;
+	}
+	else
+	{
+	  respond("You can't quit being a captain.  You weren't one in the first place.", 1);
+	}
+      }
+      return 1;
+
+     case TIMETOK:		/********************/
+      if (0 == *nexttoken)
+      {
+	switch (status2->league)
+	{
+	 case 2:
+	  sprintf(buf, "%d seconds left in pre-tourney warm-up.",
+		  status2->leagueticksleft / SECONDS(1));
+	  break;
+	 case 3:
+	  sprintf(buf, "%d minutes left in regulation play.",
+		  status2->leagueticksleft / MINUTES(1));
+	  break;
+	 case 4:
+	  sprintf(buf, "%d minutes left in overtime.",
+		  status2->leagueticksleft / MINUTES(1));
+	  break;
+	 default:
+	  sprintf(buf, "game is configured for %d minutes (%d overtime).",
+	      configvals->regulation_minutes, configvals->overtime_minutes);
+	  break;
+	}
+	respond(buf, 0);
+	return 1;
+      }
+      else if (!iscaptain)
+      {
+	respond(captain_only, 1);
+	return 1;
+      }
+      else if (status2->league != 1)
+      {
+	respond("You can only adjust the time parameters during the configuration phase", 1);
+	return 1;
+      }
+      else if (otherteam->ready)
+      {
+	respond("The other team is ready to start.  You can't change the game params NOW.", 1);
+	return 1;
+      }
+      else if (!get_int(nexttoken, &myteam->desired.regulation, &nexttoken)
+	     || !get_int(nexttoken, &myteam->desired.overtime, (char **) 0))
+      {
+	respond("Usage: time [ %d %d ]", 1);
+	return 1;
+      }
+
+      if (status2->home.desired.regulation == status2->away.desired.regulation
+	&& status2->home.desired.overtime == status2->away.desired.overtime)
+      {
+	configvals->regulation_minutes = status2->home.desired.regulation;
+	configvals->overtime_minutes = status2->home.desired.overtime;
+	sprintf(buf, "The captains have agreed to a %d minute game (%d overtime).", configvals->regulation_minutes, configvals->overtime_minutes);
+	umpire_speak(buf);
+      }
+      else
+      {
+	sprintf(buf, "The %s team wishes a game of %d minutes (%d overtime)",
+	    teamtype, myteam->desired.regulation, myteam->desired.overtime);
+	umpire_speak(buf);
+      }
+
+      return 1;
+
+     case PASSTOK:		/********************/
+      if (status2->league != 1)
+      {
+	respond("The time for that is long past.", 1);
+	return 1;
+      }
+      if (!iscaptain)
+      {
+	respond(captain_only, 1);
+	return 1;
+      }
+      if (me->p_homeaway == AWAY && status2->awaypassed)
+      {
+	respond("You already passed the choice of empire.", 1);
+	return 1;
+      }
+      else if (me->p_homeaway == HOME && status2->awaypassed == 0)
+      {
+	respond("You can't possibly pass the choice of empire.  You don't HAVE it!", 1);
+	return 1;
+      }
+      else if (status2->awaypassed > 1)
+      {
+	respond("You both passed already, so get on with it.  (indecisive wishy-washy cretins)", 1);
+	return 1;
+      }
+      status2->awaypassed++;
+
+      sprintf(buf, "The %s team has passed the choice of empire", teamtype);
+      umpire_speak(buf);
+
+      if (status2->awaypassed > 1)
+      {
+	umpire_speak("Computer choosing randomly for both teams");
+	if (status2->home.index < 0)
+	{
+	  status2->home.index = lrand48() % ((status2->away.index < 0) ? 4 : 3);
+	  if (status2->away.index >= 0 &&
+	      status2->home.index >= status2->away.index)
+	    status2->home.index++;
+	}
+	if (status2->away.index < 0)
+	{
+	  status2->away.index = lrand48() % 3;
+	  if (status2->away.index >= status2->home.index)
+	    status2->away.index++;
+	}
+      }
+      return 1;
+
+     case STARTTOK:		/********************/
+      if (status2->league != 1)
+      {
+	respond("The game has already started.", 1);
+	return 1;
+      }
+      if (!iscaptain)
+      {
+	respond(captain_only, 1);
+	return 1;
+      }
+      if (get_int(nexttoken, &myteam->ready, (char **) 0) && !myteam->ready)
+      {
+	sprintf(buf, "The %s team is not ready.", teamtype);
+	umpire_speak(buf);
+	return 0;
+      }
+      myteam->ready = 1;
+      if (!team_really_ready(myteam))
+      {
+	respond("Your team is not really ready.  You need a name and an empire.", 0);
+	myteam->ready = 0;
+	return 0;
+      }
+
+      if (otherteam->ready && !team_really_ready(otherteam))
+      {
+	otherteam->ready = 0;
+	sprintf(buf, "The %s team was ready but the other wasn't.", teamtype);
+      }
+      else
+      {
+	sprintf(buf, "The %s team is ready to start now.", teamtype);
+      }
+      umpire_speak(buf);
+
+
+      if (otherteam->ready)
+      {
+	/* shit! we're good to go! */
+
+	umpire_speak("Both sides are ready.  Let the carnage begin!");
+	umpire_speak("Everybody dies.  T-mode starts in 1 minute.");
+	status2->league = 2;
+	status2->leagueticksleft = 60 * TICKSPERSEC;
+
+	/* version */
+
+	explode_everyone(KTOURNSTART, 0);
+      }
+      return 1;
+
+     case RESTARTTOK:		/********************/
+      if (status2->league != 1)
+      {
+	respond("The game has started.  You can't change your mind now.", 1);
+	return 1;
+      }
+
+      if (!iscaptain)
+      {
+	respond(captain_only, 1);
+	return 1;
+      }
+
+      myteam->desired.restart = !get_int(nexttoken, &i, (char **) 0) || i;
+
+      sprintf(buf, myteam->desired.restart ?
+	      "%s (%s) would like to restart team selection." :
+	      "%s (%s) is satisfied with the teams.",
+	      me->p_name, twoletters(me));
+      umpire_speak(buf);
+
+      if (status2->home.desired.restart && status2->away.desired.restart)
+      {
+	umpire_speak("Both captains have agreed to restart team selection.");
+
+	status2->awaypassed = 0;
+	status2->home.index = status2->away.index = -1;
+
+	status2->home.ready = status2->away.ready = 0;
+
+	status2->home.desired.restart = status2->away.desired.restart = 0;
+      }
+
+      return 1;
+
+     case TIMEOUTTOK:
+      respond("NYI", 0);
+      return 1;
+
+     case TEAMNAMETOK:		/********************/
+      if (status2->league != 1)
+      {
+	respond("The game has started.  You can't change your mind now.", 1);
+	return 1;
+      }
+      if (!iscaptain)
+      {
+	respond(captain_only, 1);
+	return 1;
+      }
+      if (0 == *nexttoken)
+      {
+	respond("What do you want to call your team?\n", 1);
+	return 1;
+      }
+      strncpy(myteam->name, nexttoken, sizeof(myteam->name));
+      myteam->name[sizeof(myteam->name) - 1] = 0;
+
+      sprintf(buf, "Henceforth let the %s team be known as `%s'!",
+	      teamtype, myteam->name);
+      umpire_speak(buf);
+
+      return 1;
+
+     case INFOTOK:		/********************/
+      sprintf(buf, "The game will last for %d minutes (%d overtime)",
+	      configvals->regulation_minutes,
+	      configvals->overtime_minutes);
+      respond(buf, 0);
+      sprintf(buf, "Teams are limited to %d players on the field at once",
+	      configvals->playersperteam);
+      respond(buf, 0);
+      sprintf(buf, "You are on the %s team.", teamtype);
+      respond(buf, 0);
+      talk_about_team(&status2->home, "home");
+      talk_about_team(&status2->away, "away");
+
+      if (status2->awaypassed > 1)
+	umpire_speak("Both teams passed empire choice.  Computer assigned.");
+      else if (status2->awaypassed)
+	umpire_speak("Away has passed empire choice to the Home team");
+      else
+	umpire_speak("Away chooses empire first");
+
+      return 1;
+
+
+     case AWAYTOK:		/********************/
+      {
+	struct player *victim;
+	if (!*nexttoken)
+	  victim = me;
+	else
+	{
+	  int idx = get_slotnum(nexttoken, (char **) 0);
+	  if (idx < 0)
+	  {
+	    respond("`league away' requires a valid slot number", 0);
+	    return 1;
+	  }
+	  else
+	  {
+	    victim = &players[idx];
+	  }
+	}
+	trydefect(victim, AWAY, "away", HOME, "home", me);
+      }
+      return 1;
+
+     case HOMETOK:		/********************/
+      {
+	struct player *victim;
+	if (!*nexttoken)
+	  victim = me;
+	else
+	{
+	  int idx = get_slotnum(nexttoken, (char **) 0);
+	  if (idx < 0)
+	  {
+	    respond("`league away' requires a valid slot number", 0);
+	    return 1;
+	  }
+	  else
+	  {
+	    victim = &players[idx];
+	  }
+	}
+	trydefect(victim, HOME, "home", AWAY, "away", me);
+      }
+
+      return 1;
+     case NEWGALAXY:		/********************/
+
+      if (status2->league != 1)
+      {
+	respond("The game has started.  You can't change your mind now.", 1);
+	return 1;
+      }
+
+      if (myteam->ready || otherteam->ready)
+      {
+	respond("You can't reset the galaxy now.  We're almost ready!", 1);
+	return 1;
+      }
+      if (!iscaptain)
+      {
+	respond(captain_only, 1);
+	return 1;
+      }
+
+      {
+	int j;
+	myteam->desired.galaxyreset =
+	  !get_int(nexttoken, &j, (char **) 0) || j;
+      }
+
+      if (myteam->desired.galaxyreset)
+      {
+	sprintf(buf, "%s (%s) is dissatisfied with the galaxy",
+		me->p_name, twoletters(me));
+      }
+      else
+      {
+	sprintf(buf, "%s (%s) thinks the galaxy is just fine, thank you.",
+		me->p_name, twoletters(me));
+      }
+      umpire_speak(buf);
+
+      if (status2->home.desired.galaxyreset &&
+	  status2->away.desired.galaxyreset)
+      {
+	umpire_speak("Both captains have agreed that the galaxy sucks.");
+	status2->newgalaxy = 1;
+	warning("Creating new galaxy");
+
+	status2->home.desired.galaxyreset = status2->away.desired.galaxyreset = 0;
+
+	status2->awaypassed = 0;
+	status2->home.index = status2->away.index = -1;
+	status2->home.ready = status2->away.ready = 0;
+	status2->home.desired.restart = status2->away.desired.restart = 0;
+      }
+
+      return 1;
+
+     case PAUSETOK:		/********************/
+      if (!iscaptain)
+      {
+	respond(captain_only, 1);
+	return 1;
+      }
+
+      myteam->desirepause = 1;
+
+      if (status2->home.desirepause && status2->away.desirepause)
+      {
+	/* well, it's unanimous! */
+	status2->paused = SECONDS(10);
+	umpire_speak("The game has been paused");
+      }
+      else
+      {
+	sprintf(buf, "The %s team wishes to PAUSE the game.", teamtype);
+	umpire_speak(buf);
+      }
+
+      status2->pausemsgfuse = 0;
+
+      return 1;
+
+     case CONTINUETOK:		/********************/
+      if (!iscaptain)
+      {
+	respond(captain_only, 1);
+	return 0;
+      }
+
+      myteam->desirepause = 0;
+
+      sprintf(buf, "The %s team wishes to CONTINUE.", teamtype);
+      umpire_speak(buf);
+
+      status2->pausemsgfuse = 0;
+
+      return 1;
+
+     case MAXPLAYERTOK:
+      {
+	int mp;
+	if (!get_int(nexttoken, &mp, (char **) 0))
+	{
+	  sprintf(buf, "The game is currently configured for a maximum of %d players on each", configvals->playersperteam);
+	  respond(buf, 0);
+	  respond("team.", 0);
+	  if (configvals->playersperteam != myteam->desired.maxplayers)
+	  {
+	    sprintf(buf, "You, however, want it to be %d.",
+		    myteam->desired.maxplayers);
+	    respond(buf, 0);
+	  }
+	}
+	else
+	{
+	  if (!iscaptain)
+	  {
+	    respond(captain_only, 1);
+	    return 1;
+	  }
+
+	  if (mp < 1)
+	  {
+	    respond("That's a stupid value for players-per-team.", 1);
+	    return 1;
+	  }
+
+	  myteam->desired.maxplayers = mp;
+	  if (status2->away.desired.maxplayers
+	      == status2->home.desired.maxplayers)
+	  {
+	    configvals->playersperteam = mp;
+	    sprintf(buf, "Captains have agreed to limit players per team to %d", mp);
+	    umpire_speak(buf);
+	  }
+	  else
+	  {
+	    sprintf(buf, "The %s team would like to limit the number of ",
+		    teamtype);
+	    umpire_speak(buf);
+	    sprintf(buf, "players per team to %d", mp);
+	    umpire_speak(buf);
+	  }
+	}
+      }
+      return 1;
+     case FREESLOTTOK:
+      {
+	int slotnum;
+	struct player *victim;
+	slotnum = get_slotnum(nexttoken, (char **) 0);
+	if (slotnum < 0)
+	{
+	  respond("freeslot requires slot number", 1);
+	  return 0;
+	}
+
+	victim = &players[slotnum];
+	if (victim->p_ntspid)
+	  kill(victim->p_ntspid, SIGHUP);
+
+	victim->p_status = PFREE;
+	victim->p_ntspid = 0;
+
+	sprintf(buf, "Player slot %s has been freed by %s (%2s).",
+		nexttoken, me->p_name, twoletters(me));
+	umpire_speak(buf);
+      }
+      return 1;
+    }
+}
+#endif
+/*
+ */
+
+
+
+/*
+ * Parse command messages.
+ */
+
+int
+parse_command_mess(str, who)
+  char *str;
+  unsigned char who;
+{
+  char buf[120];
+  char *nexttoken;
+  int godlike = me->p_stats.st_royal - GODLIKE + 1;
+
+  static struct control_cmd available_cmds[] = {
+    {"help", HELPTOK, 0},
+    {"control", CONTROLTOK, "control ..."},
+    {"league", LEAGUETOK, "league ..."},
+    {"version", VERSIONTOK, "version"},
+    {"player", PLAYERTOK, "player ..."},
+    {"queue", QUEUETOK, "queue"}, {"tq", QUEUETOK, 0},
+    {"information", INFOTOK, "information ..."},
+    {"observe", OBSERVETOK, "observe"},
+    {"parameters", PARAMTOK, "parameters"}, {"params", PARAMTOK, 0},
+    {"cluecheck", CLUECHECKTOK, "cluecheck [%s]"},
+    {0}
+  };
+
+  if (godlike < 0)
+    godlike = 0;
+
+
+
+#if 0
+  /* so we won't damage the original string */
+  strcpy(buf, str);
+
+  dotokenize(buf);
+
+  if (sizetokstring == 0)	/* nothing?  ok, then let them send it :) */
+    return 0;
+#endif
+
+  switch (next_token(str, available_cmds, &nexttoken))
+  {
+   case HELPTOK:
+    sprintf(buf, "Available commands: %s%s%s",
+	    godlike ? "control ..., " : "",
+#ifdef LEAGUE_SUPPORT
+	    status2->league ? "league ..., " :
+#endif
+	    "",
+	    "version, player ..., queue,");
+    respond(buf, 0);
+    respond("   information ..., observe [%d], parameters, cluecheck [%s], help", 0);
+    return 1;
+   case CONTROLTOK:
+#ifdef GOD_CONTROLS
+#ifdef LEAGUE_SUPPORT
+    if (status2->league)
+    {
+      respond("God controls are disabled during league play.", 1);
+    }
+    else
+#endif
+      return parse_control(nexttoken);
+#else
+    respond("This ntserv is not compiled with god controls.", 1);
+    return 1;
+#endif
+
+   case VERSIONTOK:
+    sprintf(buf, "NetrekII (Paradise), %s", PARAVERS);
+    respond(buf, 0);
+    return 1;
+
+   case PLAYERTOK:
+    return parse_player(nexttoken);
+
+   case QUEUETOK:
+    if (me->p_status == PTQUEUE)
+    {
+      detourneyqueue();
+    }
+    else if (status->tourn)
+      respond("Dude, what are you waiting for!?  It's T-mode.  GO FIGHT!", 1);
+    else if (!(me->p_flags & PFGREEN))
+      respond("Can not enter the tourney queue while at alert", 1);
+#ifndef AEDILE
+    else if (me->p_damage != 0 || me->p_shield < me->p_ship.s_maxshield)
+      respond("Can not enter the tourney queue while damaged", 1);
+#endif
+    else if (me->p_armies > 0)
+      respond("Can not take armies into the tourney queue", 1);
+    else
+    {
+      /*
+       * well, stick them on the queue.  They will be awoken when T mode
+       * arrives
+       */
+
+      evaporate(me);
+
+      /* need code to blab about this */
+      me->p_status = PTQUEUE;
+      sprintf(buf, "%s has entered the tournament queue to wait for T-mode", me->p_name);
+      pmessage(buf, -1, MALL, "GOD->ALL");
+    }
+    return 1;
+
+   case LEAGUETOK:
+#ifdef LEAGUE_SUPPORT
+    if (status2->league)
+    {
+      return parse_league(nexttoken);
+    }
+    else
+    {
+      respond("League commands are disabled during non-league play.", 1);
+      return 1;
+    }
+#else
+    respond("Server is not compiled with league support.", 1);
+    respond("Edit config.h, recompile, install, and nuke the game.", 1);
+    return 1;
+#endif
+
+   case INFOTOK:
+    return parse_info(nexttoken);
+
+   case OBSERVETOK:
+    {
+      int i;
+      i = !get_int(nexttoken, &i, (char **) 0) || i;
+
+      if (i)
+      {
+	if (me->p_observer && me->p_status == POBSERVE)
+	{
+	  respond("You are already an observer.", 1);
+	}
+	else
+	{
+	  if (!(me->p_flags & PFGREEN))
+	    respond("Can not become an observer while at alert", 1);
+	  else if (me->p_damage != 0 || me->p_shield < me->p_ship.s_maxshield)
+	    respond("Can not become an observer while damaged", 1);
+	  else if (me->p_armies > 0)
+	    respond("Can not become an observer while carrying armies", 1);
+	  else
+	  {
+	    evaporate(me);
+	    me->p_status = POBSERVE;
+	  }
+	  me->p_observer = 1;
+	}
+      }
+      else
+      {
+	if (me->p_observer && me->p_status == POBSERVE)
+	{
+	  me->p_observer = 0;
+#if 1
+#ifdef LEAGUE_SUPPORT
+	  if (!(status2->league && status->tourn))
+#endif
+	    evaporate(me);
+#else
+	  respond("You may now self-destruct and reenter the game as a player", 0);
+	  respond("(assuming there's room for you).", 0);
+#endif
+	}
+      }
+    }
+    return 1;
+
+   case PARAMTOK:
+    warning("Transmitting new game parameters");
+    updateGameparams();
+    return 1;
+   case CLUECHECKTOK:
+#if defined(CLUECHECK1) || defined(CLUECHECK2)
+    return accept_cluecheck(nexttoken);
+#else
+    return 0;
+#endif
+   default:
+    return 0;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/misc.c	Sat Dec 06 04:37:03 1997 +0000
@@ -0,0 +1,562 @@
+/*--------------------------------------------------------------------------
+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 <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <setjmp.h>
+
+#include "defs.h"
+#include "misc.h"
+#include "struct.h"
+#include "data.h"
+#include "daemonII.h"
+#include "planets.h"
+#include "shmem.h"
+
+/*------------------------------MODULE VARIABLES--------------------------*/
+
+#define	NMESSAGES	16
+/* The list of messages that are sent when t-mode begins.  */
+char *warmessages[] = {
+  "A dark mood settles upon the galaxy as galactic superpowers seek",
+  "to colonize new territory.  Border disputes errupt developing",
+  "into all out intergalactic WAR!!!",
+
+  "Slick Willy is elected president, the bottom falls out of the",
+  "economy, and the pressure to expand rises.",
+
+  "Clinton found with foreign emperor's wife!",
+  "All out war ensues.",
+
+  "Taxes on the rich raised to 80%.",
+  "The rich flee to neigboring empire.",
+  "Democrats demand extradition.",
+  "Foreign emporer refuses.",
+  "Hillary 'Rob Them' Clinton declares war!",
+  "Bill hides out in London.",
+
+  "INTERGALACTIC BEER SHORTAGE!",
+  "CHAOS LIKE IT HAS NEVER BEEN SEEN BEFORE ENSUES!",
+
+  "The American Gladiators hit as the number 1 show on the vid.",
+  "After a gruesome episode, the masses storm out their homes,",
+  "jump in their ships, make a quick stop at their local 7-11",
+  "to grab a few beers, then head out into the galaxy to ",
+  "KICK SOME ASS.  WAR!!!!!!!!!!!!!!!!!!",
+
+  "Khan is resurrected in a bizzare experiment.  Elected as head of",
+  "the Starfleet Council, he removes all pajama-wearing new-age",
+  "hippies from Starfleet.  (And you thought the borg were bad news)",
+
+  "Several members of the computing support staff of the Galactic",
+  "Council are severely injured in a freak skydiving accident.",
+  "The rest are killed.  The network collapses without their",
+  "guidance.  Galactic chaos breaks out!",
+
+  /* oldies */
+  "A dark mood settles upon the galaxy",
+  "Political pressure to expand is rising",
+  "Border disputes break out as political tensions increase!",
+  "Galactic superpowers seek to colonize new territory!",
+  "'Manifest Destiny' becomes motive in galactic superpower conflict!",
+  "Diplomat insults foriegn emperor's mother and fighting breaks out!",
+  "Dan Quayle declares self as galactic emperor and chaos breaks out!",
+  "Peace parties have been demobilized, and fighting ensues.",
+};
+
+
+/*
+ * The starting index of the message series and the number of messages in
+ * series.
+ */
+int warm[NMESSAGES][2] = {
+  {0, 3},
+  {3, 2},
+  {5, 2},
+  {7, 6},
+  {13, 2},
+  {15, 5},
+  {20, 3},
+  {23, 4},
+  {27, 1},
+  {28, 1},
+  {29, 1},
+  {30, 1},
+  {31, 1},
+  {32, 1},
+  {33, 1},
+  {34, 1},
+};
+
+
+/* The set of message series that are displayed when t-mode ends. */
+char *peacemessages[] = {
+  "The expansionist pressure subsides, and temporary agreements are",
+  "reached in local border disputes.",
+  "Peace returns to the galaxy...",
+
+  "Wild mob storms the White House!",
+  "Clinton flees.",
+  "Order returns to the galaxy.",
+
+  "Slick Willy apologizes about incident with foreign emperor's wife.",
+  "Claims he did not penetrate.",
+  "Peace ensues.",
+
+  "The economy goes belly up.  The Democrats are kicked",
+  "out of office, tarred and feathered, and sent to the",
+  "zoo on Rigel 4.  Capitalism is implemented and order",
+  "returns to the empire.",
+
+  "Officials sieze hidden beer stockpiles at the Mackenzie brother's",
+  "house!  The beer shortage is over.  Peace breaks out.",
+
+  "The people decide they would rather sit home and watch",
+  "Al Bundy than fight.  The war comes to an end.",
+
+  "Khan takes a fatal blow to the kidneys when Kirk returns from",
+  "retirement and whacks him in the back with his walker.",
+  "It looks like the hippies are back in control.",
+
+  "Sole survivors of the skydiving accident that took out the",
+  "rest of the computing support staff, Michael McLean and Brad",
+  "Spatz are released from intensive care and rebuild the",
+  "network.  Peace is restored to the Galaxy.",
+
+  /* oldies */
+  "A new day dawns as the oppressive mood lifts",
+  "The expansionist pressure subsides",
+  "Temporary agreement is reached in local border disputes.",
+  "Galactic governments reduce colonization efforts.",
+  "'Manifest Destiny is no longer a fad.' says influential philosopher.",
+  "Diplomat apologizes to foreign emperor's mother and invasion is stopped!",
+  "Dan Quayle is locked up and order returns to the galaxy!",
+  "The peace party has reformed, and is rallying for peace",
+};
+
+
+/*
+ * The starting index of each message series and the number of messages in
+ * the series.
+ */
+int peacem[NMESSAGES][2] = {
+  {0, 3},
+  {3, 3},
+  {6, 3},
+  {9, 4},
+  {13, 2},
+  {15, 2},
+  {17, 3},
+  {20, 4},
+  {24, 1},
+  {25, 1},
+  {26, 1},
+  {27, 1},
+  {28, 1},
+  {29, 1},
+  {30, 1},
+  {31, 1},
+};
+
+
+static int series = 0;		/* the message series that was printed */
+/* when t-mode started.  */
+
+/*------------------------------------------------------------------------*/
+
+
+
+
+
+
+
+
+/*------------------------------VISIBLE FUNCTIONS-------------------------*/
+
+/*---------------------------------WARMESSAGE----------------------------*/
+/*
+ * This function is called when t-mode ensues.  It chooses a message series
+ * and prints it out.  It records the message series in the module's series
+ * variable so that the corresponding peace message series can be printed.
+ */
+
+
+void
+warmessage()
+{
+  int i;			/* to hold index */
+  int n;			/* number of messages in a series */
+
+  i = lrand48() % NMESSAGES;	/* choose message series */
+  series = i;			/* record series number */
+  n = warm[i][1];		/* get number of messages in series */
+  i = warm[i][0];		/* get index of first message */
+  while (n > 0)
+  {				/* print all messages */
+    pmessage(warmessages[i], 0, MALL, "  WAR->  ");
+    n--;			/* dec messages that need to be printed */
+    i++;			/* on to next message */
+  }
+}
+
+
+
+
+/*-------------------------------PEACEMESSAGE-----------------------------*/
+/*
+ * This function prints a peace message series.  It uses the module variable
+ * series to decide which message series to print.
+ */
+
+void
+peacemessage()
+{
+  int i;			/* to hold index */
+  int n;			/* number of messages in a series */
+
+  n = peacem[series][1];	/* get # messages in series */
+  i = peacem[series][0];	/* get starting index */
+  while (n > 0)
+  {				/* print all messages */
+    pmessage(peacemessages[i], 0, MALL, " PEACE-> ");
+    n--;			/* dec messages that need to be printed */
+    i++;			/* on to next message */
+  }
+}
+
+
+
+
+/*-------------------------------REALNUMSHIPS-----------------------------*/
+/*
+ * This function counts the number of ships on a team.  If the race is the
+ * same and the slot is not free, then the ship is counted.
+ */
+
+int
+realNumShips(owner)
+  int owner;
+{
+  int i, num;			/* for looping and counting */
+  struct player *p;		/* to point to a player */
+
+  num = 0;			/* zero the count of ships */
+  for (i = 0, p = players; i < MAXPLAYER; i++, p++)
+    if ((p->p_status != PFREE) && (p->p_team == owner))
+      num++;			/* found a ship on this team, inc count */
+  return (num);			/* return number of ships */
+}
+
+
+
+
+/*------------------------------TOURNAMENTMODE------------------------------*/
+/*
+ * This function counts the number of players on each team and sees if two or
+ * more teams have enough players for t-mode.  It returns a 0 for no team
+ * mode.
+ */
+
+int
+tournamentMode()
+{
+#ifdef LEAGUE_SUPPORT
+  if (status2->league)
+  {
+    return status2->league > 2;
+  }
+  else
+#endif
+  {
+    static int wt = -1;		/* warning time due to team unbalance */
+    static int lct = -1;	/* last check time (ie last pmessage) */
+    char buf[80];		/* temp buffer for tmode halt warning */
+    int i;			/* looping vars */
+    int t[16];			/* to count players with */
+    int counts[4];
+    /* Even though teams go from 0-8, leave */
+    /* this at 16...or bad things might happen */
+    struct player *p;		/* to point to players */
+
+    for (i = 0; i < 16; i++)	/* clear the team players count array */
+      t[i] = 0;
+    for (i = 0, p = players; i < MAXPLAYER; i++, p++)
+    {
+      /* through all players */
+      if (p->p_flags & PFROBOT)
+	continue;		/* robots don't count */
+      switch (p->p_status)
+      {
+       case PFREE:		/* free slots obviously don't count */
+       case POBSERVE:		/* and neither do observers */
+	break;
+
+       case PEXPLODE:
+       case PDEAD:
+       case PTQUEUE:
+	if (p->p_observer)
+	  break;		/* observers in these modes don't count */
+	/* we can fall through here */
+       case POUTFIT:
+       case PALIVE:
+	t[p->p_team]++;
+	break;
+      }
+    }
+
+#if 0
+    /*
+     * If there hasnt been tmode recently (5 mins) clear all kills, and place
+     * any carried armies on the most valuble planet not yet finished.
+     */
+    if ((tourntimestamp - ticks) > 300)
+    {
+      int x;
+      for (x = 0; x < MAXPLAYER; x++)
+      {
+	if (players[x].p_status == PALIVE)
+	{
+	  if (players[x].p_armies > 0)
+	    PlaceLostArmies(players[x]);
+	  players[x].p_kills = 0.00;
+	}
+      }
+    }
+#endif
+
+    i = 0;			/* zero count of # teams with tournplayers */
+    if (t[FED] >= configvals->tournplayers)
+      counts[i++] = t[FED];
+    if (t[ROM] >= configvals->tournplayers)
+      counts[i++] = t[ROM];
+    if (t[KLI] >= configvals->tournplayers)
+      counts[i++] = t[KLI];
+    if (t[ORI] >= configvals->tournplayers)
+      counts[i++] = t[ORI];
+    if (i > 1)
+    {
+      i = counts[0] - counts[1];
+      if (i < 0)
+	i = -i;
+      if (i > 2)
+      {				/* Too big a team imbalance */
+	if (wt == -1)
+	{
+	  wt = status->clock;	/* make a timestamp */
+	  lct = status->clock;	/* used every time it sends the message */
+	}
+	if (((status->clock - wt) < 3) && (lct < status->clock))
+	{
+	  /*
+	   * teams are unblananced, and we havn't said anything for 1 minute,
+	   * warn everybody  Yes these are noisy strings, but I want people
+	   * to notice.
+	   */
+	  pmessage("**************************!! Teams are unbalanced !!**************************", 0, MALL, "");
+	  sprintf(buf, "********************* TMODE WILL BE HALTED IN %li MINUTES **********************", (wt - status->clock) + 3);
+	  pmessage(buf, 0, MALL, "");
+	  pmessage("************************ if this problem isn't fixed *************************", 0, MALL, "");
+	  lct = status->clock;
+	  return (1);
+	}
+	else if ((status->clock - wt) >= 3)
+	{
+	  if (lct < status->clock)
+	  {
+	    pmessage("******************!! TMODE HALTED DUE TO TEAM IMBALANCE !!********************", 0, MALL, "");
+	    pmessage("*********************** Balance teams to resume tmode ************************", 0, MALL, "");
+	    lct = status->clock;
+	  }
+	  return (0);		/* stop tmode */
+	}
+      }
+      else
+      {
+	wt = -1;
+	lct = -1;
+      }
+      return (1);		/* return that we are in team mode */
+    }
+    return (0);			/* we are NOT in T-mode */
+  }
+}
+
+
+
+
+/*------------------------------PMESSAGE----------------------------------*/
+/*
+ * This function sens a message to the message board.  It places the message
+ * in the next position of the array of messages.  The message will ahve a
+ * header attached to the front of it.
+ */
+
+void
+pmessage(str, recip, group, address)
+  char *str;			/* the message */
+  int recip;			/* who is the recipient */
+  int group;			/* group sent to and other flags */
+  char *address;		/* the header attached to front */
+{
+  struct message *cur;		/* to pnt to where to put message */
+  int mesgnum;			/* to hold index into array of messgs */
+
+  if ((mesgnum = ++(mctl->mc_current)) >= MAXMESSAGE)
+  {
+    mctl->mc_current = 0;	/* move to next index in array and */
+    mesgnum = 0;		/* warp around if necessart */
+  }
+  cur = &messages[mesgnum];	/* get addr of message struct */
+  cur->m_no = mesgnum;		/* set the message number */
+  cur->m_flags = group;		/* set the group and flags */
+  cur->m_recpt = recip;		/* set the recipient */
+  cur->m_from = 255;		/* message is from God */
+  (void) sprintf(cur->m_data, "%s %s", address, str);
+  cur->m_flags |= MVALID;	/* mark message as valid */
+}
+
+/*
+ * send a message from god to a particular player number
+ */
+
+void
+god2player(str, pno)
+  char *str;
+  int pno;
+{
+  struct message *cur;		/* to pnt to where to put message */
+
+  if (++(mctl->mc_current) >= MAXMESSAGE)
+    mctl->mc_current = 0;
+  cur = &messages[mctl->mc_current];
+
+  cur->m_no = mctl->mc_current;
+  cur->m_flags = MINDIV;
+  cur->m_recpt = pno;
+  cur->m_from = 255;
+  sprintf(cur->m_data, "%s->%s %s", SERVNAME, twoletters(&players[pno]), str);
+  cur->m_flags |= MVALID;
+}
+
+
+
+
+/*-------------------------------LOG_MESSAGE------------------------------*/
+/*
+ * This function writes a message into the logfile so the server god can look
+ * at it later.  It is used to record messages to god.
+ */
+
+void
+log_message(msg)
+  char *msg;			/* the string to record */
+{
+  char *path;			/* to hold path and name */
+  FILE *logfile;		/* to open logfile with */
+
+  path = build_path(GODLOGFILE);
+  logfile = fopen(path, "a");	/* let's try to open this baby */
+  if (!logfile)			/* Oops, could not open */
+    return;			/* OUt of Dodge */
+  fputs(msg, logfile);		/* write the string to log file */
+  fclose(logfile);		/* close the sucker up */
+}
+
+
+
+
+/*-----------------------------PARSE_GODMESSAGES----------------------------*/
+/*
+ * This function checks all the new messages in the message buffer to see if
+ * the keyword 'GOD' is at the first of the message.  If it is, then the
+ * message is written to the logfile so the server god can read it.
+ */
+
+void
+parse_godmessages()
+{
+  char buf[100];		/* bigger than message::m_data */
+  static int lastparsed = 0;	/* keeps track of last message */
+
+  while (mctl->mc_current != lastparsed)
+  {				/* Is there a new message? */
+    struct message *cur;	/* to point to message struct */
+    char *s;			/* to point to string */
+
+    if (++lastparsed >= MAXMESSAGE)	/* rollover after end of */
+      lastparsed = 0;		/* message buffer */
+    cur = &messages[lastparsed];/* get new message's struct */
+
+    s = cur->m_data + 1;	/* get new message */
+    while ((*s != ' ') && (*s != 0))	/* go until first space */
+      s++;
+    while ((*s == ' ') && (*s != 0))	/* go past spaces */
+      s++;
+
+    if (!*s)
+      continue;
+    if (cur->m_flags & MGOD)
+    {				/* if it's to god */
+      sprintf(buf, "%s says: %s\n",
+	      (cur->m_from >= 0) ? players[cur->m_from].p_name : "who", s);
+    }
+    else
+    {				/* or labeled to god */
+      if (strncmp(s, "GOD:", 4) != 0)	/* check for 'GOD' keyword */
+	continue;		/* not there, then next message */
+      sprintf(buf, "GOD: %s\n", s + 4);
+    }
+    log_message(buf);		/* go record message */
+  }
+}
+
+/*------------------------------------------------------------------------*/
+#if 0
+/*--------------------------[ PLACE LOST ARMIES ]--------------------------*/
+/*
+ * If for some reason or another the player looses armies they may be
+ * carrying (ghost busts, etc), this function is called, to place the armies
+ * safely on a planet.
+ */
+
+void
+PlaceLostArmies(victim)
+  struct player *victim;
+{
+  char buf[80];
+  int i, startplanet;
+
+  ((startplanet = find_start_planet(me->p_team, PLSHIPYARD)) != -1
+   || (startplanet = find_start_planet(me->p_team, PLREPAIR)) != -1
+   || (startplanet = find_start_planet(me->p_team, PLAGRI)) != -1
+   || (startplanet = find_start_planet(me->p_team, PLFUEL)) != -1
+   || (startplanet = find_start_planet(me->p_team, PLHOME)) != -1
+   || (startplanet = find_start_planet(me->p_team, 0)) != -1);
+  planets[startplanet].pl_armies += victim->p_armies;
+  (void) sprintf(buf, "%s's %d armies placed on %s",
+	    victim->p_name, victim->p_armies, planets[startplanet].pl_name);
+  pmessage(buf, 0, MALL | MGHOST, MSERVA);
+}
+#endif
+/*------------------------------------------------------------------------*/
+
+/*----------END OF FILE--------*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/misc.h	Sat Dec 06 04:37:03 1997 +0000
@@ -0,0 +1,36 @@
+/*--------------------------------------------------------------------------
+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 warmessage();		/* print war message */
+void peacemessag();		/* print peace message */
+int realNumShips();		/* number of ships on a team */
+int tournamentMode();		/* are we in tourn mode */
+void pmessage( /* char *str, int recip, int group, char addr */ );
+void parse_godmesssages();	/* detect and log messages to god */
+void PlaceLostArmies();		/* places armies from a lost/GB'd player */
+/*--------------------------------------------------------------------------*/
+
+
+
+
+
+
+/*--------END OF FILE------*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/orbit.c	Sat Dec 06 04:37:03 1997 +0000
@@ -0,0 +1,235 @@
+/*--------------------------------------------------------------------------
+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 <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+
+#include "defs.h"
+#include "struct.h"
+#include "data.h"
+#include "shmem.h"
+
+
+void newdock();
+extern void move_player();
+
+static void
+deactivate_friendly_tractors()
+{
+  int i;
+  struct player *j;
+  for (i = 0; i < MAXPLAYER; i++)
+  {
+    j = &players[i];
+    if (i == me->p_no ||
+	j->p_team != me->p_team ||
+	j->p_tractor != me->p_no)
+      continue;
+    /* j is a teammate with a tractor on me */
+    j->p_flags &= ~(PFTRACT | PFPRESS);
+  }
+}
+
+/*------------------------------VISIBLE PROCEDURES-------------------------*/
+
+/*-----------------------------------ORBIT---------------------------------*/
+/*
+ * This function is called when the player presses the orbit key.  It check
+ * to make sure the player can orbit or dock.  The function first checks
+ * through the list of players to see whether there is a dockable ship
+ * nearby. If that fails, then the planets are checked.  The orbit key acts
+ * as a toggle for docking and undocking at ships.
+ */
+
+void
+orbit()
+{
+  register int i;		/* looping var */
+  register struct planet *l;	/* to point to planet being orbited */
+  unsigned char dir;		/* to hold course direction */
+  int dx, dy;			/* used to get distances */
+
+  if (me->p_flags & PFORBIT)	/* if not orbiting then we do not */
+    return;			/* need to do this section of code */
+  if (me->p_speed > ORBSPEED)
+  {				/* going to fast to orbit/dock? */
+    warning("Helmsman: Captain, the maximum safe speed for docking or orbiting is warp 2!");
+    return;
+  }				/* turn off flags */
+  me->p_flags &= ~(PFORBIT | PFTRACT | PFPRESS |
+		   PFWARP | PFAFTER | PFWARPPREP | PFWPSUSPENDED);
+  me->p_warptime = 0;
+  if ((me->p_flags & PFDOCK) && (players[me->p_docked].p_speed > 4))
+  {
+    warning("It's unsafe to disengage from your base when it's moving faster then warp 4.");	/* cannot disengage from
+												 * travelling */
+    return;			/* ships if they are going too fast */
+  }
+  else
+    undock_player(me);		/* make sure I'm not docked */
+
+  if (!(me->p_flags & PFPLLOCK) &&	/* if we aren't locked onto a planet */
+      can_dock(me->p_ship))
+  {				/* and player can dock then */
+    for (i = 0; i < MAXPLAYER; i++)
+    {				/* go through all players */
+      if (me->p_no == i)	/* and look for ships that */
+	continue;		/* allow docking */
+      if (!allows_docking(players[i].p_ship))
+	continue;
+      if (!isAlive(&players[i]))/* disregard players not */
+	continue;		/* alive */
+      if (!friendlyPlayer(&players[i]))	/* cannot dock on enemy */
+	continue;		/* players */
+      dx = ABS(players[i].p_x - me->p_x);	/* get distance */
+      dy = ABS(players[i].p_y - me->p_y);
+      if (dx > DOCKDIST || dy > DOCKDIST)	/* if too far away thenwe */
+	continue;		/* cannot dock here */
+      newdock(i);		/* find a port and dock */
+
+      deactivate_friendly_tractors();
+
+      me->p_flags &= ~(PFPLOCK | PFPLLOCK);
+      return;
+    }
+  }				/* not docking with a player try a planet */
+  if (!(me->p_flags & PFPLOCK))
+  {				/* aren't locked onto a player */
+    for (i = 0, l = &planets[i]; i < NUMPLANETS; i++, l++)
+    {
+      switch (PL_TYPE(*l))
+      {
+       case PLSTAR:
+       case PLNEB:
+       case PLBHOLE:
+       case PLPULSAR:
+	continue;
+      }
+
+      dx = ABS(l->pl_x - me->p_x);	/* go through all planets and */
+      dy = ABS(l->pl_y - me->p_y);	/* check their distance */
+      if (dx > ENTORBDIST || dy > ENTORBDIST)
+	continue;		/* too far away?  */
+      if (dx * dx + dy * dy > ENTORBDIST * ENTORBDIST)
+	continue;
+
+      if (!(me->p_team & planets[i].pl_owner) &&	/* can player orbit? */
+	  !(me->p_ship.s_nflags & SFNCANORBIT))
+      {
+	warning("Central Command regulations prohibits you from orbiting foreign planets");
+	return;
+      }
+      if (!(me->p_team & planets[i].pl_owner) &&
+	  !status->tourn)
+      {
+	warning("No one is allowed to orbit alien planets outside of T-mode");
+	return;
+      }
+      dir = (unsigned char) (int) (atan2((double) (me->p_x - l->pl_x),
+			    (double) (l->pl_y - me->p_y)) / 3.14159 * 128.);
+      scout_planet(me->p_no, l->pl_no);
+#if 0
+      l->pl_torbit |= me->p_team;	/* place team in orbit */
+#endif
+      me->p_orbitdir = drand48() < configvals->orbitdirprob;
+      me->p_dir = dir + (me->p_orbitdir ? 64 : -64);	/* get direction for
+							 * player */
+      me->p_flags |= PFORBIT;	/* set his orbiting flag */
+
+      deactivate_friendly_tractors();
+
+      move_player(me->p_no, (int) (l->pl_x + ORBDIST * Cos[dir]),
+		  (int) (l->pl_y + ORBDIST * Sin[dir]), 1);
+
+      me->p_speed = me->p_desspeed = 0;
+      me->p_planet = l->pl_no;	/* set the planet number */
+      me->p_flags &= ~(PFPLOCK | PFPLLOCK);
+      return;
+    }
+  }
+  warning("Helmsman:  Sensors read no valid targets in range to dock or orbit sir!");
+}
+
+
+
+/*--------------------------------NEWDOCK--------------------------------*/
+
+
+void
+newdock(base_num)
+  int base_num;
+{
+  char buf[80];			/* to sprintf into */
+  struct player *base = &players[base_num];
+  int port_id, i;
+  int numports;
+  long distsq = 0;		/* will be set by the first matching port */
+  int angle;
+
+  if (!(base->p_flags & PFDOCKOK))
+  {				/* docking allowed? */
+    sprintf(buf, "Starbase %s refusing us docking permission captain.",
+	    base->p_name);
+    warning(buf);		/* if not say so then */
+    return;			/* get out of here */
+  }
+  port_id = -1;
+  numports = base->p_ship.s_numports;
+
+  for (i = 0; i < numports; i++)
+  {
+    long ds;
+    int x, y;
+    angle = (2 * i + 1) * 128 / numports;
+
+    if (base->p_port[i] != VACANT)
+      continue;
+
+    x = base->p_x + DOCKDIST * Cos[angle];
+    y = base->p_y + DOCKDIST * Sin[angle];
+    ds = (me->p_x - x) * (me->p_x - x) + (me->p_y - y) * (me->p_y - y);
+    if (port_id == -1 || ds < distsq)
+    {
+      port_id = i;
+      distsq = ds;
+    }
+  }
+
+  if (port_id < 0)
+  {
+    sprintf(buf, "Base %s: Permission to dock denied, all ports currently occupied.", base->p_name);
+    warning(buf);		/* print message to tell */
+    return;
+  }				/* player */
+  dock_to(me, base_num, port_id);
+
+  sprintf(buf, "Helmsman:  Docking manuever completed Captain.  All moorings secured at port %d.", port_id);
+  warning(buf);			/* tell user he's docked */
+}
+
+#ifdef HAVE_RAND48
+
+double drand48();
+
+#endif
+
+/*------------END OF FILE--------*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/packets.c	Sat Dec 06 04:37:03 1997 +0000
@@ -0,0 +1,359 @@
+/*--------------------------------------------------------------------------
+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 <stddef.h>
+#include <stdio.h>
+
+#include "defs.h"
+#include "packets.h"
+#include "gppackets.h"
+#include "wtext.h"
+
+size_t client_packet_sizes[] = {
+  0,
+  sizeof(struct mesg_cpacket),
+  sizeof(struct speed_cpacket),
+  sizeof(struct dir_cpacket),
+  sizeof(struct phaser_cpacket),
+  sizeof(struct plasma_cpacket),
+  sizeof(struct torp_cpacket),
+  sizeof(struct quit_cpacket),
+  sizeof(struct login_cpacket),
+  sizeof(struct outfit_cpacket),
+  /* 10 v */
+  sizeof(struct war_cpacket),
+  sizeof(struct practr_cpacket),
+  sizeof(struct shield_cpacket),
+  sizeof(struct repair_cpacket),
+  sizeof(struct orbit_cpacket),
+  sizeof(struct planlock_cpacket),
+  sizeof(struct playlock_cpacket),
+  sizeof(struct bomb_cpacket),
+  sizeof(struct beam_cpacket),
+  sizeof(struct cloak_cpacket),
+  /* 20 v */
+  sizeof(struct det_torps_cpacket),
+  sizeof(struct det_mytorp_cpacket),
+  sizeof(struct copilot_cpacket),
+  sizeof(struct refit_cpacket),
+  sizeof(struct tractor_cpacket),
+  sizeof(struct repress_cpacket),
+  sizeof(struct coup_cpacket),
+  sizeof(struct socket_cpacket),
+  sizeof(struct options_cpacket),
+  sizeof(struct bye_cpacket),
+  /* 30 v */
+  sizeof(struct dockperm_cpacket),
+  sizeof(struct updates_cpacket),
+  sizeof(struct resetstats_cpacket),
+  sizeof(struct reserved_cpacket),
+  sizeof(struct scan_cpacket),
+  sizeof(struct udp_req_cpacket),
+  sizeof(struct sequence_cpacket),
+  sizeof(struct rsa_key_cpacket),
+  sizeof(struct obvious_packet),
+  0,
+  /* 40 v */
+  0,
+  0,
+  sizeof(struct ping_cpacket),
+#ifdef SHORT_PACKETS
+  sizeof(struct shortreq_cpacket),
+  sizeof(struct threshold_cpacket),
+  0,				/* CP_S_MESSAGE */
+  0,				/* CP_S_RESERVED */
+  0,				/* CP_S_DUMMY */
+#else
+  0,
+  0,
+  0,
+  0,
+  0,
+#endif
+  0,
+  0,
+  /* 50 v */
+  0,
+  0,
+  0,
+  0,
+  0,
+  0,
+  0,
+  0,
+  0,
+  0,
+  /* 60 v */
+#ifdef FEATURE
+  sizeof(struct feature_cpacket)/* CP_FEATURE */
+#else
+  0
+#endif
+};
+
+#define num_cpacket_sizes	sizeof(client_packet_sizes)/sizeof(*client_packet_sizes)
+
+int 
+size_of_cpacket(pkt)
+  void *pkt;
+{
+  CARD8 type;
+  CARD8 subtype;
+
+  type = ((CARD8 *) pkt)[0];
+  subtype = ((CARD8 *) pkt)[1];
+
+  if (type < num_cpacket_sizes && client_packet_sizes[type] > 0)
+    return client_packet_sizes[type];
+
+  switch (type)
+  {
+#ifdef CP_FIRE_WEAPON
+   case CP_FIRE_WEAPON:
+    {
+      struct fire_weapon_cpacket *fwp = pkt;
+      return (fwp->mech == TM_POSITION) ? 12 : 4;
+    }
+#endif
+
+#ifdef SHORT_PACKETS
+   case CP_S_MESSAGE:
+    return ((unsigned char *) pkt)[3];
+   case CP_S_RESERVED:
+   case CP_S_DUMMY:
+    /* hmm? good question */
+    return 0;
+#endif				/* SHORT_PACKETS */
+
+   default:
+    return 0;
+  }
+}
+
+
+int server_packet_sizes[] = {
+  0,				/* record 0 */
+  sizeof(struct mesg_spacket),	/* SP_MESSAGE */
+  sizeof(struct plyr_info_spacket),	/* SP_PLAYER_INFO */
+  sizeof(struct kills_spacket),	/* SP_KILLS */
+  sizeof(struct player_spacket),/* SP_PLAYER */
+  sizeof(struct torp_info_spacket),	/* SP_TORP_INFO */
+  sizeof(struct torp_spacket),	/* SP_TORP */
+  sizeof(struct phaser_spacket),/* SP_PHASER */
+  sizeof(struct plasma_info_spacket),	/* SP_PLASMA_INFO */
+  sizeof(struct plasma_spacket),/* SP_PLASMA */
+  /* 10 v */
+  sizeof(struct warning_spacket),	/* SP_WARNING */
+  sizeof(struct motd_spacket),	/* SP_MOTD */
+  sizeof(struct you_spacket),	/* SP_YOU */
+  sizeof(struct queue_spacket),	/* SP_QUEUE */
+  sizeof(struct status_spacket),/* SP_STATUS */
+  sizeof(struct planet_spacket),/* SP_PLANET */
+  sizeof(struct pickok_spacket),/* SP_PICKOK */
+  sizeof(struct login_spacket),	/* SP_LOGIN */
+  sizeof(struct flags_spacket),	/* SP_FLAGS */
+  sizeof(struct mask_spacket),	/* SP_MASK */
+  /* 20 v */
+  sizeof(struct pstatus_spacket),	/* SP_PSTATUS */
+  sizeof(struct badversion_spacket),	/* SP_BADVERSION */
+  sizeof(struct hostile_spacket),	/* SP_HOSTILE */
+  sizeof(struct stats_spacket),	/* SP_STATS */
+  sizeof(struct plyr_login_spacket),	/* SP_PL_LOGIN */
+  sizeof(struct reserved_spacket),	/* SP_RESERVED */
+  sizeof(struct planet_loc_spacket),	/* SP_PLANET_LOC */
+  sizeof(struct scan_spacket),	/* SP_SCAN (ATM) */
+  sizeof(struct udp_reply_spacket),	/* SP_UDP_REPLY */
+  sizeof(struct sequence_spacket),	/* SP_SEQUENCE */
+  /* 30 v */
+  sizeof(struct sc_sequence_spacket),	/* SP_SC_SEQUENCE */
+  sizeof(struct rsa_key_spacket),	/* SP_RSA_KEY */
+  sizeof(struct motd_pic_spacket),	/* SP_MOTD_PIC */
+  sizeof(struct stats_spacket2),/* SP_STATS2 */
+  sizeof(struct status_spacket2),	/* SP_STATUS2 */
+  sizeof(struct planet_spacket2),	/* SP_PLANET2 */
+  sizeof(struct obvious_packet),/* SP_NEW_MOTD */
+  sizeof(struct thingy_spacket),/* SP_THINGY */
+  sizeof(struct thingy_info_spacket),	/* SP_THINGY_INFO */
+  sizeof(struct ship_cap_spacket),	/* SP_SHIP_CAP */
+  /* 40 v */
+#ifdef SHORT_PACKETS
+  sizeof(struct shortreply_spacket),	/* SP_S_REPLY */
+  -1,				/* SP_S_MESSAGE */
+  -1,				/* SP_S_WARNING */
+  sizeof(struct youshort_spacket),	/* SP_S_YOU */
+  sizeof(struct youss_spacket),	/* SP_S_YOU_SS */
+  -1,				/* SP_S_PLAYER */
+#else
+  -1,
+  -1,
+  -1,
+  -1,
+  -1,
+  -1,
+#endif
+  sizeof(struct ping_spacket),	/* SP_PING */
+  -1,				/* SP_S_TORP */
+  -1,				/* SP_S_TORP_INFO */
+  20,				/* SP_S_8_TORP */
+  /* 50 v */
+  -1,				/* SP_S_PLANET */
+  -1,				/* SP_GPARAM */
+  -1,				/* SP_PARADISE_EXT1 */
+  sizeof(struct terrain_packet2),	/* SP_TERRAIN2 */
+  sizeof(struct terrain_info_packet2),	/* SP_TERRAIN_INFO2 */
+  -1,
+  -1,
+  -1,
+  -1,
+  -1,
+  /* 60 v */
+#ifdef FEATURE
+  sizeof(struct feature_spacket),	/* SP_FEATURE */
+#else
+  -1,
+#endif
+  -1				/* The fools!  I'm pretty sure there is an */
+  /* off-by-one in the test in the last fnc */
+  /* but I'm not sure and this WILL fix it. */
+};
+
+#define num_spacket_sizes (sizeof(server_packet_sizes) / sizeof(server_packet_sizes[0]) - 1)
+
+#ifdef SHORT_PACKETS
+unsigned char numofbits[256] =
+{0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1,
+  2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 1,
+  2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2,
+  3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 1,
+  2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2,
+  3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2,
+  3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3,
+  4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 1,
+  2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2,
+  3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2,
+  3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3,
+  4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 2,
+  3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3,
+  4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3,
+  4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4,
+5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8};
+
+static int vtsize[9] =
+{4, 8, 8, 12, 12, 16, 20, 20, 24};	/* How big is the torppacket */
+int vtisize[9] =
+{4, 7, 9, 11, 13, 16, 18, 20, 22};	/* 4 byte Header + torpdata */
+
+
+static int 
+padto4(sz)
+  int sz;
+{
+  return (sz % 4) ? (sz / 4 + 1) * 4 : sz;
+
+}
+#endif
+
+int
+size_of_spacket(pkt)
+  unsigned char *pkt;
+{
+  switch (pkt[0])
+  {
+   case SP_GPARAM:
+    switch (pkt[1])
+    {
+     case 0:
+      return sizeof(struct gp_sizes_spacket);
+     case 1:
+      return sizeof(struct gp_team_spacket);
+     case 2:
+      return sizeof(struct gp_teamlogo_spacket);
+     case 3:
+      return sizeof(struct gp_shipshape_spacket);
+     case 4:
+      return sizeof(struct gp_shipbitmap_spacket);
+     case 5:
+      return sizeof(struct gp_rank_spacket);
+     case 6:
+      return sizeof(struct gp_royal_spacket);
+     case 7:
+      return sizeof(struct gp_teamplanet_spacket);
+     default:
+      return 0;
+    }
+#ifdef SHORT_PACKETS
+   case SP_S_MESSAGE:
+    return padto4(pkt[4]);	/* IMPORTANT  Changed */
+   case SP_S_WARNING:
+    if (pkt[1] == STEXTE_STRING ||
+	pkt[1] == SHORT_WARNING)
+    {
+      return padto4(pkt[3]);
+    }
+    else
+      return 4;			/* Normal Packet */
+   case SP_S_PLAYER:
+    if (pkt[1] & 128)
+    {				/* Small +extended Header */
+      return padto4(((pkt[1] & 0x3f) * 4) + 4);
+    }
+    else if (pkt[1] & 64)
+    {				/* Small Header */
+      return padto4(((pkt[1] & 0x3f) * 4) + 4);
+    }
+    else
+    {				/* Big Header */
+      return padto4((pkt[1] * 4 + 12));
+    }
+   case SP_S_TORP:
+    return padto4(vtsize[numofbits[pkt[1]]]);
+   case SP_S_TORP_INFO:
+    return padto4((vtisize[numofbits[pkt[1]]] + numofbits[pkt[3]]));
+   case SP_S_PLANET:
+    return padto4((pkt[1] * VPLANET_SIZE) + 2);
+#endif
+   case SP_PARADISE_EXT1:
+    switch (pkt[1])
+    {
+     case SP_PE1_MISSING_BITMAP:
+      return sizeof(struct pe1_missing_bitmap_spacket);
+     case SP_PE1_NUM_MISSILES:
+      return sizeof(struct pe1_num_missiles_spacket);
+     default:
+      return 0;
+    }
+   default:
+#ifdef FEATURE_DIAG
+    if (*pkt >= num_spacket_sizes)
+    {
+      fprintf(stderr, "Packet type %d out of range (%d)\n", (*pkt), num_spacket_sizes);
+      return (0);
+    }
+    if (server_packet_sizes[*pkt] < 0)
+    {
+      fprintf(stderr, "Packet type %d has no size\n", (*pkt));
+      return (0);
+    }
+    return (server_packet_sizes[*pkt]);
+#else
+    return (*pkt < num_spacket_sizes && server_packet_sizes[*pkt] >= 0)
+      ? server_packet_sizes[*pkt] : 0;
+#endif
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/packets.h	Sat Dec 06 04:37:03 1997 +0000
@@ -0,0 +1,1201 @@
+/*--------------------------------------------------------------------------
+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 file for socket I/O xtrek.
+ * 
+ * Kevin P. Smith 1/29/89
+ */
+
+#ifndef packets_h_
+#define packets_h_
+
+#define STATUS_TOKEN	"\t@@@"	/* ATM */
+
+/*
+ * the following typedefs allow portability to machines without the
+ * ubiquitous 32-bit architecture (KSR1, Cray, DEC Alpha)
+ */
+
+typedef unsigned int CARD32;
+typedef unsigned short CARD16;
+typedef unsigned char CARD8;
+
+typedef int INT32;
+typedef short INT16;
+#if __STDC__ || defined(sgi) || defined(AIXV3)
+typedef signed char INT8;
+#else
+/* stupid compilers */
+typedef char INT8;
+#endif
+
+/*
+ * TCP and UDP use identical packet formats; the only difference is that,
+ * when in UDP mode, all packets sent from server to client have a sequence
+ * number appended to them.
+ * 
+ * (note: ALL packets, whether sent on the TCP or UDP channel, will have the
+ * sequence number.  Thus it's important that client & server agree on when
+ * to switch.  This was done to keep critical and non-critical data in sync.)
+ */
+
+/*
+ * the various pad members of the structures are used for explicit data
+ * alignment.  They do not contain any data.  All structures are aligned to 4
+ * bytes.  If your compiler forces 8 byte alignment, you will not be adhering
+ * to the netrek protocol.
+ */
+
+/* packets sent from xtrek server to remote client */
+#define SP_MESSAGE 	1
+#define SP_PLAYER_INFO 	2	/* general player info not elsewhere */
+#define SP_KILLS	3	/* # kills a player has */
+#define SP_PLAYER	4	/* x,y for player */
+#define SP_TORP_INFO	5	/* torp status */
+#define SP_TORP		6	/* torp location */
+#define SP_PHASER	7	/* phaser status and direction */
+#define SP_PLASMA_INFO	8	/* player login information */
+#define SP_PLASMA	9	/* like SP_TORP */
+#define SP_WARNING	10	/* like SP_MESG */
+#define SP_MOTD		11	/* line from .motd screen */
+#define SP_YOU		12	/* info on you? */
+#define SP_QUEUE	13	/* estimated loc in queue? */
+#define SP_STATUS	14	/* galaxy status numbers */
+#define SP_PLANET 	15	/* planet armies & facilities */
+#define SP_PICKOK	16	/* your team & ship was accepted */
+#define SP_LOGIN	17	/* login response */
+#define SP_FLAGS	18	/* give flags for a player */
+#define SP_MASK		19	/* tournament mode mask */
+#define SP_PSTATUS	20	/* give status for a player */
+#define SP_BADVERSION   21	/* invalid version number */
+#define SP_HOSTILE	22	/* hostility settings for a player */
+#define SP_STATS	23	/* a player's statistics */
+#define SP_PL_LOGIN	24	/* new player logs in */
+#define SP_RESERVED	25	/* for future use */
+#define SP_PLANET_LOC	26	/* planet name, x, y */
+
+#define SP_SCAN		27	/* scan packet */
+#define SP_UDP_REPLY	28	/* notify client of UDP status */
+#define SP_SEQUENCE	29	/* sequence # packet */
+#define SP_SC_SEQUENCE	30	/* this trans is semi-critical info */
+#define SP_RSA_KEY	31	/* RSA data packet */
+
+#define SP_MOTD_PIC     32	/* motd bitmap pictures */
+#define SP_STATS2	33	/* new stats packet */
+#define SP_STATUS2	34	/* new status packet */
+#define SP_PLANET2	35	/* new planet packet */
+#define SP_NEW_MOTD     36	/* New MOTD info notification uses */
+#define SP_THINGY	37	/* thingy location */
+#define SP_THINGY_INFO	38	/* thingy status */
+#define SP_SHIP_CAP	39	/* ship capabilities */
+
+#ifdef SHORT_PACKETS
+#define SP_S_REPLY      40	/* reply to send-short request */
+#define SP_S_MESSAGE    41	/* var. Message Packet */
+#define SP_S_WARNING    42	/* Warnings with 4  Bytes */
+#define SP_S_YOU        43	/* hostile,armies,whydead,etc .. */
+#define SP_S_YOU_SS     44	/* your ship status */
+#define SP_S_PLAYER     45	/* variable length player packet */
+#endif
+
+#define SP_PING         46	/* ping packet */
+
+#ifdef SHORT_PACKETS
+#define SP_S_TORP       47	/* variable length torp packet */
+#define SP_S_TORP_INFO  48	/* SP_S_TORP with TorpInfo */
+#define SP_S_8_TORP     49	/* optimized SP_S_TORP */
+#define SP_S_PLANET     50	/* see SP_PLANET */
+
+/* variable length packets */
+#define VPLAYER_SIZE    4
+#define SHORTVERSION    10	/* other number blocks, like UDP Version */
+#endif
+
+#define SP_GPARAM	51	/* game params packet */
+
+/*
+ * the following is a family of packets with the same type, but a
+ * discriminating subtype
+ */
+#define SP_PARADISE_EXT1	52
+#define SP_PE1_MISSING_BITMAP	0
+#define SP_PE1_NUM_MISSILES	1
+/* end of packet 52 subtypes */
+#define SP_TERRAIN2	53	/* GZipped terrain packet - 5/16/95 rpg */
+#define SP_TERRAIN_INFO2 54	/* header for terrain info */
+#ifdef FEATURE
+#define SP_FEATURE	60	/* type 60 is FEATURE packets */
+#endif
+
+
+/* packets sent from remote client to xtrek server */
+#define CP_MESSAGE      1	/* send a message */
+#define CP_SPEED	2	/* set speed */
+#define CP_DIRECTION	3	/* change direction */
+#define CP_PHASER	4	/* phaser in a direction */
+#define CP_PLASMA	5	/* plasma (in a direction) */
+#define CP_TORP		6	/* fire torp in a direction */
+#define CP_QUIT		7	/* self destruct */
+#define CP_LOGIN	8	/* log in (name, password) */
+#define CP_OUTFIT	9	/* outfit to new ship */
+#define CP_WAR		10	/* change war status */
+#define CP_PRACTR	11	/* create practice robot? */
+#define CP_SHIELD	12	/* raise/lower sheilds */
+#define CP_REPAIR	13	/* enter repair mode */
+#define CP_ORBIT	14	/* orbit planet/starbase */
+#define CP_PLANLOCK	15	/* lock on planet */
+#define CP_PLAYLOCK	16	/* lock on player */
+#define CP_BOMB		17	/* bomb a planet */
+#define CP_BEAM		18	/* beam armies up/down */
+#define CP_CLOAK	19	/* cloak on/off */
+#define CP_DET_TORPS	20	/* detonate enemy torps */
+#define CP_DET_MYTORP	21	/* detonate one of my torps */
+#define CP_COPILOT	22	/* toggle copilot mode */
+#define CP_REFIT	23	/* refit to different ship type */
+#define CP_TRACTOR	24	/* tractor on/off */
+#define CP_REPRESS	25	/* pressor on/off */
+#define CP_COUP		26	/* coup home planet */
+#define CP_SOCKET	27	/* new socket for reconnection */
+#define CP_OPTIONS	28	/* send my options to be saved */
+#define CP_BYE		29	/* I'm done! */
+#define CP_DOCKPERM	30	/* set docking permissions */
+#define CP_UPDATES	31	/* set number of usecs per update */
+#define CP_RESETSTATS	32	/* reset my stats packet */
+#define CP_RESERVED	33	/* for future use */
+
+#define CP_SCAN		34	/* ATM: request for player scan */
+
+#define CP_UDP_REQ	35	/* request UDP on/off */
+#define CP_SEQUENCE	36	/* sequence # packet */
+#define CP_RSA_KEY	37	/* request MOTD */
+#define CP_ASK_MOTD	38	/* request MOTD */
+
+#define CP_PING_RESPONSE 42	/* client response */
+
+#ifdef SHORT_PACKETS
+#define CP_S_REQ                43
+#define CP_S_THRS               44
+#define CP_S_MESSAGE    45	/* vari. Message Packet */
+#define CP_S_RESERVED       46
+#define CP_S_DUMMY      47
+#endif
+
+#ifdef FEATURE
+#define CP_FEATURE	60	/* Feature packets */
+#endif
+
+#define SOCKVERSION 	4
+#define UDPVERSION	10	/* changing this blocks other */
+/* versions */
+
+struct packet_handler
+{
+  void (*handler) ();
+};
+
+
+/*
+ * These are server --> client packets
+ */
+
+struct mesg_spacket
+{
+  INT8 type;			/* SP_MESSAGE */
+  CARD8 m_flags;
+  CARD8 m_recpt;
+  CARD8 m_from;
+  char mesg[80];
+};
+
+struct plyr_info_spacket
+{
+  INT8 type;			/* SP_PLAYER_INFO */
+  INT8 pnum;
+  INT8 shiptype;
+  INT8 team;
+};
+
+struct kills_spacket
+{
+  INT8 type;			/* SP_KILLS */
+  INT8 pnum;
+  INT8 pad1;
+  INT8 pad2;
+  CARD32 kills;			/* where 1234=12.34 kills and 0=0.00 kills */
+};
+
+struct player_spacket
+{
+  INT8 type;			/* SP_PLAYER */
+  INT8 pnum;
+  CARD8 dir;
+  INT8 speed;
+  INT32 x, y;
+};
+
+struct torp_info_spacket
+{
+  INT8 type;			/* SP_TORP_INFO */
+  INT8 war;
+  INT8 status;			/* TFREE, TDET, etc... */
+  INT8 pad1;			/* pad needed for cross cpu compatibility */
+  INT16 tnum;
+  INT16 pad2;
+};
+
+struct torp_spacket
+{
+  INT8 type;			/* SP_TORP */
+  CARD8 dir;
+  INT16 tnum;
+  INT32 x, y;
+};
+
+/*
+ * Shapes of thingys.  It would be best to add to the end of this list and
+ * try to coordinate your additions with other hackers.
+ */
+enum thingy_types
+{
+  SHP_BLANK, SHP_MISSILE, SHP_BOOM, SHP_TORP, SHP_PLASMA, SHP_MINE,
+  SHP_PBOOM, SHP_FIGHTER, SHP_WARP_BEACON
+};
+
+struct thingy_info_spacket
+{
+  INT8 type;			/* SP_THINGY_INFO */
+  INT8 war;
+  INT16 shape;			/* a thingy_types */
+  INT16 tnum;
+  INT16 owner;
+};
+
+struct thingy_spacket
+{
+  INT8 type;			/* SP_THINGY */
+  CARD8 dir;
+  INT16 tnum;
+  INT32 x, y;
+};
+
+struct phaser_spacket
+{
+  INT8 type;			/* SP_PHASER */
+  INT8 pnum;
+  INT8 status;			/* PH_HIT, etc... */
+  CARD8 dir;
+  INT32 x, y;
+  INT32 target;
+};
+
+struct plasma_info_spacket
+{
+  INT8 type;			/* SP_PLASMA_INFO */
+  INT8 war;
+  INT8 status;			/* TFREE, TDET, etc... */
+  INT8 pad1;			/* pad needed for cross cpu compatibility */
+  INT16 pnum;
+  INT16 pad2;
+};
+
+struct plasma_spacket
+{
+  INT8 type;			/* SP_PLASMA */
+  INT8 pad1;
+  INT16 pnum;
+  INT32 x, y;
+};
+
+struct warning_spacket
+{
+  INT8 type;			/* SP_WARNING */
+  INT8 pad1;
+  INT8 pad2;
+  INT8 pad3;
+  char mesg[80];
+};
+
+struct motd_spacket
+{
+  INT8 type;			/* SP_MOTD */
+  INT8 pad1;
+  INT8 pad2;
+  INT8 pad3;
+  char line[80];
+};
+
+struct you_spacket
+{
+  INT8 type;			/* SP_YOU */
+  INT8 pnum;			/* Guy needs to know this... */
+  INT8 hostile;
+  INT8 swar;
+  INT8 armies;
+  INT8 tractor;			/* ATM - visible tractor (was pad1) */
+  CARD8 pad2;
+  CARD8 pad3;
+  CARD32 flags;
+  INT32 damage;
+  INT32 shield;
+  INT32 fuel;
+  INT16 etemp;
+  INT16 wtemp;
+  INT16 whydead;
+  INT16 whodead;
+};
+
+struct queue_spacket
+{
+  INT8 type;			/* SP_QUEUE */
+  INT8 pad1;
+  INT16 pos;
+};
+
+struct status_spacket
+{
+  INT8 type;			/* SP_STATUS */
+  INT8 tourn;
+  INT8 pad1;
+  INT8 pad2;
+  CARD32 armsbomb;
+  CARD32 planets;
+  CARD32 kills;
+  CARD32 losses;
+  CARD32 time;
+  CARD32 timeprod;
+};
+
+struct planet_spacket
+{
+  INT8 type;			/* SP_PLANET */
+  INT8 pnum;
+  INT8 owner;
+  INT8 info;
+  INT16 flags;
+  INT16 pad2;
+  INT32 armies;
+};
+
+struct pickok_spacket
+{
+  INT8 type;			/* SP_PICKOK */
+  INT8 state;
+  INT8 pad2;
+  INT8 pad3;
+};
+
+struct login_spacket
+{
+  INT8 type;			/* SP_LOGIN */
+  INT8 accept;			/* 1/0 */
+  INT8 pad2;
+  INT8 pad3;
+  INT32 flags;
+  char keymap[96];
+};
+
+struct flags_spacket
+{
+  INT8 type;			/* SP_FLAGS */
+  INT8 pnum;			/* whose flags are they? */
+  INT8 tractor;			/* ATM - visible tractors */
+  INT8 pad2;
+  CARD32 flags;
+};
+
+struct mask_spacket
+{
+  INT8 type;			/* SP_MASK */
+  INT8 mask;
+  INT8 pad1;
+  INT8 pad2;
+};
+
+struct pstatus_spacket
+{
+  INT8 type;			/* SP_PSTATUS */
+  INT8 pnum;
+  INT8 status;
+  INT8 pad1;
+};
+
+struct badversion_spacket
+{
+  INT8 type;			/* SP_BADVERSION */
+  INT8 why;
+  INT8 pad2;
+  INT8 pad3;
+};
+
+struct hostile_spacket
+{
+  INT8 type;			/* SP_HOSTILE */
+  INT8 pnum;
+  INT8 war;
+  INT8 hostile;
+};
+
+struct stats_spacket
+{
+  INT8 type;			/* SP_STATS */
+  INT8 pnum;
+  INT8 pad1;
+  INT8 pad2;
+  INT32 tkills;			/* Tournament kills */
+  INT32 tlosses;		/* Tournament losses */
+  INT32 kills;			/* overall */
+  INT32 losses;			/* overall */
+  INT32 tticks;			/* ticks of tournament play time */
+  INT32 tplanets;		/* Tournament planets */
+  INT32 tarmies;		/* Tournament armies */
+  INT32 sbkills;		/* Starbase kills */
+  INT32 sblosses;		/* Starbase losses */
+  INT32 armies;			/* non-tourn armies */
+  INT32 planets;		/* non-tourn planets */
+  INT32 maxkills;		/* max kills as player * 100 */
+  INT32 sbmaxkills;		/* max kills as sb * 100 */
+};
+
+struct plyr_login_spacket
+{
+  INT8 type;			/* SP_PL_LOGIN */
+  INT8 pnum;
+  INT8 rank;
+  INT8 pad1;
+  INT8 name[16];
+  INT8 monitor[16];
+  INT8 login[16];
+};
+
+struct reserved_spacket
+{
+  INT8 type;			/* SP_RESERVED */
+  INT8 pad1;
+  INT8 pad2;
+  INT8 pad3;
+  INT8 data[16];
+};
+
+struct planet_loc_spacket
+{
+  INT8 type;			/* SP_PLANET_LOC */
+  INT8 pnum;
+  INT8 pad2;
+  INT8 pad3;
+  INT32 x;
+  INT32 y;
+  INT8 name[16];
+};
+
+struct scan_spacket
+{				/* ATM */
+  INT8 type;			/* SP_SCAN */
+  INT8 pnum;
+  INT8 success;
+  INT8 pad1;
+  INT32 p_fuel;
+  INT32 p_armies;
+  INT32 p_shield;
+  INT32 p_damage;
+  INT32 p_etemp;
+  INT32 p_wtemp;
+};
+
+struct udp_reply_spacket
+{				/* UDP */
+  INT8 type;			/* SP_UDP_REPLY */
+  INT8 reply;
+  INT8 pad1;
+  INT8 pad2;
+  INT32 port;
+};
+
+struct sequence_spacket
+{				/* UDP */
+  INT8 type;			/* SP_SEQUENCE */
+  INT8 pad1;
+  CARD16 sequence;
+};
+struct sc_sequence_spacket
+{				/* UDP */
+  INT8 type;			/* SP_CP_SEQUENCE */
+  INT8 pad1;
+  CARD16 sequence;
+};
+
+/*
+ * Game configuration. KAO 1/23/93
+ */
+
+struct ship_cap_spacket
+{				/* Server configuration of client */
+  INT8 type;			/* screw motd method */
+  INT8 operation;		/* 0 = add/change a ship, 1 = remove a ship */
+  INT16 s_type;			/* SP_SHIP_CAP */
+  INT16 s_torpspeed;
+  INT16 s_phaserrange;
+  INT32 s_maxspeed;
+  INT32 s_maxfuel;
+  INT32 s_maxshield;
+  INT32 s_maxdamage;
+  INT32 s_maxwpntemp;
+  INT32 s_maxegntemp;
+  INT16 s_width;
+  INT16 s_height;
+  INT16 s_maxarmies;
+  INT8 s_letter;
+  INT8 pad2;
+  INT8 s_name[16];
+  INT8 s_desig1;
+  INT8 s_desig2;
+  INT16 s_bitmap;
+};
+
+struct motd_pic_spacket
+{
+  INT8 type;			/* SP_MOTD_PIC */
+  INT8 pad1;
+  INT16 x, y, page;
+  INT16 width, height;
+  INT8 bits[1016];
+};
+
+
+/* This is used to send paradise style stats */
+struct stats_spacket2
+{
+  INT8 type;			/* SP_STATS2 */
+  INT8 pnum;
+  INT8 pad1;
+  INT8 pad2;
+
+  INT32 genocides;		/* number of genocides participated in */
+  INT32 maxkills;		/* max kills ever * 100  */
+  INT32 di;			/* destruction inflicted for all time * 100 */
+  INT32 kills;			/* Kills in tournament play */
+  INT32 losses;			/* Losses in tournament play */
+  INT32 armsbomb;		/* Tournament armies bombed */
+  INT32 resbomb;		/* resources bombed off */
+  INT32 dooshes;		/* armies killed while being carried */
+  INT32 planets;		/* Tournament planets conquered */
+  INT32 tticks;			/* Tournament ticks */
+  /* SB/WB/JS stats are entirely separate */
+  INT32 sbkills;		/* Kills as starbase */
+  INT32 sblosses;		/* Losses as starbase */
+  INT32 sbticks;		/* Time as starbase */
+  INT32 sbmaxkills;		/* Max kills as starbase * 100 */
+  INT32 wbkills;		/* Kills as warbase */
+  INT32 wblosses;		/* Losses as warbase */
+  INT32 wbticks;		/* Time as warbase */
+  INT32 wbmaxkills;		/* Max kills as warbase * 100 */
+  INT32 jsplanets;		/* planets assisted with in JS */
+  INT32 jsticks;		/* ticks played as a JS */
+  INT32 rank;			/* Ranking of the player */
+  INT32 royal;			/* royaly, specialty, rank */
+};
+
+/* status info for paradise stats */
+struct status_spacket2
+{
+  INT8 type;			/* SP_STATUS2 */
+  INT8 tourn;
+  INT8 pad1;
+  INT8 pad2;
+  CARD32 dooshes;		/* total number of armies dooshed */
+  CARD32 armsbomb;		/* all t-mode armies bombed */
+  CARD32 resbomb;		/* resources bombed */
+  CARD32 planets;		/* all t-mode planets taken */
+  CARD32 kills;			/* all t-mode kills made */
+  CARD32 losses;		/* all t-mode losses */
+  CARD32 sbkills;		/* total kills in SB's */
+  CARD32 sblosses;		/* total losses in Sb's */
+  CARD32 sbtime;		/* total time in SB's */
+  CARD32 wbkills;		/* kills in warbases */
+  CARD32 wblosses;		/* losses in warbases */
+  CARD32 wbtime;		/* total time played in wb's */
+  CARD32 jsplanets;		/* total planets taken by jump ships */
+  CARD32 jstime;		/* total time in a jump ship */
+  CARD32 time;			/* t mode time in this game */
+  CARD32 timeprod;		/* t-mode ship ticks--sort of like */
+};
+
+
+/* planet info for a paradise planet */
+struct planet_spacket2
+{
+  INT8 type;			/* SP_PLANET2 */
+  INT8 pnum;			/* planet number */
+  INT8 owner;			/* owner of the planet */
+  INT8 info;			/* who has touched planet */
+  INT32 flags;			/* planet's flags */
+  INT32 timestamp;		/* timestamp for info on planet */
+  INT32 armies;			/* armies on the planet */
+};
+
+/* terrain info for Paradise terrain */
+/* 5/16/95 rpg */
+
+struct terrain_info_packet2
+{
+  CARD8 type;			/* SP_TERRAIN_INFO2 */
+  CARD8 pad;
+  CARD16 pad2;
+  CARD16 xdim;			/* x dimension of grid */
+  CARD16 ydim;			/* y dimension of grid */
+};
+
+struct terrain_packet2
+{
+  CARD8 type;			/* SP_TERRAIN2 */
+  CARD8 sequence;		/* Sequence number - may need multiple
+				 * packets */
+  CARD8 total_pkts;		/* since terrain is gzipped, we need length
+				 * (may have) */
+  CARD8 length;			/* multiple packets */
+  CARD8 terrain_type[NTERRAIN];	/* send up to 128 gzipped bytes at once */
+  /* CARD16   terrain_alt1[128]; *//* Note - these values should be *changed* */
+  /* CARD16   terrain_atl2[128]; *//* depending on if alt1/alt2 are used. */
+};
+
+struct obvious_packet
+{
+  INT8 type;			/* SP_NEW_MOTD */
+  INT8 pad1;			/* CP_ASK_MOTD */
+};
+
+struct rsa_key_spacket
+{
+  INT8 type;			/* SP_RSA_KEY */
+  INT8 pad1;
+  INT8 pad2;
+  INT8 pad3;
+  CARD8 data[KEY_SIZE];
+};
+
+
+struct ping_spacket
+{
+  INT8 type;			/* SP_PING */
+  CARD8 number;			/* id (ok to wrap) */
+  CARD16 lag;			/* delay of last ping in ms */
+
+  CARD8 tloss_sc;		/* total loss server-client 0-100% */
+  CARD8 tloss_cs;		/* total loss client-server 0-100% */
+
+  CARD8 iloss_sc;		/* inc. loss server-client 0-100% */
+  CARD8 iloss_cs;		/* inc. loss client-server 0-100% */
+};
+
+struct paradiseext1_spacket
+{
+  INT8 type;
+  CARD8 subtype;
+  INT16 pad;
+};
+
+struct pe1_missing_bitmap_spacket
+{
+  INT8 type;
+  CARD8 subtype;
+
+  INT16 page;
+
+  INT16 x, y;
+  INT16 width, height;
+};
+
+struct pe1_num_missiles_spacket
+{
+  INT8 type;			/* SP_PARADISE_EXT1 */
+  CARD8 subtype;		/* SP_PE1_NUM_MISSILES */
+
+  INT16 num;			/* number of missiles */
+};
+
+/*
+ * These are the client --> server packets
+ */
+
+struct mesg_cpacket
+{
+  INT8 type;			/* CP_MESSAGE */
+  INT8 group;
+  INT8 indiv;
+  INT8 pad1;
+  INT8 mesg[80];
+};
+
+struct speed_cpacket
+{
+  INT8 type;			/* CP_SPEED */
+  INT8 speed;
+  INT8 pad1;
+  INT8 pad2;
+};
+
+struct dir_cpacket
+{
+  INT8 type;			/* CP_DIRECTION */
+  CARD8 dir;
+  INT8 pad1;
+  INT8 pad2;
+};
+
+struct phaser_cpacket
+{
+  INT8 type;			/* CP_PHASER */
+  CARD8 dir;
+  INT8 pad1;
+  INT8 pad2;
+};
+
+struct plasma_cpacket
+{
+  INT8 type;			/* CP_PLASMA */
+  CARD8 dir;
+  INT8 pad1;
+  INT8 pad2;
+};
+
+struct torp_cpacket
+{
+  INT8 type;			/* CP_TORP */
+  CARD8 dir;			/* direction to fire torp */
+  INT8 pad1;
+  INT8 pad2;
+};
+
+struct quit_cpacket
+{
+  INT8 type;			/* CP_QUIT */
+  INT8 pad1;
+  INT8 pad2;
+  INT8 pad3;
+};
+
+struct login_cpacket
+{
+  INT8 type;			/* CP_LOGIN */
+  INT8 query;
+  INT8 pad2;
+  INT8 pad3;
+  INT8 name[16];
+  INT8 password[16];
+  INT8 login[16];
+};
+
+struct outfit_cpacket
+{
+  INT8 type;			/* CP_OUTFIT */
+  INT8 team;
+  INT8 ship;
+  INT8 pad1;
+};
+
+struct war_cpacket
+{
+  INT8 type;			/* CP_WAR */
+  INT8 newmask;
+  INT8 pad1;
+  INT8 pad2;
+};
+
+struct practr_cpacket
+{
+  INT8 type;			/* CP_PRACTR */
+  INT8 pad1;
+  INT8 pad2;
+  INT8 pad3;
+};
+
+struct shield_cpacket
+{
+  INT8 type;			/* CP_SHIELD */
+  INT8 state;			/* up/down */
+  INT8 pad1;
+  INT8 pad2;
+};
+
+struct repair_cpacket
+{
+  INT8 type;			/* CP_REPAIR */
+  INT8 state;			/* on/off */
+  INT8 pad1;
+  INT8 pad2;
+};
+
+struct orbit_cpacket
+{
+  INT8 type;			/* CP_ORBIT */
+  INT8 state;			/* on/off */
+  INT8 pad1;
+  INT8 pad2;
+};
+
+struct planlock_cpacket
+{
+  INT8 type;			/* CP_PLANLOCK */
+  INT8 pnum;
+  INT8 pad1;
+  INT8 pad2;
+};
+
+struct playlock_cpacket
+{
+  INT8 type;			/* CP_PLAYLOCK */
+  INT8 pnum;
+  INT8 pad1;
+  INT8 pad2;
+};
+
+struct bomb_cpacket
+{
+  INT8 type;			/* CP_BOMB */
+  INT8 state;
+  INT8 pad1;
+  INT8 pad2;
+};
+
+struct beam_cpacket
+{
+  INT8 type;			/* CP_BEAM */
+  INT8 state;
+  INT8 pad1;
+  INT8 pad2;
+};
+
+struct cloak_cpacket
+{
+  INT8 type;			/* CP_CLOAK */
+  INT8 state;
+  INT8 pad1;
+  INT8 pad2;
+};
+
+struct det_torps_cpacket
+{
+  INT8 type;			/* CP_DET_TORPS */
+  INT8 pad1;
+  INT8 pad2;
+  INT8 pad3;
+};
+
+struct det_mytorp_cpacket
+{
+  INT8 type;			/* CP_DET_MYTORP */
+  INT8 pad1;
+  INT16 tnum;
+};
+
+struct copilot_cpacket
+{
+  INT8 type;			/* CP_COPLIOT */
+  INT8 state;
+  INT8 pad1;
+  INT8 pad2;
+};
+
+struct refit_cpacket
+{
+  INT8 type;			/* CP_REFIT */
+  INT8 ship;
+  INT8 pad1;
+  INT8 pad2;
+};
+
+struct tractor_cpacket
+{
+  INT8 type;			/* CP_TRACTOR */
+  INT8 state;
+  INT8 pnum;
+  INT8 pad2;
+};
+
+struct repress_cpacket
+{
+  INT8 type;			/* CP_REPRESS */
+  INT8 state;
+  INT8 pnum;
+  INT8 pad2;
+};
+
+struct coup_cpacket
+{
+  INT8 type;			/* CP_COUP */
+  INT8 pad1;
+  INT8 pad2;
+  INT8 pad3;
+};
+
+struct socket_cpacket
+{
+  INT8 type;			/* CP_SOCKET */
+  INT8 version;
+  INT8 udp_version;		/* was pad2 */
+  INT8 pad3;
+  CARD32 socket;
+};
+
+struct options_cpacket
+{
+  INT8 type;			/* CP_OPTIONS */
+  INT8 pad1;
+  INT8 pad2;
+  INT8 pad3;
+  CARD32 flags;
+  INT8 keymap[96];
+};
+
+struct bye_cpacket
+{
+  INT8 type;			/* CP_BYE */
+  INT8 pad1;
+  INT8 pad2;
+  INT8 pad3;
+};
+
+struct dockperm_cpacket
+{
+  INT8 type;			/* CP_DOCKPERM */
+  INT8 state;
+  INT8 pad2;
+  INT8 pad3;
+};
+
+struct updates_cpacket
+{
+  INT8 type;			/* CP_UPDATES */
+  INT8 pad1;
+  INT8 pad2;
+  INT8 pad3;
+  CARD32 usecs;
+};
+
+struct resetstats_cpacket
+{
+  INT8 type;			/* CP_RESETSTATS */
+  INT8 verify;			/* 'Y' - just to make sure he meant it */
+  INT8 pad2;
+  INT8 pad3;
+};
+
+struct reserved_cpacket
+{
+  INT8 type;			/* CP_RESERVED */
+  INT8 pad1;
+  INT8 pad2;
+  INT8 pad3;
+  INT8 data[16];
+  INT8 resp[16];
+};
+
+struct scan_cpacket
+{				/* ATM */
+  INT8 type;			/* CP_SCAN */
+  INT8 pnum;
+  INT8 pad1;
+  INT8 pad2;
+};
+
+struct udp_req_cpacket
+{				/* UDP */
+  INT8 type;			/* CP_UDP_REQ */
+  INT8 request;
+  INT8 connmode;		/* respond with port # or just send UDP
+				 * packet? */
+  INT8 pad2;
+  INT32 port;			/* compensate for hosed recvfrom() */
+};
+
+struct sequence_cpacket
+{				/* UDP */
+  INT8 type;			/* CP_SEQUENCE */
+  INT8 pad1;
+  CARD16 sequence;
+};
+
+struct rsa_key_cpacket
+{
+  INT8 type;			/* CP_RSA_KEY */
+  INT8 pad1;
+  INT8 pad2;
+  INT8 pad3;
+  CARD8 global[KEY_SIZE];
+  CARD8 public[KEY_SIZE];
+  CARD8 resp[KEY_SIZE];
+};
+
+/* the CP_ASK_MOTD packet is the same as temp_spacket */
+
+struct ping_cpacket
+{
+  INT8 type;			/* CP_PING_RESPONSE */
+  CARD8 number;			/* id */
+  INT8 pingme;			/* if client wants server to ping */
+  INT8 pad1;
+
+  INT32 cp_sent;		/* # packets sent to server */
+  INT32 cp_recv;		/* # packets recv from server */
+};
+
+#ifdef FEATURE
+struct feature_cpacket
+{
+  char type;
+  char feature_type;
+  char arg1, arg2;
+  int value;
+  char name[80];
+};
+
+struct feature_spacket
+{
+  char type;
+  char feature_type;
+  char arg1, arg2;
+  int value;
+  char name[80];
+};
+#endif
+
+/*
+ * short stuff
+ */
+
+#ifdef SHORT_PACKETS
+struct shortreq_cpacket
+{				/* CP_S_REQ */
+  INT8 type;
+  INT8 req;
+  INT8 version;
+  INT8 pad2;
+};
+
+struct threshold_cpacket
+{				/* CP_S_THRS */
+  INT8 type;
+  INT8 pad1;
+  CARD16 thresh;
+};
+
+struct shortreply_spacket
+{				/* SP_S_REPLY */
+  INT8 type;
+  INT8 repl;
+  CARD16 winside;
+  INT32 gwidth;
+};
+
+struct youshort_spacket
+{				/* SP_S_YOU */
+  INT8 type;
+
+  INT8 pnum;
+  INT8 hostile;
+  INT8 swar;
+
+  INT8 armies;
+  INT8 whydead;
+  INT8 whodead;
+
+  INT8 pad1;
+
+  CARD32 flags;
+};
+
+struct youss_spacket
+{				/* SP_S_YOU_SS */
+  INT8 type;
+  INT8 pad1;
+
+  CARD16 damage;
+  CARD16 shield;
+  CARD16 fuel;
+  CARD16 etemp;
+  CARD16 wtemp;
+};
+
+#define VPLANET_SIZE 6
+
+struct planet_s_spacket
+{				/* body of SP_S_PLANET  */
+  INT8 pnum;
+  INT8 owner;
+  INT8 info;
+  CARD8 armies;			/* more than 255 Armies ? ...  */
+  INT16 flags;
+};
+struct warning_s_spacket
+{				/* SP_S_WARNING */
+  INT8 type;
+  CARD8 whichmessage;
+  INT8 argument, argument2;	/* for phaser  etc ... */
+};
+
+struct player_s_spacket
+{
+  INT8 type;			/* SP_S_PLAYER Header */
+  INT8 packets;			/* How many player-packets are in this packet
+				 * ( only the first 6 bits are relevant ) */
+  CARD8 dir;
+  INT8 speed;
+  INT32 x, y;			/* To get the absolute Position */
+};
+
+/*
+ * The format of the body: struct player_s_body_spacket {	Body of new
+ * Player Packet CARD8 pnum;	 0-4 = pnum, 5 local or galactic, 6 = 9.
+ * x-bit, 7 9. y-bit CARD8 speeddir;	 0-3 = speed , 4-7 direction of ship
+ * CARD8 x;	 low 8 bits from X-Pixelcoordinate CARD8 y;	 low 8 bits
+ * from Y-Pixelcoordinate };
+ */
+
+struct torp_s_spacket
+{
+  INT8 type;			/* SP_S_TORP */
+  CARD8 bitset;			/* bit=1 that torp is in packet */
+  CARD8 whichtorps;		/* Torpnumber of first torp / 8 */
+  CARD8 data[21];		/* For every torp 2*9 bit coordinates */
+};
+
+struct mesg_s_spacket
+{
+  INT8 type;			/* SP_S_MESSAGE */
+  CARD8 m_flags;
+  CARD8 m_recpt;
+  CARD8 m_from;
+  CARD8 length;			/* Length of whole packet */
+  INT8 mesg;
+  INT8 pad2;
+  INT8 pad3;
+  INT8 pad[76];
+};
+
+struct mesg_s_cpacket
+{
+  INT8 type;			/* CP_S__MESSAGE */
+  INT8 group;
+  INT8 indiv;
+  INT8 length;			/* Size of whole packet   */
+  INT8 mesg[80];
+};
+
+#endif
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/parsexbm.c	Sat Dec 06 04:37:03 1997 +0000
@@ -0,0 +1,159 @@
+/*--------------------------------------------------------------------------
+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 <stdlib.h>
+#include <string.h>
+
+#define pm_error(str) {\
+fprintf(stderr, "Error in ParseXbmFile(): %s\n", str);\
+if(*dataP) { free(*dataP); *dataP = 0; }\
+return -1; }
+
+/*
+ * most of the following function came from xbmtopbm.c in the PBMPLUS library
+ */
+
+#define MAX_LINE 500
+
+int
+ParseXbmFile(stream, widthP, heightP, dataP)
+  FILE *stream;
+  int *widthP;
+  int *heightP;
+  char **dataP;
+{
+  char line[MAX_LINE], name_and_type[MAX_LINE];
+  char *ptr;
+  char *t;
+  int raster_length, v;
+  register int bytes, bytes_per_line;
+  register int c1, c2, value1, value2;
+  int hex_table[256];
+
+  *widthP = *heightP = -1;
+  *dataP = 0;
+
+  for (;;)
+  {
+    if (fgets(line, MAX_LINE, stream) == NULL)
+      pm_error("EOF / read error");
+    if (strlen(line) == MAX_LINE - 1)
+      pm_error("line too long");
+
+    if (sscanf(line, "#define %s %d", name_and_type, &v) == 2)
+    {
+      if ((t = strrchr(name_and_type, '_')) == NULL)
+	t = name_and_type;
+      else
+	++t;
+      if (!strcmp("width", t))
+	*widthP = v;
+      else if (!strcmp("height", t))
+	*heightP = v;
+      continue;
+    }
+
+    if (sscanf(line, "static char %s = {", name_and_type) == 1 ||
+	sscanf(line, "static unsigned char %s = {", name_and_type) == 1)
+      break;
+  }
+
+  if (*widthP == -1)
+    pm_error("invalid width");
+  if (*heightP == -1)
+    pm_error("invalid height");
+
+  bytes_per_line = (*widthP + 7) / 8;
+
+  raster_length = bytes_per_line * *heightP;
+  *dataP = (char *) malloc(raster_length);
+  if (*dataP == (char *) 0)
+    pm_error("out of memory");
+
+  /* Initialize hex_table. */
+  for (c1 = 0; c1 < 256; ++c1)
+    hex_table[c1] = 256;
+
+  hex_table['0'] = 0;
+  hex_table['1'] = 1;
+  hex_table['2'] = 2;
+  hex_table['3'] = 3;
+  hex_table['4'] = 4;
+  hex_table['5'] = 5;
+  hex_table['6'] = 6;
+  hex_table['7'] = 7;
+  hex_table['8'] = 8;
+  hex_table['9'] = 9;
+  hex_table['A'] = 10;
+  hex_table['B'] = 11;
+  hex_table['C'] = 12;
+  hex_table['D'] = 13;
+  hex_table['E'] = 14;
+  hex_table['F'] = 15;
+  hex_table['a'] = 10;
+  hex_table['b'] = 11;
+  hex_table['c'] = 12;
+  hex_table['d'] = 13;
+  hex_table['e'] = 14;
+  hex_table['f'] = 15;
+
+  for (bytes = 0, ptr = *dataP; bytes < raster_length; ++bytes)
+  {
+    /*
+     * Skip until digit is found.
+     */
+    for (;;)
+    {
+      c1 = getc(stream);
+      if (c1 == EOF)
+	pm_error("EOF / read error");
+      value1 = hex_table[c1];
+      if (value1 != 256)
+	break;
+    }
+    /*
+     * Loop on digits.
+     */
+    for (;;)
+    {
+      c2 = getc(stream);
+      if (c2 == EOF)
+	pm_error("EOF / read error");
+      value2 = hex_table[c2];
+      if (value2 != 256)
+      {
+	value1 = (value1 << 4) | value2;
+	if (value1 >= 256)
+	  pm_error("syntax error");
+      }
+      else if (c2 == 'x' || c2 == 'X')
+      {
+	if (value1 == 0)
+	  continue;
+	else
+	  pm_error("syntax error");
+      }
+      else
+	break;
+    }
+    *ptr++ = (char) (value1 ^ 0xFF);
+  }
+  return (raster_length);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/path.c	Sat Dec 06 04:37:03 1997 +0000
@@ -0,0 +1,77 @@
+/*--------------------------------------------------------------------------
+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 <string.h>
+#include <stdlib.h>
+
+/*
+ * This is the default path, you don't have to change this as long as you set
+ * the NETREKDIR env
+ */
+char netrekpath[256] = "/local/lib/paradise";
+
+
+static char buf[512];
+static int initted = 0;
+
+char *
+build_path(suffix)
+  char *suffix;
+{
+  int len;
+  if (!initted)
+  {
+    char *ptr;
+    initted = 1;
+    ptr = (char *) getenv("NETREKDIR");
+    if (ptr == NULL)
+    {
+      fprintf(stderr, "Warning, no NETREKDIR envariable.  Using default of %s\n", netrekpath);
+    }
+    else
+    {
+      strncpy(netrekpath, ptr, 255);
+      netrekpath[255] = '\0';
+    }
+    len = strlen(netrekpath);
+    if (len > 230)
+    {
+      fprintf(stderr, "NETREKDIR enviroment variable too long.\n");
+      fprintf(stderr, "Please change it.\n");
+      exit(1);
+    }
+    if (netrekpath[len - 1] != '/')
+    {
+      netrekpath[len] = '/';
+      netrekpath[len + 1] = '\0';
+    }
+  }
+  if (*suffix == '/')
+  {				/* absolute path... don't prepend anything */
+    strcpy(buf, suffix);
+  }
+  else
+  {
+    strcpy(buf, netrekpath);
+    strcat(buf, suffix);
+  }
+
+  return buf;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/path.h	Sat Dec 06 04:37:03 1997 +0000
@@ -0,0 +1,19 @@
+/*--------------------------------------------------------------------------
+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 *build_path();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/phaser.c	Sat Dec 06 04:37:03 1997 +0000
@@ -0,0 +1,247 @@
+/*--------------------------------------------------------------------------
+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 "defs.h"
+#include "struct.h"
+#include "data.h"
+#include "weapons.h"
+#include "shmem.h"
+
+/*-----------------------------VISIBLE FUNCTIONS---------------------------*/
+
+/*----------------------------------PHASER---------------------------------*/
+/*
+ * This function shoots a phaser for a player.  Various conditions are
+ * checked to see if the phaser should be allowed to fire.  If the player can
+ * fire then, a player is found in the direction the phaser was fired.
+ */
+
+
+extern int angdist();
+
+void
+phaser(course)
+  unsigned char course;
+{
+  int i;			/* looping var */
+  struct player *j, *target = 0;/* to hold player found */
+  struct plasmatorp *k, *target2 = 0;	/* to hold plasma torp found */
+  struct missile *d, *target3 = 0;
+  struct phaser *mine;		/* to pnt to player's phaser */
+  int whichtarget;		/* to hold type of target */
+  int target_x = 0, target_y = 0;	/* target's x and y coords */
+  unsigned char dir;		/* to get direction of phasr */
+  int range, trange;		/* range of target */
+  int maxangle;			/* potential target range */
+  int myphrange;		/* angle to hit potentl targ */
+  char buf[80];			/* to sprintf warnings into */
+
+  mine = &phasers[me->p_no];	/* get phaser struct */
+  if (!(myship->s_nflags & SFNHASPHASERS))
+  {				/* do we have phasers? */
+    warning("Weapons Officer:  This ship is not armed with phasers, captain!");
+    return;
+  }
+  if (mine->ph_status != PHFREE)
+  {				/* is phaser currently being */
+    warning("Phasers have not recharged");	/* fired */
+    return;
+  }
+  if (me->p_fuel < myship->s_phaser.cost)
+  {				/* do we have enough fuel */
+    warning("Not enough fuel for phaser");
+    return;
+  }
+  if (me->p_flags & PFREPAIR)
+  {				/* cannot fire while in */
+    warning("Can't fire while repairing");	/* repair mode */
+    return;
+  }
+  if (me->p_flags & PFWEP)
+  {				/* cannot fire while weapon */
+    warning("Weapons overheated");	/* temped */
+    return;
+  }
+  if ((me->p_cloakphase) && (me->p_ship.s_type != ATT))
+  {
+    warning("Cannot fire while cloaked");	/* cannot fire while cloaked */
+    return;
+  }
+  if (!check_fire_warp()
+      || !check_fire_warpprep()
+      || !check_fire_docked())
+    return;
+
+  me->p_fuel -= myship->s_phaser.cost;	/* subtract off fuel cost */
+  me->p_wtemp += myship->s_phaser.wtemp;	/* add to w temp */
+  mine->ph_dir = course;	/* get direction of phaser */
+  whichtarget = 0;		/* no target fount yet */
+  range = 1000000;		/* Sufficiently big. */
+  /* check the players */
+  for (i = 0, j = &players[i]; i < MAXPLAYER; i++, j++)
+  {				/* loop all players */
+    if (((j->p_status != PALIVE)
+#ifdef PFBIRD
+	 && !(j->p_flags & PFBIRD)
+#endif
+	 ) || (j == me))	/* only check alive players */
+      continue;
+    if ((!((j->p_swar | j->p_hostile) & me->p_team)) &&
+	(!((me->p_swar | me->p_hostile) & j->p_team)) &&
+#ifdef PFBIRD
+	!(j->p_flags & PFBIRD)
+#endif
+      )
+      continue;			/* only check at war with */
+    dir = (unsigned char) (int) (atan2((double) (j->p_x - me->p_x),
+			     (double) (me->p_y - j->p_y)) / 3.14159 * 128.);
+    /* get range of target */
+    trange = ihypot(j->p_x - me->p_x, j->p_y - me->p_y);
+    if (trange == 0)		/* don't want zero in atan */
+      trange = 1;
+    maxangle = atan((float) EXPDIST / trange) / 3.14159 * 128.0;
+    if (angdist(dir, course) <= maxangle)
+    {				/* if angle within tolerance */
+      if (range > trange)
+      {				/* then check to see if */
+	whichtarget = 1;	/* this is the closest target */
+	target = j;		/* found yet */
+	range = trange;		/* record if it is */
+      }
+    }
+  }				/* check the plasmas */
+  for (i = 0, k = &plasmatorps[i]; i < MAXPLASMA * MAXPLAYER; i++, k++)
+  {
+    if ((k->pt_status != PTMOVE) || (k->pt_owner == me->p_no))
+      continue;			/* only check live plasmas */
+    if ((!(k->pt_war & me->p_team)) &&	/* and unfriendly ones */
+	(!((me->p_swar | me->p_hostile) & k->pt_team)))
+      continue;
+    dir = (unsigned char) (int) (atan2((double) (k->pt_x - me->p_x),
+			    (double) (me->p_y - k->pt_y)) / 3.14159 * 128.);	/* find direction */
+    trange = ihypot(k->pt_x - me->p_x, k->pt_y - me->p_y);
+    if (trange == 0)		/* no zeroes in math funcs */
+      trange = 1;
+    maxangle = atan((float) EXPDIST / 4 / trange) / 3.14159 * 128.0;
+    if (angdist(dir, course) <= (maxangle + 1))
+    {				/* if we can hit it */
+      if (range > trange)
+      {				/* then check to see if this */
+	target_x = k->pt_x;	/* is the closest plasma */
+	target_y = k->pt_y;	/* found yet */
+	whichtarget = 2;	/* and record it if it is */
+	target2 = k;
+	range = trange;
+      }
+    }
+  }
+  /* check the fighters */
+  for (i = 0, d = &missiles[i]; i < NPTHINGIES * MAXPLAYER; i++, d++)
+  {
+    if ((d->ms_owner == me->p_no) || (d->ms_type != FIGHTERTHINGY))
+      continue;			/* only check live fighters */
+    if ((!(d->ms_war & me->p_team)) &&	/* and unfriendly ones */
+	(!((me->p_swar | me->p_hostile) & d->ms_team)))
+      continue;
+    dir = (unsigned char) (atan2((double) (d->ms_x - me->p_x),
+				 (double) (me->p_y - d->ms_y))
+			   / 3.14159 * 128.);	/* find direction */
+    trange = ihypot(d->ms_x - me->p_x, d->ms_y - me->p_y);
+    if (trange == 0)		/* no zeroes in math funcs */
+      trange = 1;
+    maxangle = atan((float) EXPDIST / 8 / trange) / 3.14159 * 128.0;
+    if (angdist(dir, course) <= (maxangle + 1))
+    {				/* if we can hit it */
+      if (range > trange)
+      {				/* then check to see if this */
+	target_x = d->ms_x;	/* is the closest fighter */
+	target_y = d->ms_y;	/* found yet */
+	whichtarget = 3;	/* and record it if it is */
+	target3 = d;
+	range = trange;
+      }
+    }
+  }
+
+  mine->ph_fuse = me->p_ship.s_phaser.fuse;	/* set phaser fuse */
+  myphrange = me->p_ship.s_phaser.speed;	/* phaser range */
+  if ((whichtarget == 0) ||	/* if no target found or all */
+      (range > myphrange))
+  {				/* targets too long */
+    mine->ph_status = PHMISS;	/* then we missed */
+    warning("Phaser missed!!!");
+  }
+  else if (whichtarget == 2)
+  {				/* if we hit a plasma then */
+    warning("You destroyed the plasma torpedo!");
+    mine->ph_x = target_x;	/* the set point to shoot at */
+    mine->ph_y = target_y;
+    mine->ph_status = PHHIT2;	/* we hit a plasma */
+    target2->pt_status = PTEXPLODE;	/* Plasmas hurt everyone */
+    target2->pt_whodet = me->p_no;
+  }
+  else if (whichtarget == 3)
+  {				/* if we hit a fighter then */
+    warning("You shot a fighter!");
+    mine->ph_x = target_x;	/* the set point to shoot at */
+    mine->ph_y = target_y;
+    mine->ph_status = PHHIT2;	/* we hit the fighter */
+    target3->ms_status = TDET;	/* det the fighter */
+    target3->ms_whodet = me->p_no;
+  }
+  else
+  {				/* else if we hit player */
+    mine->ph_target = target->p_no;	/* set the player number */
+    mine->ph_damage = me->p_ship.s_phaser.damage *	/* get damage */
+      (1.0 - (range / (float) myphrange));
+    if (mine->ph_damage < 0)	/* if damage inflicted */
+      mine->ph_damage = -mine->ph_damage;	/* set the phaser damage */
+    mine->ph_status = PHHIT;	/* status is a hit */
+
+#ifdef PFBIRD
+    if (target->p_flags & PFBIRD)
+    {
+      /* change to PHHIT2 so phaser won't follow bird */
+      mine->ph_status = PHHIT2;
+      mine->ph_x = target->p_x;
+      mine->ph_y = target->p_y;
+      /* xx: slight misuse of fields here */
+      target->p_damage = mine->ph_damage;
+      target->p_whodead = me->p_no;
+
+      (void) sprintf(buf, "\"AAWWK!\"");
+    }
+#endif
+
+    (void) sprintf(buf, "Phaser burst hit %s for %d points",
+		   target->p_name, mine->ph_damage);
+    warning(buf);
+  }
+}
+
+/*------------------------------------------------------------------------*/
+
+
+
+
+
+/*-------END OF FILE-------*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ping.c	Sat Dec 06 04:37:03 1997 +0000
@@ -0,0 +1,374 @@
+/*--------------------------------------------------------------------------
+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 <sys/types.h>
+#include <sys/time.h>
+#include <math.h>
+#include <errno.h>
+#include <netinet/in.h>
+#include "defs.h"
+#include "struct.h"
+#include "data.h"
+#include "packets.h"
+#include "shmem.h"
+
+#define PING_DEBUG				0	/* debugging */
+
+/* special fields in stats record for rountrip delay and packet loss */
+#define INL_STATS
+
+
+static unsigned char ping_id;	/* wraparound expected */
+static int ping_lag;		/* ping roundtrip delay */
+
+static int tloss_sc,		/* total packet loss s-c */
+    tloss_cs,			/* total packet loss c-s */
+    iloss_sc,			/* inc. packet loss s-c */
+    iloss_cs;			/* inc. packet loss c-s */
+
+/*
+ * This structure allows us to send several pings before any response is
+ * received without losing information -- as would be the case for roundtrip
+ * times equal to or larger then the ping interval times. HASHSIZE * ping
+ * interval must be greater then the largest expected roundtrip time.
+ */
+
+#define HASHSIZE		32
+#define PITH(i)			(((int)i) & (HASHSIZE-1))
+
+static
+struct
+{
+  long time;
+  long packets_sent_at_ping;
+}   ping_sent[HASHSIZE];
+
+
+void calc_loss();
+void update_lag_stats();
+void update_loss_stats();
+int mstime();
+int msetime();
+
+/*
+ * response from client
+ */
+
+void
+pingResponse(packet)
+  struct ping_cpacket *packet;
+{
+  register i;
+  static int last_num;
+
+  if (!ping || packet->pingme != 1)
+    return;			/* oops, garbage */
+
+  ping_ghostbust = 0;		/* don't ghostbust, client is alive */
+
+  /* throw out out-of-order packets */
+  i = uchar_diff((int) packet->number, last_num);
+  if (i < 0)
+  {
+#if PING_DEBUG >= 1
+    fprintf(stderr, "out-of-order response ignored: %d (last: %d)\n",
+	    packet->number, last_num);
+    fflush(stderr);
+#endif
+    return;
+  }
+  last_num = packet->number;
+  i = PITH(last_num);
+
+  /* calculate roundtrip */
+  ping_lag = mstime() - ping_sent[i].time;
+
+#ifdef INL_STATS
+  /* fill in lag stats fields */
+  update_lag_stats();
+#endif
+
+  /* watch out for div by 0 */
+  if (!packets_received || !ping_sent[i].packets_sent_at_ping)
+    return;
+
+  /* calculate total packet loss */
+  calc_loss(i, packet);
+
+#ifdef INL_STATS
+  update_loss_stats();
+#endif
+}
+
+/*
+ * request from server
+ */
+
+void
+sendClientPing()
+{
+  struct ping_spacket packet;
+
+  ping_ghostbust++;
+  ping_id++;			/* ok to wrap */
+
+  packet.type = SP_PING;
+  packet.number = (unsigned char) ping_id;
+  packet.lag = htons((unsigned short) ping_lag);
+  packet.tloss_sc = tloss_sc;
+  packet.tloss_cs = tloss_cs;
+  packet.iloss_sc = iloss_sc;
+  packet.iloss_cs = iloss_cs;
+
+  ping_sent[PITH(ping_id)].time = mstime();
+  /*
+   * printf("ping sent at %d\n", msetime());
+   */
+
+  sendClientPacket(&packet);
+
+  ping_sent[PITH(ping_id)].packets_sent_at_ping = packets_sent;
+}
+
+void
+calc_loss(i, packet)
+  int i;
+  struct ping_cpacket *packet;
+{
+  /* tloss vars */
+  register cp_recv,		/* client packets recv */
+      cp_sent;			/* client packets sent */
+  int s_to_c_dropped,		/* server to client */
+      c_to_s_dropped;		/* client to server */
+  static int old_s_to_c_dropped,/* previous update */
+      old_c_to_s_dropped;	/* "" */
+  /* iloss vars */
+  int p_sent, p_recv;
+
+  static
+  int timer;
+
+  static int inc_packets_sent,	/* packets sent start-point */
+      inc_packets_received,	/* packets recvd start-pt  */
+      inc_s_to_c_dropped,	/* dropped s-to-c start-pt */
+      inc_c_to_s_dropped;	/* dropped c-to-s start-pt */
+
+  if (!timer)
+    timer = configvals->ping_iloss_interval;
+
+  cp_recv = ntohl(packet->cp_recv);
+  cp_sent = ntohl(packet->cp_sent);
+
+  /* at ping time, total packets dropped from server to client */
+  s_to_c_dropped = ping_sent[i].packets_sent_at_ping - cp_recv;
+
+  if (s_to_c_dropped < old_s_to_c_dropped)
+  {
+    /*
+     * The network may duplicate or send out-of-order packets. Both are
+     * detected and thrown out by the client if sequence checking is on. If
+     * not there's not much we can do -- there's no way to distinguish a
+     * duplicated packet from a series of out of order packets.  While the
+     * latter case cancels itself out eventually in terms of packet loss, the
+     * former hides real packet loss by adding extra packets. We'll have to
+     * kludge it by adding the extra packets the client thinks it got to
+     * packets_sent
+     */
+    packets_sent += old_s_to_c_dropped - s_to_c_dropped;
+    /* and adjust s_to_c_dropped so we don't get a negative packet loss */
+    s_to_c_dropped = old_s_to_c_dropped;
+  }
+
+  /* total loss server-to-client since start of connection */
+  tloss_sc = 100 -
+    (100 * (ping_sent[i].packets_sent_at_ping - s_to_c_dropped)) /
+    ping_sent[i].packets_sent_at_ping;
+
+  /*
+   * at ping time, total packets dropped from client to server NOTE: not
+   * packets_received_at_ping since the client may have sent any amount of
+   * packets between the time we sent the ping and the time the client
+   * received it.
+   */
+  c_to_s_dropped = cp_sent - packets_received;
+
+#if PING_DEBUG >= 2
+  printf("cp_sent: %d, packets_received: %d\n",
+	 cp_sent, packets_received);
+#endif
+
+  if (c_to_s_dropped < old_c_to_s_dropped)
+  {
+    /*
+     * The network may duplicate or send out-of-order packets. Since no
+     * sequence checking is done by the server, there's not much we can do --
+     * there's no way to distinguish a duplicated packet from a series of out
+     * of order packets.  While the latter case cancels itself out eventually
+     * in terms of packet loss, the former hides real packet loss by adding
+     * extra packets. We'll have to kludge it by subtracting the extra
+     * packets we think we got from the client from packets_received.
+     */
+    packets_received -= old_c_to_s_dropped - c_to_s_dropped;
+    /* and adjust c_to_s_dropped so we don't get a negative packet loss */
+    c_to_s_dropped = old_c_to_s_dropped;
+  }
+
+  /* total loss client-to-server since start of connection */
+  tloss_cs = 100 -
+    (100 * (packets_received - c_to_s_dropped)) / (packets_received ? packets_received : 1);
+
+  old_s_to_c_dropped = s_to_c_dropped;
+  old_c_to_s_dropped = c_to_s_dropped;
+
+  /* Incremental packet loss */
+
+  /* packets sent since last ping response */
+  p_sent = ping_sent[i].packets_sent_at_ping - inc_packets_sent;
+
+  /* packets received since last ping response */
+  p_recv = packets_received - inc_packets_received;
+
+  if (!p_sent || !p_recv)
+  {
+    /* just in case */
+    return;
+  }
+
+  /* percent loss server-to-client since PACKET_LOSS_INTERVAL */
+  iloss_sc = 100 -
+    (100 * (p_sent - (s_to_c_dropped - inc_s_to_c_dropped))) / p_sent;
+  /*
+   * we're not going to do any of the adjustments we did in tloss
+   * calculations since this starts fresh every PACKET_LOSS_INTERVAL
+   */
+  if (iloss_sc < 0)
+    iloss_sc = 0;
+
+  /* total percent loss client-to-server since PACKET_LOSS_INTERVAL */
+  iloss_cs = 100 -
+    (100 * (p_recv - (c_to_s_dropped - inc_c_to_s_dropped))) / p_recv;
+  /*
+   * we're not going to do any of the adjustments we did in tloss
+   * calculations since this starts fresh every PACKET_LOSS_INTERVAL
+   */
+  if (iloss_cs < 0)
+    iloss_cs = 0;
+
+  /*
+   * we update these variables every PACKET_LOSS_INTERVAL seconds to start a
+   * fresh increment
+   */
+  if ((timer % configvals->ping_iloss_interval) == 0)
+  {
+    inc_s_to_c_dropped = s_to_c_dropped;
+    inc_c_to_s_dropped = c_to_s_dropped;
+
+    inc_packets_sent = ping_sent[i].packets_sent_at_ping;
+    inc_packets_received = packets_received;
+  }
+
+  timer++;
+}
+
+#ifdef INL_STATS
+
+/*
+ * Lag stats struct player .p_avrt -	average round trip time ms struct
+ * player .p_stdv - 	standard deviation in rt time struct player .p_pkls -
+ * input/output packet loss
+ */
+
+static int sum, n, s2;
+static int M, var;
+
+void
+update_lag_stats()
+{
+  n++;
+  sum += ping_lag;
+  s2 += (ping_lag * ping_lag);
+  if (n == 1)
+    return;
+
+  M = sum / n;
+  var = (s2 - M * sum) / (n - 1);
+
+  /* average round trip time */
+  me->p_avrt = M;
+  /* standard deviation */
+  if (var > 0)
+    me->p_stdv = (int) isqrt(var);
+}
+
+void
+update_loss_stats()
+{
+  /*
+   * packet loss (as average of server-to-client, client-to-server loss),
+   * give tloss_sc extra weight (or should we?)
+   */
+  me->p_pkls = (2 * tloss_sc + tloss_cs) / 3;
+}
+#endif				/* INL_STATS */
+
+/* utilities */
+
+/* ms time from start */
+int
+mstime()
+{
+  static struct timeval tv_base = {0, 0};
+  struct timeval tv;
+
+  if (!tv_base.tv_sec)
+  {
+    gettimeofday(&tv_base, NULL);
+    return 0;
+  }
+  gettimeofday(&tv, NULL);
+  return (tv.tv_sec - tv_base.tv_sec) * 1000 +
+    (tv.tv_usec - tv_base.tv_usec) / 1000;
+}
+
+/* debugging */
+int
+msetime()
+{
+  struct timeval tv;
+  gettimeofday(&tv, NULL);
+  return (tv.tv_sec - 732737182) * 1000 + tv.tv_usec / 1000;
+}
+
+int
+uchar_diff(x, y)
+  int x, y;
+{
+  register res;
+
+  res = x - y;
+
+  if (res > 128)
+    return res - 256;
+  else if (res < -128)
+    return res + 256;
+  else
+    return res;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pl_gen0.c	Sat Dec 06 04:37:03 1997 +0000
@@ -0,0 +1,336 @@
+/*--------------------------------------------------------------------------
+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 <stdio.h>
+
+#include "defs.h"
+#include "struct.h"
+#include "shmem.h"
+#include "planets.h"
+
+/*
+ * This file contains utility procedures useful when laying out the galaxy.
+ * 
+ */
+
+/* #define SLOWER */
+
+int 
+place_stars(first, count, border, minpad, maxpad,
+	    othercheck, ocount)
+  struct planet *first;
+  int count;
+  int border, minpad, maxpad;
+  struct planet *othercheck;
+  int ocount;
+{
+  int i;
+  double x, y;
+
+  for (i = 0; i < count; i++)
+  {
+    int done, attempts;
+    int j;
+
+    attempts = 0;
+    done = 0;
+#ifndef SLOWER
+    x = drand48() * (configvals->gwidth - 2 * border) + border;
+    y = drand48() * (configvals->gwidth - 2 * border) + border;
+#endif
+    do
+    {
+
+      attempts++;
+
+#ifdef SLOWER
+      x = drand48() * (configvals->gwidth - 2 * border) + border;
+      y = drand48() * (configvals->gwidth - 2 * border) + border;
+#else
+      x = border + fmod(x + 3574 - border,
+			(configvals->gwidth - 2.0 * border));
+      y = border + fmod(y + 1034 - border,
+			(configvals->gwidth - 2.0 * border));
+#endif
+      done = 1;
+      /* check to make sure we aren't too close to other stars */
+      for (j = 0; j < ocount; j++)
+      {
+	double dist = hypot(x - othercheck[j].pl_x,
+			    y - othercheck[j].pl_y);
+	if (dist < minpad || dist > maxpad)
+	{
+	  done = 0;
+	  break;
+	}
+      }
+      /*
+       * check to make sure we're not too close to the current set of stars
+       */
+      if (done)
+	for (j = 0; j < i; j++)
+	{
+	  double dist = hypot(x - first[j].pl_x,
+			      y - first[j].pl_y);
+	  if (dist < minpad || dist > maxpad)
+	  {
+	    done = 0;
+	    break;
+	  }
+	}
+    } while (!done && attempts < 1000);
+    if (!done)
+      return 0;
+
+    first[i].pl_owner = NOBODY;
+    first[i].pl_system = (&first[i] - planets) + 1;
+    first[i].pl_flags |= PLSTAR;
+    move_planet(&first[i] - planets, (int) x, (int) y, 0);
+    first[i].pl_hinfo = ALLTEAM;/* all teams know its a star */
+    for (j = 0; j < MAXTEAM + 1; j++)
+    {				/* go put in info for teams */
+      first[i].pl_tinfo[j].owner = NOBODY;	/* nobody owns it */
+      first[i].pl_tinfo[j].armies = 0;
+      first[i].pl_tinfo[j].flags = first[i].pl_flags;
+    }
+  }
+  return 1;
+}
+
+void
+zero_plflags(first, count)
+  struct planet *first;
+  int count;
+{
+  int i;
+  for (i = 0; i < count; i++)
+  {
+    first[i].pl_flags = 0;
+  }
+}
+
+void
+randomize_atmospheres(first, count, p1, p2, p3, p4)
+  struct planet *first;
+  int count;
+  int p1, p2, p3, p4;
+{
+  int i;
+  int sum = p1 + p2 + p3 + p4;
+  for (i = 0; i < count; i++)
+  {
+    int val;
+    int atmosphere;
+    val = lrand48() % sum;
+    if ((val -= p1) < 0)
+      atmosphere = PLATYPE1;
+    else if ((val -= p2) < 0)
+      atmosphere = PLATYPE2;
+    else if ((val -= p3) < 0)
+      atmosphere = PLATYPE3;
+    else
+      atmosphere = PLPOISON;
+    first[i].pl_flags &= !PLATMASK;
+    first[i].pl_flags |= atmosphere;
+  }
+}
+
+/*
+ * special note.
+ * 
+ * It looks like this function originally wanted to make all Dilithium planets
+ * toxic, but the code was buggy and if an arable happened to be placed on
+ * the same planet later, you would get an STND DA.
+ * 
+ * I am loath to fix this bug, because it would noticably alter the galactic
+ * mix.  This must be brought before the PLC.
+ * 
+ * -RF
+ * 
+ */
+void
+randomize_resources(first, count, nm, nd, na)
+  struct planet *first;
+  int count;
+  int nm, nd, na;
+{
+  for (; count > 0; count--, first++)
+  {
+    int val;
+
+    val = lrand48() % count;
+    if (val < nm)
+    {
+      nm--;
+      first->pl_flags |= PLMETAL;
+      if (!configvals->resource_bombing)
+	first->pl_flags |= PLREPAIR;
+    }
+
+    val = lrand48() % count;
+    if (val < nd)
+    {
+      nd--;
+      first->pl_flags |= PLDILYTH;
+      first->pl_flags &= ~(PLATMASK | PLARABLE);
+      first->pl_flags |= PLPOISON;
+      if (!configvals->resource_bombing)
+	first->pl_flags |= PLFUEL;
+    }
+
+    val = lrand48() % count;
+    if (val < na)
+    {
+      na--;
+      first->pl_flags |= PLARABLE | PLATYPE1;
+      if (!configvals->resource_bombing)
+	first->pl_flags |= PLAGRI;
+    }
+  }
+}
+
+static int
+count_planets_in_system(sysnum)
+  int sysnum;
+{
+  int rval = 0;
+  int i;
+
+  for (i = 0; i < NUMPLANETS; i++)
+  {
+    if (PL_TYPE(planets[i]) == PLPLANET &&
+	planets[i].pl_system == sysnum)
+      rval++;
+  }
+  return rval;
+}
+
+static int
+pick_metal_planet_from_system(sysnum, nplanets)
+  int sysnum, nplanets;
+{
+  int i;
+
+  for (i = 0; i < NUMPLANETS; i++)
+  {
+    if (PL_TYPE(planets[i]) == PLPLANET &&
+	planets[i].pl_system == sysnum &&
+	(planets[i].pl_flags & PLMETAL))
+    {
+      if (lrand48() % nplanets == 0)
+	return i;
+      nplanets--;
+    }
+  }
+  return -1;
+}
+
+static int
+pick_planet_from_system(sysnum, nplanets)
+  int sysnum, nplanets;
+{
+  int i;
+
+  if (nplanets < 0)
+    nplanets = count_planets_in_system(sysnum);
+
+  for (i = 0; i < NUMPLANETS; i++)
+  {
+    if (PL_TYPE(planets[i]) == PLPLANET &&
+	planets[i].pl_system == sysnum)
+    {
+      if (lrand48() % nplanets == 0)
+	return i;
+      nplanets--;
+    }
+  }
+  return -1;
+}
+
+
+void
+justify_galaxy(numsystems)
+  int numsystems;
+/*
+ * Balances the galaxy to be "fair".  Currently ensures that: -> One metal
+ * planet exists within each system.
+ */
+{
+  int i, j;
+  int *metalcount;
+
+  metalcount = malloc(sizeof(*metalcount) * (numsystems + 1));
+
+  for (i = 0; i <= numsystems; i++)
+    metalcount[i] = 0;
+
+  for (i = 0; i < NUMPLANETS; i++)
+  {
+    switch (PL_TYPE(planets[i]))
+    {
+     case PLPLANET:
+      {
+	int system = planets[i].pl_system;
+	if (system < 0 || system > numsystems)
+	  break;
+	if (planets[i].pl_flags & PLMETAL)
+	  metalcount[system]++;
+      }
+      break;
+     default:
+      ;
+      /* don't care about other stuff */
+    }
+  }
+
+  for (i = 1; i <= numsystems; i++)
+  {
+    if (metalcount[i] < 1)
+    {
+      int to, from;
+      int randbase;
+
+      randbase = lrand48() % (numsystems + 1);
+
+      for (j = 0; j <= numsystems; j++)
+	if (metalcount[(j + randbase) % (numsystems + 1)] > 1)
+	  break;
+      if (j > numsystems)
+      {
+	fprintf(stderr, "error stealing metal planet.  Too few!\n");
+	return;
+      }
+      j = (j + randbase) % (numsystems + 1);
+      to = pick_planet_from_system(i, -1);
+      from = pick_metal_planet_from_system(j, metalcount[j]);
+      planets[to].pl_flags |= PLMETAL;
+      planets[from].pl_flags &= ~PLMETAL;
+      if (!configvals->resource_bombing)
+      {
+	planets[to].pl_flags |= PLREPAIR;
+	planets[from].pl_flags &= PLREPAIR;
+      }
+      metalcount[i]++;
+      metalcount[j]--;
+    }
+  }
+  free(metalcount);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pl_gen1.c	Sat Dec 06 04:37:03 1997 +0000
@@ -0,0 +1,509 @@
+/*--------------------------------------------------------------------------
+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)	/* width of a system */
+
+#define SYSTEMS		9	/* number of planetary systems */
+
+/* atmosphere chances form a cascade win rand()%100 */
+#define PATMOS1		40	/* chance for normal atmosphere */
+#define PATMOS2		70	/* chance for thin atmosphere */
+#define PATMOS3		90	/* chance for slightly toxic stmos */
+#define PPOISON		100	/* chance for poison atmos */
+
+/* defines that deal with planets resources and types */
+#define NMETAL		2	/* number of metal deposits */
+#define NDILYTH		10	/* number of dilythium deposits */
+#define NARABLE		30	/* number of arable land planets */
+/* defines that deal with star placement */
+
+#define GW	((float)GWIDTH)	/* size of galaxy in floating point */
+#define	STARBORD	(SYSWIDTH/2)
+#define STARMIN		(GW/3.7)/* min dist between stars */
+#define STARMIN2	STARMIN*STARMIN	/* min star dist squared */
+
+/* defines that deal with systems and their planets */
+#define SYSMINP		4	/* min number of planets per system */
+#define SYSADD		2	/* number possible above min number */
+#define SYSBORD		(5000.0	+ (float)(GWIDTH/200))	/* min distance from
+							 * border wall */
+#define SYSMIN		(7000.0	+ (float)(GWIDTH/100))	/* 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;
+
+  for (i = 0; i < SYSTEMS; i++)
+  {				/* star for each system */
+    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 + 134.0, GW);	/* every loop */
+      if ((x > GW - STARBORD) || (x < STARBORD)
+	  || (y < STARBORD) || (y > GW - STARBORD))
+	continue;		/* too close to border? */
+      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);
+	if (dx * dx + dy * dy < STARMIN2)	/* if too close then */
+	  done = 0;		/* we must get another coord */
+      }
+    } while (!done && attempts < 1000);	/* do until location found */
+
+    if (!done)
+      return 0;
+
+    planets[i].pl_owner = NOBODY;	/* no team owns a star */
+    planets[i].pl_flags |= PLSTAR;	/* mark planet as a star */
+    move_planet(i, (int) x, (int) y, 0);
+    planets[i].pl_system = i + 1;	/* mark the sytem number */
+    planets[i].pl_hinfo = ALLTEAM;	/* all teams know its a star */
+    for (j = 0; j < MAXTEAM + 1; j++)
+    {				/* go put in info for teams */
+      planets[i].pl_tinfo[j].owner = NOBODY;	/* nobody owns it */
+      planets[i].pl_tinfo[j].armies = 0;
+      planets[i].pl_tinfo[j].flags = planets[i].pl_flags;
+    }
+  }
+  return 1;
+}
+#endif
+
+
+
+/*-----------------------------PLACESYSTEMS------------------------------*/
+/*
+ * This function places the planets in each star's system.  The function will
+ * return the index of the first planet that was not placed in a system. The
+ * coordinates of the planets are placed in the space grid.
+ */
+
+static int
+placesystems()
+{
+  int i, j, k;			/* looping vars */
+  double x, y;			/* to hold star coordinates */
+  int done;			/* flag to indicate done */
+  double dx, dy;		/* delta x and y's */
+  int n;			/* number of planet to place */
+  int np;			/* number of planets in system */
+  int attempts;
+
+  n = SYSTEMS;			/* first planet to place */
+  for (i = 0; i < SYSTEMS; i++)
+  {				/* planets for each system */
+    np = SYSPLMIN + lrand48() % (SYSPLADD + 1);	/* how many planets */
+    for (k = 0; k < np; k++)
+    {				/* go place the planets */
+      attempts = 0;
+      do
+      {				/* do until location found */
+	attempts++;
+	done = 0;		/* not done yet */
+	dx = (drand48() * SYSWIDTH - SYSWIDTH / 2.0);
+	dy = (drand48() * SYSWIDTH - SYSWIDTH / 2.0);
+	if (dx * dx + dy * dy > (SYSWIDTH / 2.0) * (SYSWIDTH / 2.0))
+	  continue;		/* might orbit its way out of the galaxy */
+	x = planets[i].pl_x + dx;
+	y = planets[i].pl_y + dy;
+	if ((x > GW - SYSBORD) || (x < SYSBORD)
+	    || (y < SYSBORD) || (y > GW - SYSBORD))
+	  continue;		/* too close to border? */
+
+	done = 1;		/* assume valid coord found */
+	for (j = 0; j < n; j++)
+	{			/* go through previous planets */
+	  dx = fabs(x - (double) planets[j].pl_x);
+	  dy = fabs(y - (double) planets[j].pl_y);
+	  if (dx * dx + dy * dy < SYSMIN2)
+	  {			/* if too close to another star */
+	    done = 0;		/* we must get another coord */
+	  }
+	}
+      } while (!done && attempts < 100);	/* 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;		/* 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 + 134.0, GW);	/* every loop */
+      if ((x > GW - SYSBORD) || (x < SYSBORD)
+	  || (y < SYSBORD) || (y > GW - SYSBORD))
+	continue;		/* too close to border? */
+      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 < 100);	/* 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.  This is the algorithm used by the paradise
+ * 2.01 server in its first release. I hope.
+ */
+
+void
+gen_galaxy_1()
+{
+  int t;
+  while (1)
+  {
+		NUMPLANETS = 60;
+    GWIDTH = 200000;
+    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 */
+    if (!place_stars(planets, SYSTEMS,
+		     (int) STARBORD, (int) STARMIN, (int) GW,
+		     (struct planet *) 0, 0))
+      continue;
+
+    t = placesystems();		/* place planets in systems */
+    if (!t)
+      continue;
+
+    if (!placeindep(t))		/* place independent planets */
+      continue;
+
+    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_gen2.c	Sat Dec 06 04:37:03 1997 +0000
@@ -0,0 +1,559 @@
+/*--------------------------------------------------------------------------
+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/8)	/* width of a system */
+
+#define SYSTEMS		8	/* 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		3	/* number of metal deposits */
+#define NDILYTH		10	/* number of dilythium deposits */
+#define NARABLE		30	/* number of arable land planets */
+/* defines that deal with star placement */
+
+#define	GW	((float)GWIDTH)	/* size of galaxy in floating point */
+#define	STARBORD ((GWIDTH-SYSWIDTH*4)/2)	/* cannot be this close to
+						 * wall */
+#define STARMIN		(6*SYSWIDTH/5)	/* min dist between stars */
+#define STARMIN2	STARMIN*STARMIN	/* min star dist squared */
+
+/* defines that deal with systems and their planets */
+#define SYSMINP		4	/* min number of planets per system */
+#define SYSADD		2	/* number possible above min number */
+#define SYSBORD		(SYSWIDTH/4)	/* min distance from border wall */
+#define SYSMIN		(SYSWIDTH/3)	/* 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 < NUMPLANETS; i++)
+    planets[i].pl_flags = 0;
+
+  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;
+
+  for (i = 0; i < SYSTEMS; i++)
+  {				/* star for each system */
+    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 + 134.0, GW);	/* every loop */
+      if ((x > GW - STARBORD) || (x < STARBORD)
+	  || (y < STARBORD) || (y > GW - STARBORD))
+	continue;		/* too close to border? */
+      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);
+	if (dx * dx + dy * dy < STARMIN2)	/* if too close then */
+	  done = 0;		/* we must get another coord */
+      }
+    } while (!done && attempts < 1000);	/* do until location found */
+
+    if (!done)
+      return 0;
+
+    planets[i].pl_flags |= PLSTAR;	/* mark planet as a star */
+    move_planet(i, (int) x, (int) y, 0);
+    planets[i].pl_system = i + 1;	/* mark the sytem number */
+    planets[i].pl_hinfo = ALLTEAM;	/* all teams know its a star */
+    for (j = 0; j < MAXTEAM + 1; j++)
+    {				/* go put in info for teams */
+      planets[i].pl_tinfo[j].owner = NOBODY;	/* nobody owns it */
+      planets[i].pl_tinfo[j].armies = 0;
+      planets[i].pl_tinfo[j].flags = planets[i].pl_flags;
+    }
+  }
+  return 1;
+}
+#endif
+
+
+
+/*-----------------------------PLACESYSTEMS------------------------------*/
+/*
+ * This function places the planets in each star's system.  The function will
+ * return the index of the first planet that was not placed in a system. The
+ * coordinates of the planets are placed in the space grid.
+ */
+
+static int
+placesystems()
+{
+  int i, j, k;			/* looping vars */
+  double x, y;			/* to hold star coordinates */
+  int done;			/* flag to indicate done */
+  double dx, dy;		/* delta x and y's */
+  int n;			/* number of planet to place */
+  int np;			/* number of planets in system */
+  int attempts;
+
+  n = SYSTEMS;			/* first planet to place */
+  for (i = 0; i < SYSTEMS; i++)
+  {				/* planets for each system */
+    np = SYSPLMIN + lrand48() % (SYSPLADD + 1);	/* how many planets */
+    for (k = 0; k < np; k++)
+    {				/* go place the planets */
+      attempts = 0;
+      do
+      {				/* do until location found */
+	attempts++;
+	done = 0;		/* not done yet */
+	dx = (drand48() * SYSWIDTH - SYSWIDTH / 2.0);
+	dy = (drand48() * SYSWIDTH - SYSWIDTH / 2.0);
+	if (dx * dx + dy * dy > (SYSWIDTH / 2.0) * (SYSWIDTH / 2.0))
+	  continue;		/* might orbit its way out of the galaxy */
+	x = planets[i].pl_x + dx;
+	y = planets[i].pl_y + dy;
+	if ((x > GW - SYSBORD) || (x < SYSBORD)
+	    || (y < SYSBORD) || (y > GW - SYSBORD))
+	  continue;		/* too close to border? */
+
+	done = 1;		/* assume valid coord found */
+	for (j = 0; j < n; j++)
+	{			/* go through previous planets */
+	  dx = fabs(x - (double) planets[j].pl_x);
+	  dy = fabs(y - (double) planets[j].pl_y);
+	  if (dx * dx + dy * dy < SYSMIN2)
+	  {			/* if too close to another star */
+	    done = 0;		/* we must get another coord */
+	  }
+	}
+      } while (!done && attempts < 100);	/* 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;		/* 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 + 134.0, GW);	/* every loop */
+      if ((x > GW - SYSBORD) || (x < SYSBORD)
+	  || (y < SYSBORD) || (y > GW - SYSBORD))
+	continue;		/* too close to border? */
+      done = 1;			/* assume valid coord */
+      for (j = 0; j < i; 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 * (2 * 2))
+	{			/* if planet to close */
+	  done = 0;		/* we must get another coord */
+	}
+      }
+    } while (!done && attempts < 100);	/* 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 + 134.0, GW);	/* every loop */
+
+      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 wormhole */
+    planets[i].pl_hinfo = ALLTEAM;	/* all teams know its a wormhole */
+    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 colony planet with
+ * dilythium deposits and COLONYARMIES on it.
+ */
+
+static int
+placeraces()
+{
+  int i, j, k;			/* looping vars */
+  int p;			/* to hold planet for race */
+  int racestars[4 /* NRACES */ ];	/* hold the home stars of each race */
+  int attempts = 0;
+  int n;
+
+  for (i = 0; i < NUMPLANETS; i++)
+  {
+    /* zero ownership */
+    planets[i].pl_owner = NOBODY;	/* no team owns a star */
+    if ((PL_TYPE(planets[i]) != PLSTAR) && (PL_TYPE(planets[i]) != PLWHOLE))
+      planets[i].pl_hinfo = NOBODY;	/* no race has planet info */
+  }
+
+  for (i = 0; i < 4 && attempts < 1000; i++)
+  {				/* go through races */
+    /* find home planet */
+    attempts++;
+    p = lrand48() % NUMPLANETS;	/* pick random planet */
+    while ((planets[p].pl_system == 0)
+	   || (PL_TYPE(planets[p]) == PLSTAR)
+	   || (planets[p].pl_owner != NOBODY))
+      p = (p + 1) % NUMPLANETS;	/* go on to next planet */
+
+    racestars[i] = planets[p].pl_system - 1;
+    for (j = 0; j < i; j++)
+    {
+      struct planet *mystar = &planets[racestars[i]];
+      struct planet *otherstar = &planets[racestars[j]];
+      float dx, dy;
+      dx = otherstar->pl_x - mystar->pl_x;
+      dy = otherstar->pl_y - mystar->pl_y;
+      if (dx * dx + dy * dy < 3.0 * SYSWIDTH * SYSWIDTH)
+      {
+	break;
+      }
+    }
+    if (j < i)
+    {
+      i--;
+      continue;
+    }
+    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 != racestars[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;
+    n = 0;
+    for (j = 0; j < NUMPLANETS; j++)
+    {
+      if ((planets[j].pl_system == racestars[i] + 1)
+	  && !(PL_TYPE(planets[j]) == PLSTAR))
+      {
+
+	if (planets[j].pl_owner == NOBODY)
+	{
+	  planets[j].pl_flags &= ~(PLATMASK | PLSURMASK);
+	  planets[j].pl_flags |= (n << PLATSHIFT) | (1 << (n + PLSURSHIFT));
+	  n++;
+	}
+	planets[j].pl_owner = 1 << i;
+	planets[j].pl_hinfo =
+#ifdef LEAGUE_SUPPORT
+	  status2->league ? (1 << 4) - 1 :
+#endif
+	  (1 << i);
+
+#ifdef LEAGUE_SUPPORT
+	for (k = (status2->league ? 0 : i);
+	     k < (status2->league ? 4 : i + 1);
+	     k++)
+#else
+	k = i;
+#endif
+	{
+	  struct teaminfo *info = &planets[j].pl_tinfo[1 << k];
+	  info->owner = 1 << i;
+	  info->armies = planets[j].pl_armies;
+	  info->flags = planets[j].pl_flags;
+	}
+      }
+    }
+  }
+  return i >= 4;
+}
+
+/*
+ * generate a complete galaxy.
+ * 
+ * This algorithm was invented by Robert Forsman.
+ * 
+ * It tries to make a denser universe with fairer race resource distribution and
+ * races that are further apart..
+ */
+
+void
+gen_galaxy_2()
+{
+  int t;
+
+  while (1)
+  {
+    NUMPLANETS = 60;
+    GWIDTH = 200000;
+
+    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);
+
+    if (!place_stars(planets, SYSTEMS,
+		     (int) STARBORD, (int) STARMIN, (int) GW,
+		     (struct planet *) 0, 0))	/* place system centers */
+      continue;
+
+    t = placesystems();		/* place planets in systems */
+    if (!t)
+      continue;
+
+    if (!placeindep(t))		/* place independent planets */
+      continue;
+
+    if (configvals->justify_galaxy)
+      justify_galaxy(SYSTEMS);
+
+    if (!placeraces())		/* place home planets for races */
+      continue;
+    break;			/* success! */
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pl_gen3.c	Sat Dec 06 04:37:03 1997 +0000
@@ -0,0 +1,561 @@
+/*--------------------------------------------------------------------------
+NETREK II -- Paradise
+
+Permission to use, copy, modify, and distribute this software and its
+documentation, or any derivative works thereof, for any NON-COMMERCIAL
+purpose and without fee is hereby granted, provided that this copyright
+notice appear in all copies.  No representations are made about the
+suitability of this software for any purpose.  This software is provided
+"as is" without express or implied warranty.
+
+    Xtrek Copyright 1986                            Chris Guthrie
+    Netrek (Xtrek II) Copyright 1989                Kevin P. Smith
+                                                    Scott Silvey
+    Paradise II (Netrek II) Copyright 1993          Larry Denys
+                                                    Kurt Olsen
+                                                    Brandon Gillespie
+--------------------------------------------------------------------------*/
+
+#include "config.h"
+#include <math.h>
+
+#include "defs.h"
+#include "struct.h"
+#include "data.h"
+#include "shmem.h"
+#include "planets.h"
+
+#define SYSWIDTH	(GWIDTH/5.9)	/* width of a system */
+
+#define SYSTEMS		9	/* number of planetary systems */
+
+/* atmosphere chances form a cascade win rand()%100 */
+#define PATMOS1		40	/* chance for normal atmosphere */
+#define PATMOS2		70	/* chance for thin atmosphere */
+#define PATMOS3		90	/* chance for slightly toxic stmos */
+#define PPOISON		100	/* chance for poison atmos */
+
+/* defines that deal with planets resources and types */
+#define NMETAL		13	/* number of metal deposits */
+#define NDILYTH		10	/* number of dilythium deposits */
+#define NARABLE		15	/* number of arable land planets */
+/* defines that deal with star placement */
+
+#define GW	((float)GWIDTH)	/* size of galaxy in floating point */
+#define	STARBORD	(GW*0.27)
+#define TEAMBORD	(GW*0.32)
+#define STARMIN		(GW/5.6)/* min dist between stars */
+#define STARMAX		GW
+#define TEAMMIN		(GW/2.8)/* min dist between team stars */
+#define TEAMMAX		(GW/1.8)/* max dist between team stars */
+
+/* defines that deal with systems and their planets */
+#define SYSADD		2	/* number possible above min number */
+#define SYSBORD		(7000.0 + (float)GWIDTH/200)	/* min distance from
+							 * border wall */
+#define INDBORD		(GW*0.23)
+#define SYSMIN		(5500.0 + (float)GWIDTH/200)	/* min distance between
+							 * objects */
+#define SYSMIN2		(SYSMIN*SYSMIN)	/* square of sysmin distance */
+#define SYSPLMIN	5	/* min number of planets for system */
+#define SYSPLADD	0	/* number of possible extra planets */
+#define MINARMY 8		/* min numer of armies on a planet */
+#define MAXARMY 15		/* max number of armies on a planet */
+
+/* other defines */
+#define HOMEARMIES 30		/* number of armies on home planets */
+#define COLONYARMIES 10		/* number of armies for colony planet */
+
+
+/* defines dealing with growth timers */
+#define PLGFUEL		configvals->plgrow.fuel	/* time for growth of fuel
+						 * depot */
+#define PLGAGRI		configvals->plgrow.agri	/* time for growth of agri */
+#define PLGREPAIR	configvals->plgrow.repair	/* time for growth of
+							 * repair */
+#define PLGSHIP		configvals->plgrow.shipyard	/* time for growth of
+							 * shipyard */
+
+
+#if 0
+/*-------------------------------GENRESOURCES----------------------------*/
+/*
+ * This function goes through the planets structure and determines what kind
+ * of atmosphere and what kind of surface the planets have.  It generates the
+ * stars that will be used as system centers ans then places atmospheres on
+ * the other planets.  It then distributes the resources on the planet
+ * surfaces.
+ */
+
+static void
+genresources()
+{
+  int i;			/* looping vars */
+  int t;			/* temp var */
+
+  for (i = 0; i < SYSTEMS; i++)	/* first planets are stars */
+    planets[i].pl_flags |= PLSTAR;	/* or in star flag */
+  for (i = SYSTEMS; i < NUMPLANETS; i++)
+  {				/* generate atmospheres */
+    t = lrand48() % 100;	/* random # 0-99 */
+    if (t < PATMOS1)		/* is it atmosphere type 1 */
+      planets[i].pl_flags |= PLATYPE1;
+    else if (t < PATMOS2)	/* is it atmosphere type 2 */
+      planets[i].pl_flags |= PLATYPE2;
+    else if (t < PATMOS3)	/* is it atmosphere type 3 */
+      planets[i].pl_flags |= PLATYPE3;
+    else if (t < PPOISON)	/* is it poison atmosphere */
+      planets[i].pl_flags |= PLPOISON;
+  }
+  for (i = 0; i < NMETAL; i++)
+  {				/* place the metal deposits */
+    t = lrand48() % (NUMPLANETS - SYSTEMS) + SYSTEMS;	/* random planet */
+    planets[t].pl_flags |= PLMETAL;	/* OR in the metal flag */
+    if (!configvals->resource_bombing)
+      planets[t].pl_flags |= PLREPAIR;
+  }
+  for (i = 0; i < NDILYTH; i++)
+  {				/* place the metal deposits */
+    t = lrand48() % (NUMPLANETS - SYSTEMS) + SYSTEMS;	/* random planet */
+    planets[t].pl_flags |= PLDILYTH;	/* OR in the dilyth flag */
+    planets[t].pl_flags &= ~(PLATMASK | PLARABLE);	/* zero off previous
+							 * atmos */
+    planets[t].pl_flags |= PLPOISON;	/* dilyth poisons atmosphere */
+    if (!configvals->resource_bombing)
+      planets[t].pl_flags |= PLFUEL;
+  }
+  for (i = 0; i < NARABLE; i++)
+  {				/* place the metal deposits */
+    t = lrand48() % (NUMPLANETS - SYSTEMS) + SYSTEMS;	/* random planet */
+    planets[t].pl_flags |= PLARABLE | PLATYPE1;	/* OR in the arable flag */
+    if (!configvals->resource_bombing)
+      planets[t].pl_flags |= PLAGRI;
+  }
+}
+#endif
+
+
+
+#if 0
+/*--------------------------------PLACESTARS------------------------------*/
+/*
+ * This function places each system's star.  The stars are expected to be in
+ * the first SYSTEMS number of planets.  The coordinates of the stars are
+ * placed in the space grid.
+ */
+
+static int
+placestars()
+{
+  int i, j;			/* looping vars */
+  double x, y;			/* to hold star coordinates */
+  int done;			/* flag to indicate done */
+  double dx, dy;		/* delta x and y's */
+  int attempts;
+  double min, max, dist, bord, nbwidth;
+  double xoff, yoff;
+
+  for (i = 0; i < SYSTEMS; i++)
+  {				/* star for each system */
+    if (i < 2)
+    {				/* choose optimal position for first two */
+      min = TEAMMIN2;
+      max = TEAMMAX2;
+      bord = TEAMBORD;
+    }
+    else if (i < 4)
+    {
+      min = TEAMMIN2;
+      max = STARMAX2;
+      bord = STARBORD * 0.8;
+    }
+    else
+    {
+      min = STARMIN2;
+      max = STARMAX2;
+      bord = STARBORD;
+    }
+    nbwidth = GW - 2 * bord;
+    x = drand48() * nbwidth + bord;	/* pick intial coords */
+    y = drand48() * nbwidth + bord;
+    xoff = 3574.0 - bord;
+    yoff = 1034.0 - bord;
+    attempts = 0;
+    do
+    {				/* do until location found */
+      attempts++;
+      done = 0;			/* not done yet */
+      x = bord + fmod(x + xoff, nbwidth);	/* offset coords a little */
+      y = bord + fmod(y + yoff, nbwidth);	/* every loop */
+#if 0
+      if ((x > GW - bord) || (x < bord)
+	  || (y < bord) || (y > GW - bord))
+	continue;		/* too close to border? */
+#endif
+      done = 1;			/* assume valid cord found */
+      for (j = 0; j < i; j++)
+      {				/* go through previous stars */
+	dx = fabs(x - (double) planets[j].pl_x);
+	dy = fabs(y - (double) planets[j].pl_y);
+	dist = dx * dx + dy * dy;
+	if (dist < min || dist > max)	/* if too close or too far then */
+	  done = 0;		/* we must get another coord */
+      }
+    } while (!done && attempts < 1000);	/* do until location found */
+
+    if (!done)
+      return 0;
+
+    planets[i].pl_owner = NOBODY;	/* no team owns a star */
+    planets[i].pl_flags |= PLSTAR;	/* mark planet as a star */
+    move_planet(i, (int) x, (int) y, 0);
+    planets[i].pl_system = i + 1;	/* mark the sytem number */
+    planets[i].pl_hinfo = ALLTEAM;	/* all teams know its a star */
+    for (j = 0; j < MAXTEAM + 1; j++)
+    {				/* go put in info for teams */
+      planets[i].pl_tinfo[j].owner = NOBODY;	/* nobody owns it */
+      planets[i].pl_tinfo[j].armies = 0;
+      planets[i].pl_tinfo[j].flags = planets[i].pl_flags;
+    }
+  }
+  return 1;
+}
+#endif
+
+
+
+/*-----------------------------PLACESYSTEMS------------------------------*/
+/*
+ * This function places the planets in each star's system.  The function will
+ * return the index of the first planet that was not placed in a system. The
+ * coordinates of the planets are placed in the space grid.
+ */
+
+static int
+placesystems()
+{
+  int i, j, k;			/* looping vars */
+  double x, y;			/* to hold star coordinates */
+  int done;			/* flag to indicate done */
+  double dx, dy;		/* delta x and y's */
+  int n;			/* number of planet to place */
+  int np;			/* number of planets in system */
+  int attempts;
+
+  n = SYSTEMS;			/* first planet to place */
+  for (i = 0; i < SYSTEMS; i++)
+  {				/* planets for each system */
+    np = SYSPLMIN + lrand48() % (SYSPLADD + 1);	/* how many planets */
+    for (k = 0; k < np; k++)
+    {				/* go place the planets */
+      attempts = 0;
+      do
+      {				/* do until location found */
+	attempts++;
+	done = 0;		/* not done yet */
+	dx = (drand48() * SYSWIDTH - SYSWIDTH / 2.0);
+	dy = (drand48() * SYSWIDTH - SYSWIDTH / 2.0);
+	if (dx * dx + dy * dy > (SYSWIDTH / 2.0) * (SYSWIDTH / 2.0))
+	  continue;		/* might orbit its way out of the galaxy */
+	x = planets[i].pl_x + dx;
+	y = planets[i].pl_y + dy;
+	if ((x > GW - SYSBORD) || (x < SYSBORD)
+	    || (y < SYSBORD) || (y > GW - SYSBORD))
+	  continue;		/* too close to border? */
+
+	done = 1;		/* assume valid coord found */
+	for (j = 0; j < n; j++)
+	{			/* go through previous planets */
+	  dx = fabs(x - (double) planets[j].pl_x);
+	  dy = fabs(y - (double) planets[j].pl_y);
+	  if (dx * dx + dy * dy < SYSMIN2)
+	  {			/* if too close to another star */
+	    done = 0;		/* we must get another coord */
+	  }
+	}
+      } while (!done && attempts < 200);	/* do until location found */
+
+      if (!done)
+	return 0;		/* universe too crowded, try again */
+
+      move_planet(n, (int) x, (int) y, 0);
+      planets[n].pl_system = i + 1;	/* mark the sytem number */
+      planets[n].pl_armies = MINARMY + lrand48() % (MAXARMY - MINARMY);
+      n++;			/* go to next planet */
+    }
+  }
+  return (n);			/* return index of next planet */
+}
+
+
+
+
+/*-----------------------------PLACEINDEP------------------------------*/
+/*
+ * This function places idependent planets that are not in a system. They can
+ * appear anywhere in the galaxy as long as they are not too close to another
+ * planet.  The coords are put in the space grid.
+ */
+
+static int
+placeindep(n)
+  int n;
+/* number of planet to start with */
+{
+  int i, j;			/* looping vars */
+  double x, y;			/* to hold star coordinates */
+  int done;			/* flag to indicate done */
+  double dx, dy;		/* delta x and y's */
+  int attempts;
+
+  for (i = n; i < (NUMPLANETS - (WORMPAIRS * 2)); i++)
+  {				/* go through rest of planets */
+    x = drand48() * (GW - 2 * INDBORD) + INDBORD;	/* pick initial coords */
+    y = drand48() * (GW - 2 * INDBORD) + INDBORD;
+    attempts = 0;
+    do
+    {				/* do until location found */
+      attempts++;
+      done = 0;			/* not done yet */
+      x = INDBORD + fmod(x + (3574.0 - INDBORD), GW - 2 * INDBORD);	/* offset coords a
+									 * little */
+      y = INDBORD + fmod(y + (1034.0 - INDBORD), GW - 2 * INDBORD);	/* every loop */
+#if 0
+      if ((x > GW - INDBORD) || (x < INDBORD)
+	  || (y < INDBORD) || (y > GW - INDBORD))
+	continue;		/* too close to border? */
+#endif
+      done = 1;			/* assume valid coord */
+      for (j = 0; j < n; j++)
+      {				/* go through previous planets */
+	dx = fabs(x - (double) planets[j].pl_x);
+	dy = fabs(y - (double) planets[j].pl_y);
+	if (dx * dx + dy * dy < SYSMIN2)
+	{			/* if planet to close */
+	  done = 0;		/* we must get another coord */
+	}
+      }
+    } while (!done && attempts < 200);	/* do until location found */
+
+    if (!done)
+      return 0;
+
+    move_planet(n, (int) x, (int) y, 0);
+    planets[n].pl_system = 0;	/* mark the no sytem */
+    planets[n].pl_armies = MINARMY + lrand48() % (MAXARMY - MINARMY);
+    n++;			/* go to next planet */
+  }
+  for (i = n; i < NUMPLANETS; i++)	/* now place wormholes */
+  {
+    x = drand48() * GW;		/* pick intial coords */
+    y = drand48() * GW;
+    attempts = 0;
+    do
+    {				/* do until location found */
+      attempts++;
+      done = 0;			/* not done yet */
+      x = fmod(x + 3574.0, GW);	/* offset coords a little */
+      y = fmod(y + 1034.0, GW);	/* every loop */
+#if 0
+      if ((x > GW) || (y > GW))
+	continue;		/* too close to border? */
+#endif
+      done = 1;			/* assume valid coord */
+      for (j = 0; j < n; j++)
+      {				/* go through previous planets */
+	dx = fabs(x - (double) planets[j].pl_x);
+	dy = fabs(y - (double) planets[j].pl_y);
+	if (dx * dx + dy * dy < SYSMIN2)
+	{			/* if planet to close */
+	  done = 0;		/* we must get another coord */
+	}
+      }
+    } while (!done && attempts < 200);	/* do until location found */
+
+    if (!done)
+      return 0;
+
+    move_planet(n, (int) x, (int) y, 0);
+    planets[n].pl_system = 0;	/* mark the no system */
+    planets[n].pl_flags |= PLWHOLE;	/* mark the planet as a wormhole */
+    /* the armies in a wormhole is the other wormhole's x coord */
+    /* the radius is the other wormhole's y coord */
+    if (NUMPLANETS % 2)
+    {
+      if (!(n % 2))
+      {
+	planets[n].pl_armies = planets[n - 1].pl_x;
+	planets[n].pl_radius = planets[n - 1].pl_y;
+	planets[n - 1].pl_armies = planets[n].pl_x;
+	planets[n - 1].pl_radius = planets[n].pl_y;
+      }
+    }
+    else
+    {
+      if (n % 2)
+      {
+	planets[n].pl_armies = planets[n - 1].pl_x;
+	planets[n].pl_radius = planets[n - 1].pl_y;
+	planets[n - 1].pl_armies = planets[n].pl_x;
+	planets[n - 1].pl_radius = planets[n].pl_y;
+      }
+    }
+    planets[i].pl_owner = NOBODY;	/* no team owns a star */
+    planets[i].pl_hinfo = ALLTEAM;	/* all teams know its a star */
+    for (j = 0; j < MAXTEAM + 1; j++)
+    {				/* go put in info for teams */
+      planets[i].pl_tinfo[j].owner = NOBODY;	/* nobody owns it */
+      planets[i].pl_tinfo[j].armies = 0;
+      planets[i].pl_tinfo[j].flags = planets[i].pl_flags;
+    }
+    n++;			/* go to next planet */
+  }
+  return 1;
+}
+
+
+
+
+/*---------------------------------PLACERACES------------------------------*/
+/*
+ * This function places the races in the galaxy.  Each race is placed in a
+ * different system.  The race is given a home world with an Agri and Ship-
+ * yard on it and HOMEARMIES.  They are also given a conoly planet with
+ * dilythium deposits and COLONYARMIES on it.
+ */
+
+static void
+placeraces()
+{
+  int i, j, k;			/* looping vars */
+  int p;			/* to hold planet for race */
+  int r[4], t;
+
+  r[0] = r[1] = lrand48() % 4;	/* pick two races at random.  They will be */
+  while (r[0] == r[1])		/* the races whose systems are 'optimally' */
+    r[1] = lrand48() % 4;	/* placed. */
+  i = 0;
+  while (i == r[0] || i == r[1])
+    i++;
+  r[2] = i++;
+  while (i == r[0] || i == r[1])
+    i++;
+  r[3] = i;
+  status2->nontteamlock = (1 << r[0]) | (1 << r[1]);	/* only allow these
+							 * teams */
+
+  for (i = 0; i < 4; i++)
+  {				/* go through races */
+    t = r[i];			/* which team */
+    p = lrand48() % NUMPLANETS;	/* pick random planet */
+    while ((planets[p].pl_system != i + 1)
+	   || (PL_TYPE(planets[p]) == PLSTAR)
+	   || (planets[p].pl_owner != NOBODY))
+      p = (p + 1) % NUMPLANETS;	/* go on to next planet */
+
+    planets[p].pl_flags &= ~PLSURMASK;	/* make sure no dilithium */
+    planets[p].pl_flags |= (PLMETAL | PLARABLE);	/* metal and arable */
+    planets[p].pl_flags |= PLATYPE1;	/* good atmosphere */
+    planets[p].pl_flags |= (PLAGRI | PLSHIPYARD | PLREPAIR);
+    planets[p].pl_tagri = PLGAGRI;	/* set timers for resources */
+    planets[p].pl_tshiprepair = PLGSHIP;
+    planets[p].pl_owner = 1 << t;	/* make race the owner */
+    planets[p].pl_armies = HOMEARMIES;	/* set the armies */
+    planets[p].pl_hinfo = 1 << t;	/* race has info on planet */
+    planets[p].pl_tinfo[1 << t].owner = 1 << t;	/* know about owner */
+    planets[p].pl_tinfo[1 << t].armies = planets[p].pl_armies;
+    planets[p].pl_tinfo[1 << t].flags = planets[p].pl_flags;
+    /* find colony planet */
+    p = lrand48() % NUMPLANETS;	/* pick random planet */
+    while ((planets[p].pl_system != i + 1)
+	   || (PL_TYPE(planets[p]) == PLSTAR)
+	   || (planets[p].pl_owner != NOBODY))
+      p = (p + 1) % NUMPLANETS;	/* go on to next planet */
+    planets[p].pl_flags |= PLFUEL;	/* make fuel depot */
+    planets[p].pl_tfuel = PLGFUEL;	/* set timer for fuel depot */
+    planets[p].pl_flags &= ~PLATMASK;	/* take off previous atmos */
+    planets[p].pl_flags |= PLPOISON;	/* poison atmosphere */
+    planets[p].pl_flags |= PLDILYTH;	/* dilythium deposits */
+    planets[p].pl_owner = 1 << t;	/* make race the owner */
+    planets[p].pl_armies = COLONYARMIES;	/* set the armies */
+    planets[p].pl_hinfo = 1 << t;	/* race knows about */
+    planets[p].pl_tinfo[1 << t].owner = 1 << t;	/* know about owner */
+    planets[p].pl_tinfo[1 << t].armies = planets[p].pl_armies;
+    planets[p].pl_tinfo[1 << t].flags = planets[p].pl_flags;
+    for (j = 0; j < NUMPLANETS; j++)
+    {
+      if ((planets[j].pl_system == i + 1) && (PL_TYPE(planets[j]) != PLSTAR))
+      {
+#ifdef LEAGUE_SUPPORT
+	for (k = (status2->league ? 0 : t);
+	     k < (status2->league ? 4 : t + 1);
+	     k++)
+#else
+	k = t;
+#endif
+	{
+	  planets[j].pl_owner = 1 << t;
+	  planets[j].pl_hinfo =
+#ifdef LEAGUE_SUPPORT
+	    status2->league ? (1 << 4) - 1 :
+#endif
+	    (1 << t);
+	  planets[j].pl_tinfo[1 << k].owner = 1 << t;
+	  planets[j].pl_tinfo[1 << k].armies = planets[j].pl_armies;
+	  planets[j].pl_tinfo[1 << k].flags = planets[j].pl_flags;
+	}
+      }
+    }
+  }
+}
+
+/*
+ * Generate a complete galaxy. This variation is similar to gen_galaxy_1;
+ * except that it tries to place the races at consistent distances from one
+ * another.
+ */
+
+void
+gen_galaxy_3()
+{
+  int t;
+
+  NUMPLANETS = 60;		/* planets + wormholes */
+  GWIDTH = 200000;
+
+  while (1)
+  {
+    initplanets();		/* initialize planet structures */
+
+    /* place the resources */
+    zero_plflags(planets, NUMPLANETS);
+    randomize_atmospheres(planets + SYSTEMS, NUMPLANETS - SYSTEMS,
+			  PATMOS1, PATMOS2, PATMOS3, PPOISON);
+    randomize_resources(planets + SYSTEMS, NUMPLANETS - SYSTEMS,
+			NMETAL, NDILYTH, NARABLE);
+
+    /* place system centers */
+    t = place_stars(planets, 2,
+		    (int) TEAMBORD, (int) TEAMMIN, (int) TEAMMAX,
+		    (struct planet *) 0, 0)
+      && place_stars(planets + 2, 2,
+		     (int) (STARBORD * 0.8), (int) TEAMMIN, (int) STARMAX,
+		     planets, 2)
+      && place_stars(planets + 4, SYSTEMS - 4,
+		     (int) STARBORD, (int) STARMIN, (int) STARMAX,
+		     planets, 4);
+
+    if (!t)
+      continue;
+    t = placesystems();		/* place planets in systems */
+    if (!t)
+      continue;
+    t = placeindep(t);		/* place independent planets */
+    if (t)
+      break;			/* success */
+  }
+  if (configvals->justify_galaxy)
+    justify_galaxy(SYSTEMS);
+  placeraces();			/* place home planets for races */
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pl_gen4.c	Sat Dec 06 04:37:03 1997 +0000
@@ -0,0 +1,260 @@
+/*--------------------------------------------------------------------------
+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 <memory.h>
+
+#include "defs.h"
+#include "struct.h"
+#include "data.h"
+#include "shmem.h"
+#include "planets.h"
+
+#if 0
+#define SYSWIDTH	(GWIDTH/5.75)	/* width of a system */
+#endif
+
+#define SYSTEMS		0	/* number of planetary systems */
+
+/* atmosphere chances form a cascade win rand()%100 */
+#define PATMOS1		100	/* chance for normal atmosphere */
+#define PATMOS2		100	/* chance for thin atmosphere */
+#define PATMOS3		100	/* chance for slightly toxic stmos */
+#define PPOISON		100	/* chance for poison atmos */
+
+/* defines that deal with planets resources and types */
+#define NMETAL		8	/* number of metal deposits */
+#define NDILYTH		12	/* number of dilythium deposits */
+#define NARABLE		8	/* number of arable land 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 */
+
+
+/*-------------------------------INITBRONCO------------------------------*/
+/*
+ * Initializes the planet array the way normaltrek did it -- not much
+ * variety, but some people dig playing chess from the same setup over and
+ * over again too. :)
+ */
+static void
+initbronco()
+{
+  int i, j;
+
+  static struct planet pdata[MAXPLANETS] = {
+    {0, (FED | PLHOME | PLCORE | PLFUEL | PLREPAIR | PLSHIPYARD | PLMETAL | PLARABLE | PLDILYTH),
+      FED, 20000, 80000, 0, 0, 0, "Earth", 5,
+    (ROM | KLI | ORI), 0, 0, 0, 30, 0, FED},
+    {1, FED | PLCORE, FED, 30000, 90000, 0, 0, 0, "Deneb", 5,
+    (ROM | KLI | ORI), 0, 0, 0, 30, 0, FED},
+    {2, FED | PLCORE, FED, 11000, 75000, 0, 0, 0, "Altair", 6,
+    (ROM | KLI | ORI), 0, 0, 0, 30, 0, FED},
+    {3, FED | PLCORE, FED, 8000, 93000, 0, 0, 0, "Vega", 4,
+    (ROM | KLI | ORI), 0, 0, 0, 30, 0, FED},
+    {4, FED, FED, 10000, 60000, 0, 0, 0, "Rigel", 5,
+    (ROM | KLI | ORI), 0, 0, 0, 30, 0, FED},
+    {5, FED, FED, 25000, 60000, 0, 0, 0, "Canopus", 7,
+    (ROM | KLI | ORI), 0, 0, 0, 30, 0, FED},
+    {6, FED, FED, 44000, 81000, 0, 0, 0, "Beta Crucis", 11,
+    (ROM | KLI | ORI), 0, 0, 0, 30, 0, FED},
+    {7, FED, FED, 39000, 55000, 0, 0, 0, "Organia", 7,
+    (ROM | KLI | ORI), 0, 0, 0, 30, 0, FED},
+    {8, FED, FED, 45000, 66000, 0, 0, 0, "Ceti Alpha V", 12,
+    (ROM | KLI | ORI), 0, 0, 0, 30, 0, FED},
+    {9, FED, FED, 32000, 74000, 0, 0, 0, "Alpha Centauri", 14,
+    (ROM | KLI | ORI), 0, 0, 0, 30, 0, FED},
+    {10, (ROM | PLHOME | PLCORE | PLFUEL | PLREPAIR | PLSHIPYARD | PLMETAL | PLARABLE | PLDILYTH),
+      ROM, 20000, 20000, 0, 0, 0, "Romulus", 7,
+    (FED | KLI | ORI), 0, 0, 0, 30, 0, ROM},
+    {11, ROM | PLCORE, ROM, 28000, 8000, 0, 0, 0, "Tauri", 5,
+    (FED | KLI | ORI), 0, 0, 0, 30, 0, ROM},
+    {12, ROM | PLCORE, ROM, 28000, 23000, 0, 0, 0, "Draconis", 8,
+    (FED | KLI | ORI), 0, 0, 0, 30, 0, ROM},
+    {13, ROM | PLCORE, ROM, 4000, 12000, 0, 0, 0, "Aldeberan", 9,
+    (FED | KLI | ORI), 0, 0, 0, 30, 0, ROM},
+    {14, ROM, ROM, 45000, 7000, 0, 0, 0, "Eridani", 7,
+    (FED | KLI | ORI), 0, 0, 0, 30, 0, ROM},
+    {15, ROM, ROM, 42000, 44000, 0, 0, 0, "Regulus", 7,
+    (FED | KLI | ORI), 0, 0, 0, 30, 0, ROM},
+    {16, ROM, ROM, 13000, 45000, 0, 0, 0, "Capella", 7,
+    (FED | KLI | ORI), 0, 0, 0, 30, 0, ROM},
+    {17, ROM, ROM, 40000, 25000, 0, 0, 0, "Sirius", 6,
+    (FED | KLI | ORI), 0, 0, 0, 30, 0, ROM},
+    {18, ROM, ROM, 25000, 44000, 0, 0, 0, "Indi", 4,
+    (FED | KLI | ORI), 0, 0, 0, 30, 0, ROM},
+    {19, ROM, ROM, 8000, 29000, 0, 0, 0, "Hydrae", 6,
+    (FED | KLI | ORI), 0, 0, 0, 30, 0, ROM},
+    {20, (KLI | PLHOME | PLCORE | PLFUEL | PLREPAIR | PLSHIPYARD | PLMETAL | PLARABLE | PLDILYTH),
+      KLI, 80000, 20000, 0, 0, 0, "Klingus", 7,
+    (FED | ROM | ORI), 0, 0, 0, 30, 0, KLI},
+    {21, KLI | PLCORE, KLI, 88000, 12000, 0, 0, 0, "Pollux", 6,
+    (FED | ROM | ORI), 0, 0, 0, 30, 0, KLI},
+    {22, KLI | PLCORE, KLI, 69000, 31000, 0, 0, 0, "Scorpii", 7,
+    (FED | ROM | ORI), 0, 0, 0, 30, 0, KLI},
+    {23, KLI | PLCORE, KLI, 73000, 5000, 0, 0, 0, "Castor", 6,
+    (FED | ROM | ORI), 0, 0, 0, 30, 0, KLI},
+    {24, KLI, KLI, 70000, 40000, 0, 0, 0, "Pleiades V", 10,
+    (FED | ROM | ORI), 0, 0, 0, 30, 0, KLI},
+    {25, KLI, KLI, 60000, 10000, 0, 0, 0, "Andromeda", 9,
+    (FED | ROM | ORI), 0, 0, 0, 30, 0, KLI},
+    {26, KLI, KLI, 54000, 40000, 0, 0, 0, "Lalande", 7,
+    (FED | ROM | ORI), 0, 0, 0, 30, 0, KLI},
+    {27, KLI, KLI, 90000, 37000, 0, 0, 0, "Lyrae", 5,
+    (FED | ROM | ORI), 0, 0, 0, 30, 0, KLI},
+    {28, KLI, KLI, 83000, 48000, 0, 0, 0, "Mira", 4,
+    (FED | ROM | ORI), 0, 0, 0, 30, 0, KLI},
+    {29, KLI, KLI, 54000, 21000, 0, 0, 0, "Cygni", 5,
+    (FED | ROM | ORI), 0, 0, 0, 30, 0, KLI},
+    {30, (ORI | PLHOME | PLCORE | PLFUEL | PLREPAIR | PLSHIPYARD | PLMETAL | PLARABLE | PLDILYTH),
+      ORI, 80000, 80000, 0, 0, 0, "Orion", 5,
+    (FED | ROM | KLI), 0, 0, 0, 30, 0, ORI},
+    {31, ORI | PLCORE, ORI, 72000, 69000, 0, 0, 0, "Procyon", 7,
+    (FED | ROM | KLI), 0, 0, 0, 30, 0, ORI},
+    {32, ORI | PLCORE, ORI, 91000, 94000, 0, 0, 0, "Ursae Majoris", 13,
+    (FED | ROM | KLI), 0, 0, 0, 30, 0, ORI},
+    {33, ORI | PLCORE, ORI, 85000, 70000, 0, 0, 0, "Antares", 7,
+    (FED | ROM | KLI), 0, 0, 0, 30, 0, ORI},
+    {34, ORI, ORI, 92000, 59000, 0, 0, 0, "Cassiopia", 9,
+    (FED | ROM | KLI), 0, 0, 0, 30, 0, ORI},
+    {35, ORI, ORI, 65000, 55000, 0, 0, 0, "El Nath", 7,
+    (FED | ROM | KLI), 0, 0, 0, 30, 0, ORI},
+    {36, ORI, ORI, 52000, 60000, 0, 0, 0, "Spica", 5,
+    (FED | ROM | KLI), 0, 0, 0, 30, 0, ORI},
+    {37, ORI, ORI, 64000, 80000, 0, 0, 0, "Polaris", 7,
+    (FED | ROM | KLI), 0, 0, 0, 30, 0, ORI},
+    {38, ORI, ORI, 56000, 89000, 0, 0, 0, "Arcturus", 8,
+    (FED | ROM | KLI), 0, 0, 0, 30, 0, ORI},
+    {39, ORI, ORI, 70000, 93000, 0, 0, 0, "Herculis", 8,
+    (FED | ROM | KLI), 0, 0, 0, 30, 0, ORI}
+  };
+  for (i = 0; i < NUMPLANETS; i++)
+  {
+    for (j = 0; j < MAXTEAM + 1; j++)
+    {
+      pdata[i].pl_tinfo[j].owner = pdata[i].pl_owner;
+      pdata[i].pl_tinfo[j].armies = pdata[i].pl_armies;
+      pdata[i].pl_tinfo[j].flags = pdata[i].pl_flags;
+      pdata[i].pl_tinfo[j].timestamp = 0;
+    }
+    pdata[i].pl_trevolt = 0;
+    pdata[i].pl_next = 0;
+    pdata[i].pl_prev = 0;
+    pdata[i].pl_gridnum = 0;
+  }
+  memcpy((char *) planets, (char *) pdata, MAXPLANETS * sizeof(struct planet));
+}
+/*-------------------------------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.  This version's been bronco-ified. :)
+ */
+
+static void
+genresources_bronco()
+{
+  int i, j;			/* looping vars */
+  int t;			/* temp var */
+
+  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) / 4) + SYSTEMS +
+      ((i / (NMETAL / 4)) * ((NUMPLANETS - SYSTEMS) / 4));
+    if (!(planets[t].pl_flags & PLMETAL & PLSURMASK))
+    {
+      planets[t].pl_flags |= PLMETAL;	/* OR in the metal flag */
+      planets[t].pl_flags |= PLREPAIR;
+    }
+    else
+      i--;
+  }
+  for (i = 0; i < NDILYTH; i++)
+  {				/* place the crystals */
+    t = lrand48() % ((NUMPLANETS - SYSTEMS) / 4) + SYSTEMS +
+      ((i / (NDILYTH / 4)) * ((NUMPLANETS - SYSTEMS) / 4));
+    if (!(planets[t].pl_flags & PLDILYTH & PLSURMASK))
+    {
+      planets[t].pl_flags |= PLDILYTH;	/* OR in the dilyth flag */
+      planets[t].pl_flags |= PLFUEL;
+    }
+    else
+      i--;
+  }
+  for (i = 0; i < NARABLE; i++)
+  {				/* place the farms */
+    t = lrand48() % ((NUMPLANETS - SYSTEMS) / 4) + SYSTEMS +
+      ((i / (NARABLE / 4)) * ((NUMPLANETS - SYSTEMS) / 4));
+    if (!(planets[t].pl_flags & PLARABLE & PLSURMASK) &&
+	!(planets[t].pl_flags & PLHOME))
+    {
+      planets[t].pl_flags |= PLARABLE | PLATYPE1;	/* OR in the arable flag */
+      planets[t].pl_flags |= PLAGRI;
+    }
+    else
+      i--;
+  }
+  for (i = 0; i < NUMPLANETS; i++)
+    for (j = 0; j < MAXTEAM + 1; j++)
+      if (j == planets[i].pl_owner)
+	planets[i].pl_tinfo[j].flags = planets[i].pl_flags;
+}
+
+
+
+/*
+ * Generate a complete galaxy. Uses ye old bronco planet setup.
+ */
+
+void
+gen_galaxy_4()
+{
+  GWIDTH = 100000;
+  NUMPLANETS = 40;
+  initbronco();			/* initialize planet structures */
+  genresources_bronco();	/* place the resources */
+  return;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pl_gen5.c	Sat Dec 06 04:37:03 1997 +0000
@@ -0,0 +1,544 @@
+/*--------------------------------------------------------------------------
+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.75)	/* 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 */
+	  }
+	}
+      } 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.  Generates like generator 3, only in a smaller
+ * environment
+ */
+
+void
+gen_galaxy_5()
+{
+  int t;
+
+  GWIDTH = 100000;
+  NUMPLANETS = 48;
+
+  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 */
+
+}