diff src/planets.c @ 6:8c6d5731234d

First entry of Paradise Server 2.9 patch 10 Beta
author darius
date Sat, 06 Dec 1997 04:37:04 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/planets.c	Sat Dec 06 04:37:04 1997 +0000
@@ -0,0 +1,1497 @@
+/*--------------------------------------------------------------------------
+NETREK II -- Paradise
+
+Permission to use, copy, modify, and distribute this software and its
+documentation, or any derivative works thereof, for any NON-COMMERCIAL
+purpose and without fee is hereby granted, provided that this copyright
+notice appear in all copies.  No representations are made about the
+suitability of this software for any purpose.  This software is provided
+"as is" without express or implied warranty.
+
+    Xtrek Copyright 1986                            Chris Guthrie
+    Netrek (Xtrek II) Copyright 1989                Kevin P. Smith
+                                                    Scott Silvey
+    Paradise II (Netrek II) Copyright 1993          Larry Denys
+                                                    Kurt Olsen
+                                                    Brandon Gillespie
+--------------------------------------------------------------------------*/
+
+
+#define PLANETS 1
+#define GRID 0			/* for space grid */
+
+#include "config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <setjmp.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <unistd.h>
+
+#include "struct.h"
+#include "data.h"
+#include "daemonII.h"
+#include "planets.h"
+#include "misc.h"
+#include "conquer.h"
+#include "player.h"
+#include "grid.h"
+#include "shmem.h"
+#include "terrain.h"
+
+
+/* define this if you want the experimental dragging-into-star-counts mod */
+#define GIVESTARKILLS
+
+#define	friendly(fred, bart) \
+	(!(fred->p_team & (bart->p_swar|bart->p_hostile)) && \
+	 !(bart->p_team & (fred->p_swar|fred->p_hostile)))
+
+
+/* defines dealing with growth timers */
+#define PLGFUEL		configvals->plgrow.fuel	/* time for growth of fuel
+						 * depot */
+#define PLGAGRI		configvals->plgrow.agri	/* time for growth of agri */
+#define PLGREPAIR	configvals->plgrow.repair	/* time for growth of
+							 * repair */
+#define PLGSHIP		configvals->plgrow.shipyard	/* time for growth of
+							 * shipyard */
+
+/* other defines */
+#define UCVISIBLE 40000		/* dist for uncloaked visibility */
+#define CVISMIN 12000		/* cloakers always visible distance */
+#define CVISSPEED 2000		/* cloak dist added per warp point */
+#define CVISIBLE 25000		/* dist for cloaked visibility */
+#define PLFIREDIST 1500		/* distance planets fire at players */
+#define PLVISDIST 5000		/* dist planets sense enemy players */
+#define REVOLT 200		/* chance out of 1000 of revolt start */
+#define STARTREV 8		/* for revolt timer */
+/*-------------------------------------------------------------------------*/
+
+
+
+
+
+
+/*-----------------------------MODULE VARIABLES----------------------------*/
+
+/* the list of all possible planet names */
+char *pnames[] =
+{
+  /* Federation planets */
+  "Rigel", "Canopus", "Beta Crucis", "Organia", "Deneb",
+  "Ceti Alpha V", "Altair", "Vega", "Alpha Centauri",
+  /* Romulan worlds */
+  "Eridani", "Aldeberan", "Regulus", "Capella", "Tauri",
+  "Draconis", "Sirius", "Indi", "Hydrae",
+  /* Klingon worlds */
+  "Pleiades V", "Andromeda", "Lalande", "Pollux", "Lyrae",
+  "Scorpii", "Mira", "Cygni", "Castor",
+  /* Orion worlds */
+  "Cassiopia", "El Nath", "Spica", "Procyon", "Polaris",
+  "Arcturus", "Ursae Majoris", "Herculis", "Antares",
+
+  /* new worlds */
+  "Planet 10", "Bezier", "Sequent", "Ophiuchi", "Lacaille",
+  "Luyten", "Pavonis", "Wolf 424", "Ross 882", "Cephei",
+  "Kruger", "Groombridge", "Maanen's Star", "Heinlein",
+  "Pixel", "Lazarus", "Mycroft", "Asimov", "Varley",
+  "Clarke's Star", "Ren", "Stimpy", "Foo", "Jolt Cola",
+  "Kelly Bundy", "Tyrell", "Roy", "Deckard", "Vangelis",
+  "Orpheus", "Xanth", "Tatooine", "Ludicrous", "Ogg",
+  "Scum", "Twink", "Chiapucci", "Bugno", "Hampsten", "Fignon",
+  "Paradise", "Azriel", "Gargamel", "Smurf Village",
+  "Praxis", "Acherner", "Arrakis", "Caladan", "Giedi Prime",
+  "Clue", "Paulina", "Sith", "Salusa", "Ahrain", "Cerranos",
+  "Darkurthe", "Dagobah", "Phaze", "Chatsubu", "Lemond",
+  "Bronco", "Vulcan", "Eden", "Klein", "Merckx", "Tarot",
+  "Mottet", "Roche", "Doorstop", "Shaedron", "Fondriest",
+
+  /* Bob's fave worlds */
+  "Wayne's World", "DanjerHaus", "Anvil", /* B-52s */ "Claire",
+  "Planet Reebok", "Sony Corp.", "SEGA!", "McWorld",
+  "Tokyo", "New York", "D.C.", "Atlanta",	/* places I've never been */
+   /* Tony */ "Levin",
+  "Planet Woogie", "Nancy", "Wilson",	/* real people */
+  "Beavis", "Butthead",
+  "Memolo",			/* Matt Memolo was murdered in Miami in July
+				 * of '93.  He was a really swell guy. "...he
+				 * would go far out of his way to give you
+				 * the shirt off his back." - ajc */
+  /* names from the T.V. shows */
+  "New Berlin",
+  /*
+   * "Bejor", "Cardassia" I'm not including these till I can spell them - RF
+   */
+
+  /* Mike's fave worlds */
+  "Melmac", "Order", "Yosemite", "New Chicago", "Ceptus", "Ork",
+  "Levi 501", "Toughskin", "Wonka",
+
+  /* book names */
+  "Terminus", "Magrathea", "Trantor", "Synnax", "Coruscant",
+
+  /* Moons, names, etc. */
+  "Io ", "Titan", "Europa", "Ganymede", "Charon",
+  "Tholia", "Gor", "Kzin", "Aerth",
+  "Proxima", "Cellust", "Calamar", "Icarus",
+  "New Prague",
+
+  /* How about the solar system? */
+  "Mercury", "Venus", "Mars", "Jupiter", "Saturn", "Neptune",
+  "Uranus", "Pluto",		/* are Neptune and Uranus in order? */
+
+#if 0
+  /* Player's names */
+  "Claypigeon", "Maxout", "Fungus", "Lynx",
+  "Bubbles", "KnightRaven", "Bolo", "Vladimir",
+  "Gajah Mada", "Trippix", "Shrew", "Bob Dobbs", "Wibble",
+  "Rogue"
+#endif
+};
+
+#define MAXNAMES (sizeof(pnames)/sizeof(char *))	/* # of planet names */
+
+char *homenames[] =		/* names of the race's home worlds */
+{
+  " ", "Earth", "Romulus", " ", "Klingus", " ", " ", " ",
+  "Orion"
+};
+
+
+/*
+ * This table is used to turn the four bits of resources flags into a three
+ * bit number.  The shipyard and the repair are ORed together.  All the non
+ * resource bits need to be masked off with PLRESMASK before this table is
+ * used
+ */
+int restores[16] = {0, 1, 2, 3, 4, 5, 6, 7, 1, 1, 3, 3, 5, 5, 7, 7};
+
+
+/*
+ * This is a matrix that determines the chance a planet has of popping.  The
+ * chance is expressed as a chance out of 100.  The matrix is accessed with
+ * the planet's atmosphere type and the resource bits after they have been
+ * converted to 3 bits with the table above.
+ */
+int popchance[4][8] = {
+  /*
+   * 000   00Z   0f0   0fZ   a00   a0Z   af0   afZ--the resources flags,
+   * Z=r|s
+   */
+  {2, 3, 2, 2, 5, 7, 4, 8},	/* poison */
+  {3, 5, 2, 4, 9, 11, 7, 12},	/* atmos #3 */
+  {5, 7, 4, 6, 12, 14, 10, 15},	/* atmos #2 */
+  {8, 12, 7, 10, 20, 24, 18, 23}/* atmos #1 */
+};
+
+
+/*
+ * This is a matrix that determines the multiplier for popping. When popping
+ * the armies on a planet will be multiplied by this multiplier to get the
+ * number of extra armies that grow.  A negative number indicates negative
+ * growth.
+ */
+float popmult[4][8] = {
+  /* 000      00Z    0f0    0fZ    a00    a0Z    af0   afZ  */
+  {-0.08, 0.00, -0.10, -0.03, 0.00, 0.05, -0.05, 0.05},	/* poison */
+  {0.03, 0.05, 0.02, 0.04, 0.06, 0.07, 0.06, 0.07},	/* atmos #3 */
+  {0.05, 0.07, 0.05, 0.06, 0.10, 0.11, 0.08, 0.10},	/* atmos #2 */
+  {0.09, 0.12, 0.08, 0.10, 0.17, 0.19, 0.15, 0.18}	/* atmos #1 */
+};
+
+
+/*
+ * This is a matrix that determines the maximum army capacity of a planet.
+ * Once this capacity is reached, no other armies can grow there.
+ */
+float popcap[4][8] = {
+  /*
+   * 000   00Z   0f0   0fZ   a00   a0Z   af0    afZ--the resources flags,
+   * Z=r|s
+   */
+  {5, 10, 7, 10, 15, 15, 10, 18},	/* poison */
+  {9, 14, 11, 14, 20, 20, 14, 22},	/* atmos #3 */
+  {12, 18, 15, 18, 25, 25, 19, 27},	/* atmos #2 */
+  {15, 22, 18, 25, 40, 35, 27, 40}	/* atmos #1 */
+};
+
+/*-------------------------------------------------------------------------*/
+
+
+
+
+
+
+
+
+#ifdef LEAGUE_SUPPORT
+extern void tlog_res();
+extern void tlog_bomb();
+extern void tlog_bres();
+extern void tlog_plankill();
+extern void tlog_revolt();
+extern void tlog_pop();
+#else
+#define tlog_res(a,b)
+#define tlog_bomb(a,b,c)
+#define tlog_bres(a,b,c)
+#define tlog_plankill(a,b,c)
+#define tlog_revolt(a)
+#define tlog_pop(a,b)
+#endif
+extern void scout_planet();
+extern int inflict_damage();
+extern void killmess();
+extern int enemy_admiral();
+extern off_t lseek();
+extern int write();
+
+/*------------------------------INTERNAL FUNCTIONS-------------------------*/
+
+void fill_planets();
+
+
+#ifndef NO_QSORT
+/* used by the qsort() in sortnames() below */
+static int
+comp_pl_name(a, b)
+  void *a, *b;
+{
+  return strcasecmp(((struct planet *) a)->pl_name,
+		    ((struct planet *) b)->pl_name);
+}
+#endif
+
+/*--------------------------------SORTNAMES---------------------------------*/
+/*
+ * This function sorts the planet into a alphabeticly increasing list.  It
+ * operates on the global planets structure.  This uses a simple bubble sort
+ * because I was too lazy to write anything more sophisticated.
+ */
+
+/*
+ * Bubble sorts suck.  Let's use the qsort library function instead, if
+ * available (HK)
+ */
+
+void
+sortnames()
+{
+#ifdef NO_QSORT
+  struct planet ptemp;		/* temporary space to hold planet */
+  int exchange;			/* flag for exchange made in pass */
+  int i;			/* looping var */
+  int t;			/* temp var */
+
+  exchange = 1;			/* no exchanges done yet */
+  while (exchange)
+  {				/* do until no exchanges */
+    exchange = 0;		/* no exchanges for this pass yet */
+    for (i = 0; i < NUMPLANETS - 1; i++)
+    {				/* go through list */
+      if (strcmp(planets[i].pl_name, planets[i + 1].pl_name) > 0)
+      {
+	t = planets[i].pl_no;	/* exchange planet numbers */
+	planets[i].pl_no = planets[i + 1].pl_no;
+	planets[i + 1].pl_no = t;
+	memcpy(&ptemp, &(planets[i]), sizeof(struct planet));
+	memcpy(&(planets[i]), &(planets[i + 1]), sizeof(struct planet));
+	memcpy(&(planets[i + 1]), &ptemp, sizeof(struct planet));
+	exchange++;		/* we made an exchange this pass */
+      }
+    }
+  }
+#else
+  int i;
+
+  qsort(planets, NUMPLANETS, sizeof(struct planet), comp_pl_name);
+  for (i = 0; i < NUMPLANETS; i++)	/* go through the planets */
+    planets[i].pl_no = i;	/* and fix their pl_no value */
+#endif
+}
+
+
+/*--------------------------------INITPLANETS-------------------------------*/
+/*
+ * This function generates the names and initializes the fields in the
+ * planets structure.  The planet names need to be sorted afterthe planets
+ * have been placed.
+ */
+
+void
+initplanets()
+{
+  int i, j;			/* looping vars */
+  int nused[MAXNAMES];		/* to mark which names are used */
+
+  for (i = 0; i < MAXNAMES; i++)/* go through all possible names */
+    nused[i] = 0;		/* mark name is not used yet */
+  for (i = 0; i < NUMPLANETS; i++)
+  {
+    planets[i].pl_no = i;	/* set planet number */
+    planets[i].pl_flags = PLPARADISE;	/* Paradise planet */
+    planets[i].pl_owner = NOBODY;	/* no owner yet */
+    planets[i].pl_x = 0;	/* just to intialize x and y */
+    planets[i].pl_y = 0;
+    j = lrand48() % MAXNAMES;	/* get a random name */
+    do
+    {				/* do until unused name found */
+      j = (j + 1) % MAXNAMES;	/* go on to next name in list */
+    } while (nused[j]);		/* until unused name found */
+    nused[j] = 1;		/* mark name as used */
+    strcpy(planets[i].pl_name, pnames[j]);	/* copy into planet struct */
+    planets[i].pl_namelen = strlen(pnames[j]);	/* set name's length */
+#if 1
+    planets[i].pl_hostile = 0;	/* planet doesn't hate anyone yet */
+#else
+    planets[i].pl_torbit = 0;	/* no teams orbiting */
+#endif
+    planets[i].pl_tshiprepair = 0;	/* zero the repair growth timer */
+    planets[i].pl_tagri = 0;	/* zero the agri growth timer */
+    planets[i].pl_tfuel = 0;	/* zero the fuel growth timer */
+    planets[i].pl_armies = 0;	/* no armies yet */
+    planets[i].pl_warning = 0;	/* no warning being counted down for */
+    planets[i].pl_system = 0;	/* not in a system yet */
+    planets[i].pl_hinfo = NOBODY;	/* no race has info on planet */
+    for (j = 0; j < MAXTEAM + 1; j++)
+    {				/* go through four races */
+      planets[i].pl_tinfo[j].owner = NOBODY;	/* do not know who owns it */
+      planets[i].pl_tinfo[j].armies = 0;	/* no armies on planet */
+      planets[i].pl_tinfo[j].flags = PLPARADISE;	/* know nothing about
+							 * flags */
+      planets[i].pl_tinfo[j].timestamp = 0;	/* set the timestamp */
+    }
+    planets[i].pl_trevolt = 0;	/* revolt timer not counting down */
+#if GRID
+    planets[i].pl_next = NULL;	/* set fields related to space grid */
+    planets[i].pl_previous = NULL;
+    planets[i].pl_gridnum = 0;
+#endif
+  }
+}
+
+
+
+
+/*-------------------------------GROWPLANETS------------------------------*/
+/*
+ * This function grows resources on planets.  It goes through all planets and
+ * updates the growth timers and checks for growth.  Independent planets do
+ * not grow.  This function also checks to see if any player in a starbase is
+ * orbiting a planet and adjusts the planet's growth rate if so.
+ */
+
+void
+growplanets()
+{
+  int i;			/* looping var */
+  struct planet *p;		/* to point within planets */
+  int add;			/* number to add to timers */
+
+  if (!status->tourn)
+    return;
+
+  if (!configvals->resource_bombing)
+    return;
+
+  for (i = 0; i < MAXPLAYER; i++)
+  {				/* go through all players */
+    struct player *py = &players[i];	/* and look for orbiting */
+    if ((py->p_status != PALIVE) ||	/* starbases */
+	(py->p_ship.s_type != STARBASE) ||
+	!(py->p_flags & PFORBIT))
+      continue;
+    p = &planets[py->p_planet];	/* found one, get planet */
+    p->pl_tfuel += 20;		/* give growth rate a boost */
+    p->pl_tagri += 30;		/* NOTE: change these if PLG consts */
+    p->pl_tshiprepair += 50;	/* change */
+  }
+  p = &planets[0];		/* start with first planet */
+  for (i = 0; i < NUMPLANETS; i++, p++)
+  {				/* through all planets */
+    if (p->pl_owner == NOBODY)	/* if independent then */
+      continue;			/* no growth */
+    add = p->pl_armies / 2;	/* rate based on armies */
+    p->pl_tfuel += add;		/* add to fuel timer */
+    p->pl_tfuel = (p->pl_tfuel > PLGFUEL) ? PLGFUEL : p->pl_tfuel;
+    if ((!(p->pl_flags & PLFUEL))	/* if no fuel */
+	&& (p->pl_flags & PLDILYTH)	/* and dilythium deposits */
+	&& (p->pl_tfuel >= PLGFUEL))
+    {				/* and timer high enough */
+      p->pl_flags |= (PLFUEL | PLREDRAW);	/* create fuel depot */
+      p->pl_tinfo[p->pl_owner].flags = p->pl_flags;
+      p->pl_tinfo[p->pl_owner].timestamp = status->clock;
+      tlog_res(p, "FUEL");
+    }
+    p->pl_tagri += add;		/* add to agri timer */
+    p->pl_tagri = (p->pl_tagri > PLGAGRI) ? PLGAGRI : p->pl_tagri;
+    if ((!(p->pl_flags & PLAGRI))	/* if no agri on planet */
+	&& (p->pl_flags & PLARABLE)	/* and arable */
+	&& (p->pl_tagri >= PLGAGRI))
+    {				/* and timer high enough */
+      p->pl_flags |= (PLAGRI | PLREDRAW);	/* create agri planet */
+      p->pl_tinfo[p->pl_owner].flags = p->pl_flags;
+      p->pl_tinfo[p->pl_owner].timestamp = status->clock;
+      tlog_res(p, "AGRI");
+    }
+    p->pl_tshiprepair += add;	/* add to ship/repair timer */
+    if ((!(p->pl_flags & PLREPAIR))	/* if not repair */
+	&& (p->pl_flags & PLMETAL)	/* and metal deposits */
+	&& (p->pl_tshiprepair >= PLGREPAIR))
+    {				/* and timer high enough */
+      p->pl_flags |= (PLREPAIR | PLREDRAW);	/* create repair station */
+      p->pl_tinfo[p->pl_owner].flags = p->pl_flags;
+      p->pl_tinfo[p->pl_owner].timestamp = status->clock;
+      tlog_res(p, "REPAIR");
+    }
+    p->pl_tshiprepair = (p->pl_tshiprepair > PLGSHIP) ? PLGSHIP :
+      p->pl_tshiprepair;	/* clamp value to max */
+    if ((!(p->pl_flags & PLSHIPYARD))	/* if not repair */
+	&& (p->pl_flags & PLMETAL)	/* and metal deposits */
+	&& (p->pl_tshiprepair >= PLGSHIP))
+    {				/* and timer high enough */
+      p->pl_flags |= (PLSHIPYARD | PLREDRAW);	/* create repair station */
+      p->pl_tinfo[p->pl_owner].flags = p->pl_flags;
+      p->pl_tinfo[p->pl_owner].timestamp = status->clock;
+      tlog_res(p, "SHIPYARD");
+    }
+  }
+}
+
+
+
+
+/*----------------------------------PVISIBLE------------------------------*/
+/*
+ * This function goes through the players and checks the other playes to see
+ * if an enemy is close enough to see him.  THIS FUNCTION SHOULD EVENTUALLY
+ * USE THE SPACE GRID.
+ */
+
+void
+pvisible()
+{
+  struct player *p;		/* to point to a player */
+  int i;			/* looping var */
+  int h;			/* looping var */
+  struct player *pl2;		/* to point to other players */
+  int dx, dy;			/* delta coords */
+  int dist;			/* to hold distance */
+
+  for (i = 0, p = &players[0]; i < MAXPLAYER; i++, p++)
+    p->p_flags &= ~PFSEEN;	/* clear all players' the seen flags */
+  for (i = 0, p = &players[i]; i < MAXPLAYER - 1; i++, p++)
+  {
+    if (p->p_status != PFREE &&	/* only do if player alive */
+	p->p_status != POBSERVE)
+    {				/* observers can't augment team scanning */
+      for (h = i + 1, pl2 = &players[h]; h < MAXPLAYER; h++, pl2++)
+      {
+	if ((pl2->p_status == PFREE) || (pl2->p_status == POBSERVE)
+	    || (pl2->p_flags & PFROBOT)	/* if not alive or robot or */
+	    || (pl2->p_team == p->p_team))	/* same team then continue */
+	  continue;
+	dx = ABS(pl2->p_x - p->p_x);	/* calc delta coords */
+	dy = ABS(pl2->p_y - p->p_y);
+	if ((dx > UCVISIBLE) || (dy > UCVISIBLE))	/* if obviously too far
+							 * away */
+	  continue;		/* then don't bother further */
+	dist = ihypot(dx, dy);
+	if (dist > UCVISIBLE)	/* out of range */
+	  continue;		/* on to next ship */
+	if ((dist < CVISMIN + CVISSPEED * pl2->p_speed) ||
+	    (!(pl2->p_flags & PFCLOAK)))
+	  pl2->p_flags |= PFSEEN;	/* if close then visible */
+	if ((dist < CVISMIN + CVISSPEED * p->p_speed) ||
+	    (!(p->p_flags & PFCLOAK)))
+	  p->p_flags |= PFSEEN;	/* second player */
+      }
+    }
+  }
+}
+
+
+
+void
+blast_resource(p, l, res, dival)
+  struct player *p;
+  struct planet *l;
+  int res;
+  double dival;
+{
+  if (status->tourn)
+  {
+    p->p_stats.st_di += dival;
+    p->p_stats.st_tresbomb++;
+    p->p_resbomb++;
+    status->resbomb++;
+  }
+  l->pl_flags &= ~res;
+  l->pl_tinfo[l->pl_owner].flags = l->pl_flags;
+  l->pl_tinfo[l->pl_owner].timestamp = status->clock;
+  l->pl_tinfo[p->p_team].flags = l->pl_flags;
+  l->pl_tinfo[p->p_team].timestamp = status->clock;
+  l->pl_flags |= PLREDRAW;	/* slate for redraw */
+}
+
+/*-----------------------------------PBOMB---------------------------------*/
+/*
+ * This function goes through the players and does the bombing if any player
+ * is bombing.  This will knock resources off of planets.  If a player is
+ * bombing a planet that another team owns, then that team will see the
+ * player by having the PFSEEN flag set.
+ */
+
+void
+pbomb()
+{
+  struct player *p;		/* to point to a player */
+  int i;			/* looping var */
+  struct planet *l;		/* to point to planet being bombed */
+  char buf[90];			/* to sprintf messages into */
+  char buf1[80];
+  int rnd;			/* to hold armies to knock off */
+
+  for (i = 0, p = &players[0]; i < MAXPLAYER; i++, p++)
+  {				/* go through playrs */
+    if ((p->p_status == PALIVE)	/* only do if player is alive */
+	&& (p->p_flags & PFORBIT)	/* and he is orbiting */
+	&& (p->p_flags & PFBOMB))
+    {				/* and he is bombing */
+
+      l = &planets[p->p_planet];/* get planet being bombed */
+
+      if ((!((p->p_swar | p->p_hostile) & l->pl_owner))
+	  && (l->pl_owner != NOBODY))
+      {
+	/* if he's non-hostile, quit bombing */
+	p->p_flags &= ~PFBOMB;
+	continue;
+      }
+      if ((l->pl_warning <= 0) && (l->pl_owner != NOBODY))
+      {				/* warning? */
+	l->pl_warning = 50 / PLFIGHTFUSE;	/* reset warning timer */
+	sprintf(buf, "We are being attacked by %s %s who is %d%% damaged.",
+		p->p_name, twoletters(p),
+		(100 * p->p_damage) / (p->p_ship.s_maxdamage));
+	sprintf(buf1, "%-3s->%-3s", l->pl_name, teams[l->pl_owner].shortname);
+	pmessage(buf, l->pl_owner, MTEAM | MBOMB, buf1);	/* send message */
+
+	/* CRD feature: shipyard guardians - MAK,  2-Jun-93 */
+	if ((l->pl_flags & PLSHIPYARD) && (!status->tourn))
+	{
+	  rescue(l->pl_owner, 0, l->pl_no);
+	}
+      }
+      p->p_swar |= l->pl_owner;	/* set player at war w/ owner */
+      rnd = (lrand48() % 50) + p->p_ship.s_bomb;	/* pick random number */
+      rnd = (int) ((float) rnd / 33.0 + 0.5);	/* calc armies bombed */
+      if (rnd <= 0)
+	continue;		/* can't bomb negative armies */
+      if (l->pl_armies > 4)
+      {				/* if armies to bomb then */
+	l->pl_armies -= rnd;	/* kill off armies */
+	tlog_bomb(l, p, rnd);
+	l->pl_armies = (l->pl_armies < 1) ? 1 : l->pl_armies;
+	l->pl_tinfo[l->pl_owner].armies = l->pl_armies;
+	l->pl_tinfo[l->pl_owner].timestamp = status->clock;
+	l->pl_tinfo[p->p_team].armies = l->pl_armies;
+	l->pl_tinfo[p->p_team].timestamp = status->clock;
+	if (l->pl_armies < 5)	/* if planet needs to be redrawn */
+	  l->pl_flags |= PLREDRAW;	/* schedule planet for redraw */
+	if (l->pl_owner != NOBODY)
+	{
+	  credit_armiesbombed(p, rnd, l);
+	}
+      }				/* now do the resource bombing */
+      if ((l->pl_armies > 4) ||
+	  (!configvals->resource_bombing))	/* no bombing resources if
+						 * armies */
+	continue;		/* on planet or in bronco-mode */
+#if defined(AEDILE) || defined(SLOW_BOMB)
+      l->pl_tfuel -= rnd * 5;	/* knock fuel timer down */
+#else
+      l->pl_tfuel -= rnd * 8;	/* knock fuel timer down */
+#endif
+      l->pl_tfuel = (l->pl_tfuel < 0) ? 0 : l->pl_tfuel;
+      if ((l->pl_tfuel == 0) && (l->pl_flags & PLFUEL))
+      {
+	blast_resource(p, l, PLFUEL, 0.10);
+	tlog_bres(l, p, "FUEL");
+      }
+#if defined(AEDILE) || defined(SLOW_BOMB)
+      l->pl_tagri -= rnd * 4;	/* attack the agri timer */
+#else
+      l->pl_tagri -= rnd * 6;	/* attack the agri timer */
+#endif
+      l->pl_tagri = (l->pl_tagri < 0) ? 0 : l->pl_tagri;
+      if ((l->pl_tagri == 0) && (l->pl_flags & PLAGRI))
+      {
+	blast_resource(p, l, PLAGRI, 0.25);
+	tlog_bres(l, p, "AGRI");
+      }
+#if defined(AEDILE) || defined(SLOW_BOMB)
+      l->pl_tshiprepair -= rnd * 5;	/* knock ship/repr down */
+#else
+      l->pl_tshiprepair -= rnd * 8;	/* knock ship/repr down */
+#endif
+      l->pl_tshiprepair = (l->pl_tshiprepair < 0) ? 0 :
+	l->pl_tshiprepair;
+      if ((l->pl_tshiprepair < PLGREPAIR) && (l->pl_flags & PLSHIPYARD))
+      {
+	blast_resource(p, l, PLSHIPYARD, 0.10);
+	tlog_bres(l, p, "SHIPYARD");
+      }
+      if ((l->pl_tshiprepair == 0) && (l->pl_flags & PLREPAIR))
+      {
+	blast_resource(p, l, PLREPAIR, 0.20);
+	tlog_bres(l, p, "REPAIR");
+      }
+    }
+  }
+}
+
+
+
+
+/*---------------------------------PFIRE-----------------------------------*/
+/*
+ * This function goes through the planets and sees if any enemy players are
+ * close enough to be fired upon by the planet.  It also checks to see if
+ * players are close enough to the planet so that the planet should be
+ * redrawn. Enemy planets will 'see' players that are very close to them.
+ * THIS FUNCTION SHOULD EVENTUALLY USE THE SPACE GRID.
+ */
+
+void
+pfire()
+{
+  struct player *p;		/* to point to a player */
+  int i, j;			/* looping vars */
+  struct planet *l;		/* to point to the planets */
+  int dx, dy;			/* to hold delta coords */
+  int dist;			/* to hold distance */
+  int dam;			/* to hold damage */
+  int boost;			/* for warp zones, total boost [BDyess] */
+
+  for (j = 0, p = &players[0]; j < MAXPLAYER; j++, p++)
+  {
+    if (p->p_status != PALIVE)
+      continue;
+    boost = 0;			/* default no bonus or penalty [BDyess] */
+    for (i = 0, l = &planets[0]; i < NUMPLANETS; i++, l++)
+    {
+      if ((p->p_team == l->pl_owner) && (PL_TYPE(*l) != PLSTAR)
+	  && !configvals->warpzone)
+	continue;		/* no, then continue */
+      dx = ABS(l->pl_x - p->p_x);	/* calc delta coorda between */
+      dy = ABS(l->pl_y - p->p_y);	/* planet and player */
+      dist = ihypot(dx, dy);
+
+      if (dist < configvals->warpzone)
+      {
+	/* within warp boost/block range [BDyess] */
+	if (p->p_team == l->pl_owner)
+	  boost += configvals->warpzone - dist;
+	else if (l->pl_owner != NOBODY &&
+		 ((p->p_swar | p->p_hostile) & l->pl_owner))
+	  boost -= configvals->warpzone - dist;
+      }
+
+      if (dx < 6 * PLFIREDIST && dy < 6 * PLFIREDIST)	/* redraw planet */
+	l->pl_flags |= PLREDRAW;/* if player is very close */
+
+      if (dist <= p->p_ship.s_scanrange)
+      {				/* check for scanners */
+	scout_planet(p->p_no, l->pl_no);
+#if 0
+	handled in scout_planet now.
+	    l->pl_hinfo |= p->p_team;
+	l->pl_tinfo[p->p_team].armies = l->pl_armies;
+	l->pl_tinfo[p->p_team].flags = l->pl_flags;
+	l->pl_tinfo[p->p_team].owner = l->pl_owner;
+	l->pl_tinfo[p->p_team].timestamp = status->clock;
+#endif
+      }
+
+      if (dist > PLVISDIST)
+	continue;
+      if ((dist < PLVISDIST) && (l->pl_owner != NOBODY)	/* enemy planet */
+	  && ((p->p_swar | p->p_hostile) & l->pl_owner))	/* see players */
+	p->p_flags |= PFSEEN;	/* let team see enemy */
+      if ((dist > PFIREDIST) ||
+	  ((dist > PFIREDIST / 2) &&
+	   (PL_TYPE(*l) == PLWHOLE)))	/* if not within range */
+	continue;		/* go on to next playert */
+      if (((p->p_swar | p->p_hostile) & l->pl_owner)
+	  || ((l->pl_owner == NOBODY)
+#if 1
+	      && (l->pl_hostile & p->p_team)
+#else
+	      && (l->pl_torbit & (p->p_team << 4))
+#endif
+	      && (l->pl_armies != 0))
+	  || (PL_TYPE(*l) == PLWHOLE) || (PL_TYPE(*l) == PLSTAR))
+      {
+	dam = l->pl_armies / 7 + 2;	/* calc the damage */
+	if (PL_TYPE(*l) == PLWHOLE)
+	{			/* if a wormhole... */
+	  /* ...place outside the new wormhole's radius. */
+	  if ((wh_effect[SS_WARP] && !(p->p_flags & PFWARP))
+	      || (!wh_effect[SS_WARP]))
+	  {
+	    p->p_x = l->pl_armies +
+	      (((PLFIREDIST / 2) + 50) * Cos[p->p_dir]);
+	    p->p_y = l->pl_radius +
+	      (((PLFIREDIST / 2) + 50) * Sin[p->p_dir]);
+	  }
+	  if ((p->p_speed > (p->p_ship.s_imp.maxspeed / 2)) &&
+	      (wh_effect[SS_IMPULSE]))
+	  {
+	    dam = ((p->p_ship.s_mass / 100) * (p->p_speed -
+					     p->p_ship.s_imp.maxspeed / 2));
+	  }
+	  else
+	    dam = 0;
+
+	}
+	else if (PL_TYPE(*l) == PLSTAR)	/* if planet is a star */
+	  dam = 150;		/* do massive damage */
+	/*
+	 * this needs to be reworked and most of it jammed into
+	 * inflict_damage
+	 */
+	p->p_whodead = i;	/* which planet is shooting */
+	if (dam > 0 && inflict_damage(0, 0, p, dam, KPLANET))
+	{
+	  struct player *killer = 0;
+	  p->p_whydead = KPLANET;	/* set killed by a planet */
+	  if (PL_TYPE(*l) == PLSTAR)
+	  {			/* killed by star? */
+#ifdef GIVESTARKILLS
+	    int pln;
+	    for (pln = 0, killer = &players[0];
+		 pln < MAXPLAYER;
+		 pln++, killer++)
+	    {
+	      if (killer->p_status != PALIVE)
+		continue;
+	      if (!friendly(killer, p) && killer->p_tractor == p->p_no
+		  && killer->p_flags & (PFTRACT | PFPRESS))
+	      {
+
+		killer->p_kills += 1 + (p->p_armies + p->p_kills) / 10;
+		killerstats(killer->p_no, p);
+		checkmaxkills(killer->p_no);
+		break;
+	      }
+	    }
+	    if (pln >= MAXPLAYER)
+	      killer = 0;
+#endif
+	  }
+	  killmess(p, killer);
+	  tlog_plankill(p, l, killer);
+	}
+      }
+    }
+    /* found the boost for this player, make adjustments if in warp [BDyess] */
+    if (configvals->warpzone && p->p_flags & PFWARP)
+    {
+      if (boost == 0 && p->p_zone > 0)
+      {				/* did get warp bonus, lost it */
+	if (p->p_desspeed > p->p_ship.s_warp.maxspeed)
+	  p->p_desspeed = p->p_ship.s_warp.maxspeed;
+      }
+      else if (boost < 0 && p->p_zone >= 0)
+      {				/* warp no longer allowed */
+	p->p_desspeed = p->p_ship.s_imp.maxspeed;
+	if (!configvals->warpdecel)
+	  p->p_flags &= ~PFWARP;
+      }
+    }
+    p->p_zone = boost;
+  }
+}
+
+
+
+
+/*---------------------------------REVOLT---------------------------------*/
+/*
+ * This function does the revolt of a planet.  It updates the revolt timer
+ * and prints the messages that warn the team.
+ */
+
+void
+revolt(l)
+  struct planet *l;		/* the planet to check */
+{
+  if (!configvals->revolts)
+    return;
+
+  if (l->pl_trevolt > 0)
+  {				/* revolt timer running? */
+    char buf[80];		/* to sprintf into */
+
+    {
+      int i;
+      for (i = 0; i < MAXPLAYER; i++)
+      {
+	if (players[i].p_status == PALIVE
+	    && (players[i].p_flags & (PFORBIT | PFDOCK)) == PFORBIT
+	    && players[i].p_planet == l->pl_no
+	    && players[i].p_team == l->pl_owner)
+	  return;		/* orbiting ship delays revolt */
+      }
+    }
+
+    l->pl_trevolt--;		/* dec the timer */
+    if ((l->pl_trevolt == 0) && (l->pl_armies > 2))
+    {
+      l->pl_trevolt = 0;	/* turn off revolt timer */
+      sprintf(buf, "The revolution on %s has been put down.",
+	      l->pl_name);	/* get message to display */
+      pmessage(buf, l->pl_owner, MTEAM | MCONQ, "PREFECT->");
+    }
+    else if ((l->pl_trevolt == 0) && (l->pl_armies == 2))
+    {
+      l->pl_trevolt = STARTREV;	/* more time til last army */
+      l->pl_armies--;		/* kill one army */
+      l->pl_tinfo[l->pl_owner].armies = l->pl_armies;
+      l->pl_tinfo[l->pl_owner].timestamp = status->clock;
+      sprintf(buf, "We cannot hold out much longer on %s",
+	      l->pl_name);	/* get message to display */
+      pmessage(buf, l->pl_owner, MTEAM | MCONQ, "PREFECT->");
+    }
+    else if (l->pl_trevolt == 0)
+    {
+      l->pl_trevolt = 0;	/* revolution succeeded */
+      sprintf(buf, "The planet %s has been lost to revolutionaries",
+	      l->pl_name);	/* get message to display */
+      pmessage(buf, l->pl_owner, MTEAM | MCONQ, "PREFECT->");
+
+      tlog_revolt(l);
+
+      l->pl_tinfo[l->pl_owner].timestamp = status->clock;
+      l->pl_tinfo[l->pl_owner].owner = NOBODY;
+      l->pl_owner = NOBODY;
+      l->pl_flags |= PLREDRAW;	/* slate for redraw */
+      checkwin(enemy_admiral(-1));	/* check for game end */
+
+    }
+  }
+  else
+  {				/* no revolt timer--check for start */
+    if ((l->pl_armies <= 2) && (!(l->pl_armies == 0))
+	&& ((lrand48() % 1000) <= REVOLT))
+    {
+      char buf[80];		/* to sprintf message into */
+
+      sprintf(buf, "There is civil unrest on %s", l->pl_name);
+      pmessage(buf, l->pl_owner, MTEAM | MCONQ, "PREFECT>>");
+      l->pl_trevolt = STARTREV;	/* time before revolution */
+    }
+  }
+}
+
+void 
+check_revolt()
+{
+  static int planetlist[MAXPLANETS];
+  static int count = 0;
+  int idx;
+  struct planet *l;
+
+  if (!status->tourn)
+    return;
+
+  if (count < 1)
+    fill_planets(planetlist, &count, -1);
+
+  idx = planetlist[--count];
+  l = &planets[idx];
+
+  if (l->pl_armies > 0 && l->pl_owner != NOBODY)
+    revolt(l);
+}
+
+/*-------------------------------------------------------------------------*/
+
+
+
+
+
+
+/* struct planet *stars[NUMPLANETS + 1]; */
+
+static void
+build_stars_array()
+{
+  int i;
+  struct planet *pl;
+
+  for (i = 0; i < NUMPLANETS; i++)
+  {
+    pl = &planets[i];
+    if (PL_TYPE(*pl) == PLSTAR)
+      stars[pl->pl_system] = i;
+  }
+}
+
+/*------------------------------VISIBLE FUNCTIONS-------------------------*/
+
+/*-------------------------------GEN_PLANETS-------------------------------*/
+/*
+ * This function generates a number of random planets.  The planets are
+ * arranged in systems and are also placed so that they are not too close to
+ * any other planets.  The races are then given home planets.
+ */
+
+void
+gen_planets()
+{
+  int i;
+  struct planet *pl;
+
+  status->clock = 0;		/* reset the timestamp clock */
+
+  switch (configvals->galaxygenerator)
+  {
+   case 2:
+    gen_galaxy_2();		/* Bob Forsman's compact galaxy generator */
+    break;
+   case 3:
+    gen_galaxy_3();		/* Heath's better race placement galaxy
+				 * generator */
+    break;
+   case 4:
+    gen_galaxy_4();		/* Mike's Bronco emulator */
+    break;
+   case 5:
+    gen_galaxy_5();		/* Mike's small-galaxy generator */
+    break;
+   case 6:
+    gen_galaxy_6();		/* Brandon's hack on Heath's to give 2 */
+    break;			/* systems to each race */
+   case 7:
+    gen_galaxy_7();		/* Eric Dormans deepspace galaxy gen, rooted
+				 * in galaxy gen 6. */
+    break;
+   case 1:
+   default:
+    gen_galaxy_1();		/* original paradiseII galaxy generator */
+    break;
+  }
+
+  if (configvals->galaxygenerator != 4)
+  {
+    /* gotta do this before they are sorted */
+    for (i = 0; i < NUMPLANETS; i++)
+    {
+      pl = &planets[i];
+      if (PL_TYPE(*pl) == PLSTAR ||
+	  ((pl->pl_system == 0) && (PL_TYPE(*pl) != PLWHOLE)))
+      {
+	pl->pl_radius = 0;
+	pl->pl_angle = 0;
+      }
+      else if (PL_TYPE(*pl) != PLWHOLE)
+      {
+	int dx, dy;
+	dx = pl->pl_x - planets[pl->pl_system - 1].pl_x;
+	dy = pl->pl_y - planets[pl->pl_system - 1].pl_y;
+	pl->pl_radius = ihypot(dx, dy);
+	pl->pl_angle = atan2((double) dy, (double) dx);
+      }
+    }
+    sortnames();		/* sort the names of planets */
+    build_stars_array();
+    if (configvals->neworbits)
+      pl_neworbit();
+    generate_terrain();
+  }
+}
+
+void 
+pl_neworbit()
+/*
+ * rearranges a pre-existing galaxy setup such that planets orbit at more
+ * "unique" distances from their star.  Asteroids look and probably play bad
+ * when all the planets are approx. the same dist from the star, so I'd
+ * suggest turning this on if you plan to have asteroids or orbiting planets
+ * on your server.  I'd suggest turning it on even if you don't. :)  -MDM
+ */
+{
+  register int i, j;
+  register struct planet *p;
+  register int numStars = 0, planetsThisStar = 0;
+#ifndef IRIX
+  int planetList[NUMPLANETS];
+#else
+  int planetList[70];
+#endif
+
+  /* find the number of stars */
+  for (i = 0; i < MAXPLANETS; i++)
+    if (PL_TYPE(planets[i]) == PLSTAR)
+      numStars++;
+
+  /* for each star, find the number of planets, and the average distance */
+
+  for (i = 1; i <= numStars; i++)
+  {
+    planetsThisStar = 0;
+    for (j = 0; j < MAXPLANETS; j++)
+      if (planets[j].pl_system == i)
+	planetList[planetsThisStar++] = j;
+
+    /*
+     * now move the planets such that each planet we came across gets its
+     * previous distance from it's star, times (it's position in the
+     * planetList array)/(planetsThisStar/1.6).  also make sure that new
+     * radius isin't so close to star ship can't orbit it.  Heh.  Separate
+     * the men from the boyz, eh?
+     */
+
+    for (j = 0; j < planetsThisStar; j++)
+    {
+      planets[planetList[j]].pl_radius =
+	(int) ((float) planets[planetList[j]].pl_radius *
+	       ((float) (j + 1) / (float) (planetsThisStar / 1.6))) + 1500;
+      planets[planetList[j]].pl_x =
+	planets[stars[i]].pl_x +
+	(int) ((float) cos(planets[planetList[j]].pl_angle) *
+	       (float) planets[planetList[j]].pl_radius);
+      planets[planetList[j]].pl_y =
+	planets[stars[i]].pl_y +
+	(int) ((float) sin(planets[planetList[j]].pl_angle) *
+	       (float) planets[planetList[j]].pl_radius);
+    }
+  }
+}
+
+void
+moveplanets()
+{
+  register int i;		/* for looping */
+  register struct planet *l;	/* to point to individual plaent */
+
+  if (stars[1] < 0)
+    build_stars_array();
+
+  /* totally experimental planet moving stuff */
+  for (i = 0; i < NUMPLANETS; i++)
+  {
+    int x, y;
+    double r;
+    l = &planets[i];
+    if (PL_TYPE(*l) == PLSTAR || l->pl_system == 0)
+      continue;			/* write code for them another time */
+
+    r = l->pl_radius;
+    l->pl_angle += configvals->planupdspd * 1e2 / sqrt(r * r * r);
+    if (l->pl_angle > 2 * M_PI)
+      l->pl_angle -= 2 * M_PI;
+    x = planets[stars[l->pl_system]].pl_x + cos(l->pl_angle) * l->pl_radius;
+    y = planets[stars[l->pl_system]].pl_y + sin(l->pl_angle) * l->pl_radius;
+    move_planet(i, x, y, 1);
+  }
+}
+
+
+/*
+ * This function pops the armies on planets.  It now uses the tables that are
+ * in this module.  Negative growth is supported.
+ */
+
+static void
+pop_one_planet1(l)
+  struct planet *l;
+{
+  int r;			/* to hold resource index */
+  int a;			/* to hold atmosphere index */
+  int t;			/* temp var */
+  float ft;			/* another temp */
+
+  r = (l->pl_flags & PLRESMASK) >> PLRESSHIFT;	/* get resource bits */
+  r = restores[r];		/* convert to 3 bits */
+  a = l->pl_flags & PLATMASK;	/* get atmosphere bits */
+  a = a >> PLATSHIFT;		/* shift to lower two bits of int */
+
+#ifdef UFL
+  t = status2->league ? popchance[a][r] : 8;
+#else
+  t = popchance[a][r];		/* get pop chance */
+#endif
+  if (t < lrand48() % 100)	/* if planet misses chance */
+    return;			/* then on to next planet */
+  ft = popmult[a][r];		/* get pop multiplier */
+  if (ft >= 0)
+  {				/* positive multiplier */
+    int incr;
+
+    if (l->pl_armies >= popcap[a][r])
+      return;
+
+    if (l->pl_armies < 4)	/* chance of going over four */
+      l->pl_flags |= PLREDRAW;	/* slate planet for redraw */
+    if (configvals->new_army_growth)
+#ifdef AEDILE
+      incr = 0.5 + ft * 2.0 * (float) (lrand48() % 6 + 3);
+#else
+      incr = 1 + 0.5 + ft * (float) (l->pl_armies);
+#endif
+    else
+      /* what about agri? */
+      incr = 1 + lrand48() % 3;	/* bronco is always 1-3 armies/pop */
+    tlog_pop(l, incr);
+    l->pl_armies += incr;	/* add on multiplier armies */
+    l->pl_tinfo[l->pl_owner].armies = l->pl_armies;
+    l->pl_tinfo[l->pl_owner].timestamp = status->clock;
+  }
+  else
+  {				/* negative multiplier */
+    int decr;
+    if (l->pl_armies < 4)	/* no killing all the armies on */
+      return;			/* a planet */
+    l->pl_flags |= PLREDRAW;	/* slate planet for redraw */
+    decr = 1 + 0.5 - ft * (float) (l->pl_armies);
+    tlog_pop(l, -decr);
+    l->pl_armies -= decr;	/* subtract armies */
+    l->pl_armies = (l->pl_armies < 0) ? 0 : l->pl_armies;
+    if (l->pl_armies <= 0)
+    {				/* if all died then */
+      l->pl_armies = 0;		/* no negative armies */
+      l->pl_tinfo[l->pl_owner].armies = 0;	/* old owner knows */
+      l->pl_tinfo[l->pl_owner].timestamp = status->clock;
+      l->pl_tinfo[l->pl_owner].owner = NOBODY;
+      l->pl_owner = NOBODY;	/* planet is neutral */
+    }
+    l->pl_tinfo[l->pl_owner].armies = l->pl_armies;
+    l->pl_tinfo[l->pl_owner].timestamp = status->clock;
+    if (l->pl_armies == 0)	/* if all armies died */
+      checkwin(enemy_admiral(-1));	/* check if game over */
+  }
+}
+/*
+ * */
+
+static void
+pop_one_planet2(l)
+  struct planet *l;
+{
+  int delta = 0;
+  int atmosphere = (l->pl_flags & PLATMASK) >> PLATSHIFT;
+  int surface = (l->pl_flags & PLSURMASK) >> PLSURSHIFT;
+
+  if (l->pl_armies < 4 && (l->pl_flags & PLAGRI))
+    delta++;
+
+  if (atmosphere == 0)
+  {
+    if (l->pl_armies >= 4 && drand48() < 0.5)
+    {
+      delta--;
+    }
+  }
+  else if (atmosphere < 3)
+  {
+    if (drand48() <
+	((atmosphere == 1)
+	 ? (l->pl_armies < 4 ? 0.2 : 0.1)
+	 : (l->pl_armies < 4 ? 0.5 : 0.2)))
+    {
+      delta++;
+    }
+  }
+  else
+  {
+    if (drand48() < (l->pl_armies < 4 ? 0.3 : 0.2))
+    {
+      static int table[] = {2, 2, 2, 3, 3, 3, 4, 4};
+      int max = table[surface];
+      delta++;
+      if (l->pl_flags & PLAGRI && l->pl_armies >= 4)
+	max++;			/* armies<4 handled at top */
+      delta += lrand48() % max;
+    }
+  }
+
+  if (l->pl_armies == 0 && delta > 1)
+    delta = 1;			/* training that first army is tough */
+
+  tlog_pop(l, delta);
+
+  if (delta > 0 &&
+      l->pl_armies > popcap[atmosphere]
+      [restores[(l->pl_flags & PLRESMASK) >> PLRESSHIFT]])
+    delta = 0;
+  l->pl_armies += delta;
+
+  /*
+   * I doubt this if statement will ever get executed unless someone's
+   * frobbing shmem
+   */
+  if (l->pl_armies <= 0)
+  {				/* if all died then */
+    l->pl_armies = 0;		/* no negative armies */
+
+    tlog_revolt(l);		/* well, not exactly. */
+
+    l->pl_tinfo[l->pl_owner].armies = 0;	/* old owner knows */
+    l->pl_tinfo[l->pl_owner].timestamp = status->clock;
+    l->pl_tinfo[l->pl_owner].owner = NOBODY;
+    l->pl_owner = NOBODY;	/* planet is neutral */
+    checkwin(enemy_admiral(-1));/* check if game over */
+  }
+
+  l->pl_tinfo[l->pl_owner].armies = l->pl_armies;
+  l->pl_tinfo[l->pl_owner].timestamp = status->clock;
+}
+
+void
+pop_one_planet(l)
+  struct planet *l;
+{
+#if 0
+  printf("popping planet #%d  %x\n", l->pl_no, l->pl_owner);
+  fflush(stdout);
+#endif
+
+  switch (configvals->popscheme)
+  {
+   case 1:
+    pop_one_planet2(l);
+    break;
+   default:
+   case 0:
+    pop_one_planet1(l);
+    break;
+  }
+}
+
+
+/*-------------------------------UDPLANETS----------------------------------*/
+
+void
+fill_planets(plist, count, owner)
+  int *plist;			/* array */
+  int *count;			/* scalar */
+  int owner;
+{
+  int i;
+  *count = 0;
+  for (i = 0; i < configvals->numplanets; i++)
+  {
+    if (owner < 0 || planets[i].pl_owner == owner)
+      plist[(*count)++] = i;
+  }
+
+  for (i = *count - 1; i > 0; i--)
+  {
+    int idx = lrand48() % (i + 1);
+    int temp = plist[idx];
+    plist[idx] = plist[i];
+    plist[i] = temp;
+  }
+}
+
+int
+find_other_team(teammask)
+  int teammask;
+{
+  int counts[NUMTEAM];
+  int i;
+  for (i = 0; i < NUMTEAM; i++)
+    counts[i] = 0;
+  for (i = 0; i < MAXPLAYER; i++)
+  {
+    int teamidx = mask_to_idx(players[i].p_team);
+    if (teamidx >= 0 && teamidx < NUMTEAM && !(teammask & (1 << teamidx)))
+      counts[teamidx]++;
+  }
+
+  {
+    int max = -1;
+    int rval = 0;
+    for (i = 0; i < NUMTEAM; i++)
+    {
+      if (counts[i] > max && !(teammask & (1 << i)))
+      {
+	max = counts[i];
+	rval = 1 << i;
+      }
+    }
+    return rval;
+  }
+}
+
+void
+popplanets()
+{
+  register int i;		/* for looping */
+  register struct planet *l;	/* to point to individual plaent */
+
+  if (!status->tourn)		/* check t-mode */
+    return;			/* do not pop planets */
+
+  switch (configvals->popchoice)
+  {
+   case 0:
+    {
+      static int fuse = 0;
+      if (++fuse < PLANETFUSE)
+	return;			/* nothing to do */
+      fuse = 0;
+      for (i = 0, l = &planets[i]; i < NUMPLANETS; i++, l++)
+      {
+	if ((l->pl_armies == 0) ||
+	    (PL_TYPE(*l) == PLSTAR) ||
+	    (PL_TYPE(*l) == PLWHOLE))	/* if no armies to pop */
+	  continue;		/* go to next planet */
+#if 0
+	if (l->pl_owner != NOBODY)	/* only team planets can revolt */
+	  revolt(l);		/* check for revolt */
+#endif
+	pop_one_planet(l);
+      }
+    } break;
+   case 1:
+    {
+#if 0
+      static int indplanets[MAXPLANETS];
+      static int indcount = 0;
+#endif
+      static int Aplanets[MAXPLANETS];
+      static int Acount = 0, Amask = 0;
+      static int Bplanets[MAXPLANETS];
+      static int Bcount = 0, Bmask = 0;
+
+      int INDchance;
+      float Achance, Bchance;
+      float f;
+
+      /* make sure there's planets in the lists */
+#if 0
+      if (indcount < 1)
+	fill_planets(indplanets, &indcount, NOBODY);
+#endif
+      if (Acount < 1)
+      {
+	Amask = find_other_team(Bmask);
+	fill_planets(Aplanets, &Acount, Amask);
+      }
+      if (Bcount < 1)
+      {
+	Bmask = find_other_team(Amask);
+	fill_planets(Bplanets, &Bcount, Bmask);
+      }
+
+      /* figure out the probabilities */
+      INDchance = Achance = Bchance = 0;
+      for (i = 0; i < configvals->numplanets; i++)
+      {
+	if (planets[i].pl_owner == Amask)
+	  Achance += 1.0;
+	else if (planets[i].pl_owner == Bmask)
+	  Bchance += 1.0;
+	else if (!((PL_TYPE(planets[i]) == PLSTAR) ||
+		   (PL_TYPE(planets[i]) == PLWHOLE)))
+	  /* if (planets[i].pl_owner == NOBODY) */
+	  INDchance += 1.0;
+      }
+
+#ifdef LOOSING_ADVANTAGE
+      {
+	double la = LOOSING_ADVANTAGE;
+	if (Achance < Bchance)
+	  Achance *= (la - (la - 1) * Achance / Bchance);
+	else
+	  Bchance *= (la - (la - 1) * Bchance / Achance);
+      }
+#endif
+
+      f = drand48() * (INDchance + Achance + Bchance);
+      if (f < INDchance)
+      {
+#if 0				/* 3rd-race planets and INDs don't pop */
+	pop_one_planet(&planets[indplanets[--indcount]]);
+#endif
+      }
+      else if (f - INDchance < Achance)
+      {
+	pop_one_planet(&planets[Aplanets[--Acount]]);
+      }
+      else
+      {
+	pop_one_planet(&planets[Bplanets[--Bcount]]);
+      }
+
+    } break;
+  }
+}
+
+
+
+
+
+/*----------------------------------PLFIGHT--------------------------------*/
+/*
+ * This function does the fighting for a planet.  It decs the warning timer
+ * and clears the REDRAW flag.  It then handles the bombing for the players.
+ * It then goes on to see if a player is visible to the other team by
+ * checking the closeness of other players.  The planets are then checked to
+ * see if they are close enough to fire on enemy players.
+ */
+
+void
+plfight()
+{
+  register int h;		/* looping vars */
+  register struct planet *l;	/* for looping through planets */
+
+  for (h = 0, l = &planets[h]; h < NUMPLANETS; h++, l++)
+  {
+    l->pl_flags &= ~PLREDRAW;	/* clear the PLDRAW flag */
+    if (l->pl_warning > 0)	/* check if timer needs dec */
+      l->pl_warning--;		/* dec the warning timer */
+  }
+  pbomb();			/* go do bombing for players */
+  pvisible();			/* check visibility w/ other players */
+  pfire();			/* let planets fire on other players */
+}
+
+
+
+
+/*-------------------------------SAVE_PLANETS-----------------------------*/
+/*
+ * This function saves the planets structure to disk.  The plfd variable is a
+ * handle on the previously opened .planets file.  The function also saves
+ * the status to the glfd file.
+ */
+
+void
+save_planets()
+{
+  if (plfd >= 0)
+  {				/* if plfd file open */
+    (void) lseek(plfd, (long) 0, 0);	/* save the planets */
+    (void) write(plfd, (char *) planets, sizeof(struct planet) * MAXPLANETS);
+  }
+  if (glfd >= 0)
+  {				/* if glfd file open then */
+    (void) lseek(glfd, (long) 0, 0);	/* save the status */
+    (void) write(glfd, (char *) status, sizeof(struct status));
+  }
+}
+
+/*-------------------------------------------------------------------------*/
+
+
+
+/*----------END OF FILE--------*/