#include "copyright.h"
#include "galaxy.h"
#include "process.h"


/* internal functions */

int      nextgame _PROTO((char *glist[MAXGAMES]));


#ifdef __STDC__
void
at_order(player * P, strlist ** s)
#else
void
at_order(P, s)
strlist ** s;
player * P;
#endif
{
char *         ns = getstr(0);
alliance *     a;
alliance *     plist;
player *       P2;

   if (ns[0]) {
      plist = 0;
      do {
	 P2 = identify(players, ns);
	 if (P2) {
	    a = alloc(sizeof(alliance));
	    a->who = P2;
	    addlist(&plist, a);
	 } else
	    mistake(P, *s, "Player not recognized");
	 ns = getstr(0);
      }
      while (ns[0]);
      for (a = plist; a; a = a->next)
	 addlist(&a->who->messages, makestrlist(""));
      while ((*s)->next) {
	 (*s) = (*s)->next;
	 if (getstr((*s)->s[0])[0] == '@')
	    return;
	 for (a = plist; a; a = a->next)
	    addlist(&a->who->messages, makestrlist((*s)->s[0]));
	 (*s)->s[0][0] = 0;
      }
      freelist(plist);
   } else {
      addlist(&messages, makestrlist(""));
      while ((*s)->next) {
	 (*s) = (*s)->next;
	 if (getstr((*s)->s[0])[0] == '@') {
	    return;
	 }
	 addlist(&messages, makestrlist((*s)->s[0]));
	 (*s)->s[0][0] = 0;
      }
   }
}

#ifdef __STDC__
void
a_order(player * P, strlist ** s)
#else
void
a_order(P, s)
strlist ** s;
player * P;
#endif
{
player *       P2;
alliance *     a;

   P2 = identify(players, getstr(0));
   if (!P2) {
      mistake(P, *s, "Player not recognized");
      return;
   }
   for (a = P->allies; a; a = a->next) {
      if (a->who == P2) {
	 return;
      }
   }
   if (!a && P2 != P) {
      a = alloc(sizeof(alliance));
      a->who = P2;
      addlist(&P->allies, a);
   }
}

#ifdef __STDC__
void
b_order(player * P, strlist ** s)
#else
void
b_order(P, s)
strlist ** s;
player * P;
#endif
{
group      *g;
group      *g2;
int        i;
char       *ns;

   g = findgroup(P, getstr(0));
   if (!g) {
      mistake(P, *s, "Group not recognized");
      return;
   }
   ns = getstr(0);
   if (!memicmp(ns, "fleet", 5)) {
      if (g->dist) {
         mistake(P, *s, "Fleet is in hyperspace");
         return;
      }
      g->thefleet = 0;
      return;
   }
   i = atoi(ns);
   if (i >= g->ships) {
      mistake(P, *s, "Not enough ships in group");
      return;
   }
   g2 = alloc(sizeof(group));
   *g2 = *g;
   g2->ships = i;
   g->ships -= i;
   g->thefleet = 0;
   addlist(&P->groups, g2);
}

#ifdef __STDC__
void
c_order(player * P, strlist ** s)
#else
void
c_order(P, s)
strlist ** s;
player * P;
#endif
{
char *    ns;
int       i;

   ns = getstr(0);
   i = strlen(ns);
   while (i && !isalnum(ns[i - 1]))
      i--;
   ns[i] = 0;
   if (!ns[0]) {
      mistake(P, *s, "No new race name given");
      return;
   }
   if (nametop(players, ns)) {
      mistake(P, *s, "Race name already in use");
      return;
   }
   nstrcpy(P->name, ns, NAMESIZE);
   if (P->namecase)
      ckcase(P->name);
}

#ifdef __STDC__
void
d_order(player * P, strlist ** s)
#else
void
d_order(P, s)
strlist ** s;
player * P;
#endif
{
char       *ns;
fleetname  *fl;
shiptype   *t;
int 	    i;
/* I wish I could remember how to do this right now.   I know that
   inserting a constant down there isn't the best idea.  Basically
   I'm trying to make nproducts = sizeof(productname[]);  Does that
   work?  I'm too lazy to find out right now.  -RJS

const int   nproducts = sizeof(productname)...
*/

   ns = getstr(0);
   if (!ns[0]) {
      mistake(P, *s, "No ship type name given");
      return;
   }

   if (identify (P->fleetnames, ns)) {
      mistake (P, *s, "Name already in use for fleet");
      return;
   }

/* Occasionally someone designs a ship called "Cargo" or something, then
   doesn't understand why the planet didn't produce the ship when they
   do "P planet Cargo" :)  This will fix this problem.  - RJS */

/* need to change that '7' down there with something that will change
   with the array.  Yea, I know.  I'm being anal.  But when it comes
   back to haunt us...    -RJS */

   for(i=0; i < 7;i++) {
      if(productname[i] && !strcmpl(productname[i],ns)) {
 	 mistake(P, *s, "Ship name can not be the same as a product name");
	 return;
      }
   }

   if (nametop(P->shiptypes, ns)) {
      mistake(P, *s, "Ship type name already in use");
      return;
   }

   if (!memicmp(ns, "fleet", 5)) {
      ns = getstr(0);
      if (!ns[0]) {
	 mistake (P, *s, "No fleet name given");
	 return;
      }
      if (identify (P->fleetnames, ns)) {
	 mistake (P, *s, "Fleet name already in use");
	 return;
      }
      if (identify (P->shiptypes, ns)) {
	 mistake (P, *s, "Name already in use for ship type");
	 return;
      }
      fl = alloc (sizeof (fleetname));
      nstrcpy (fl->name, ns, NAMESIZE);
      fl->fleetspeed = 1000.0;
      addlist (&P->fleetnames, fl);
      if (P->namecase)
	 ckcase (fl->name);
      return;
   }

   t = alloc(sizeof(shiptype));
   nstrcpy(t->name, ns, NAMESIZE);
   t->drive = atof(getstr(0));
   if (t->drive < 1)
      t->drive = 0;
   t->attacks = atoi(getstr(0));
   t->weapons = atof(getstr(0));
   if (t->weapons < 1)
      t->attacks = 0;
   if (!t->attacks)
      t->weapons = 0;
   t->shields = atof(getstr(0));
   if (t->shields < 1)
      t->shields = 0;
   t->cargo = atof(getstr(0));
   if (t->cargo < 1)
      t->cargo = 0;
   if (!t->drive && !t->attacks && !t->shields && !t->cargo) {
      mistake(P, *s, "At least one component must be non-zero");
      free(t);
      return;
   }
   addlist(&P->shiptypes, t);
   if (P->namecase)
      ckcase(t->name);
}

#ifdef __STDC__
void
e_order(player * P, strlist ** s)
#else
void
e_order(P, s)
strlist ** s;
player * P;
#endif
{
shiptype   *t;
fleetname  *fl;
group      *g;
planet     *p;
char       *ns;

   ns = getstr (0);
   t = nametop (P->shiptypes, ns);
   fl = identify(P->fleetnames, ns);
   if (!t && !fl) {
      mistake(P, *s, "Ship or fleet type not recognized");
      return;
   }

   if (fl) {
      for (g=P->groups; g; g=g->next)
         if ((g->thefleet == fl)&&(g->dist)) {
             mistake(P, *s, "Group is in hyperspace");
             return;
	 }
      for (g=P->groups; g; g=g->next)
	 if (g->thefleet == fl)
	    g->thefleet = 0;
      removelist (&P->fleetnames, fl);
      return;
   }

   for (g = P->groups; g; g = g->next)
      if (g->type == t) {
	 mistake(P, *s, "Some of these ships still exist");
	 return;
      }
   if (g)
      return;
   for (p = planets; p; p = p->next)
      if (p->producingshiptype == t) {
	 mistake(P, *s, "Some of these ships are still being produced");
	 return;
      }
   if (p)
      return;
   removelist(&P->shiptypes, t);
}

#ifdef __STDC__
void
f_order(player * P, strlist ** s)
#else
void
f_order(P, s)
strlist ** s;
player * P;
#endif
{
player     *P2;

   P2 = identify(players, getstr(0));
   if (!P2) {
      mistake(P, *s, "Player not recognized");
      return;
   }
   if (P2->addr[0])
      sprintf(buf, "The address of %s is %s", P2->name, P2->addr);
   else
      sprintf(buf, "There is currently no address for %s.", P2->name);
   addlist(&P->messages, makestrlist(""));
   addlist(&P->messages, makestrlist(buf));
}

#ifdef __STDC__
void
g_order(player * P, strlist ** s)
#else
void
g_order(P, s)
strlist ** s;
player * P;
#endif
{
planet *   p;
group *    g;
group *    g2;
shiptype * t;
double     x;
double     y;
double     z;
char *     ns;
int        i;

   g = findgroup(P, getstr(0));
   if (!g) {
      mistake(P, *s, "Group not recognized");
      return;
   }
   if (g->dist) {
      mistake(P, *s, "Group is in hyperspace");
      return;
   }
   p = g->where;
   t = g->type;
   x = INDPERSHIP * ((1 - g->drive / P->drive) * t->drive +
	   (1 - g->weapons / P->weapons) * weaponmass(t) +
	   (1 - g->shields / P->shields) * t->shields +
	   (1 - g->cargo / P->cargo) * t->cargo);
   y = p->ind * .75 + p->pop * .25 - p->spent;
   ns = getstr(0);
   if (ns[0]) {
      i = atoi(ns);
      if (i == 0)
	 i = g->ships;
      if (i > g->ships) {
	 mistake(P, *s, "Not enough ships, all available used");
	 i = g->ships;
      }
      if (i != g->ships) {
	 g2 = alloc(sizeof(group));
	 *g2 = *g;
	 addlist(&P->groups, g2);
	 g->ships -= i;
	 g2->ships = i;
	 g = g2;
      }
      z = y / i;
      if (z >= x)
	 memcpy(&g->drive, &P->drive, 4 * sizeof(double));
      else {
	 z /= x;
	 x *= z;
	 g->drive = g->drive + (P->drive - g->drive) * z;
	 g->weapons = g->weapons + (P->weapons - g->weapons) * z;
	 g->shields = g->shields + (P->shields - g->shields) * z;
	 g->cargo = g->cargo + (P->cargo - g->cargo) * z;
      }
      cktech(g);
   } else {
      i = g->ships;
      if (x * i > y) {
	 i = y / x;
	 g2 = alloc(sizeof(group));
	 *g2 = *g;
	 addlist(&P->groups, g2);
	 g->ships -= i;
	 g2->ships = i;
	 g = g2;
      }
      memcpy(&g->drive, &P->drive, 4 * sizeof(double));
      cktech(g);
   }
   p->spent += x * i;
}

#ifdef __STDC__
void
i_order(player * P, strlist ** s)
#else
void
i_order(P, s)
strlist ** s;
player * P;
#endif
{
group      *g;
group      *g2;
planet     *p;
int        i;
fleetname  *fl;
int        j;
char       *ns;

   ns = getstr(0);
   g = findgroup(P, ns);
   fl = identify (P->fleetnames, ns);
   if (!g && !fl) {
      mistake(P, *s, "Group or fleet not recognized");
      return;
   }
   if (fl) {
      p = identify (planets, getstr(0));
      if (!p) {
	 mistake (P, *s, "Planet not recognized");
	 return;
      }
      for (g=P->groups; g; g=g->next) {
         if ((g->thefleet == fl)&&(g->dist)) {
	    mistake (P, *s, "Fleet is in hyperspace");
	    return;
         }
         if ((g->thefleet == fl)&&(!g->type->drive)) {
	    mistake (P, *s, "Fleet cannot move");
	    return;
         }
      }
      for (g=P->groups; g; g=g->next) {
	 if (g->thefleet == fl) {
	    g->from = p;
	    g->dist = -1;
         }
      }
      return;
   }
   if (g->type->drive == 0) {
      mistake(P, *s, "Ships in this group can't move");
      return;
   }
   if (g->dist) {
      mistake(P, *s, "Group is in hyperspace");
      return;
   }
   p = identify(planets, getstr(0));
   if (!p) {
      mistake(P, *s, "Planet not recognized");
      return;
   }
   i = g->ships;
   if ((j = atoi(getstr(0))) != 0) {
      i = j;
      if (i > g->ships) {
	 mistake(P, *s, "Not enough ships, all available used");
	 i = g->ships;
      }
      if (i != g->ships) {
	 g2 = alloc(sizeof(group));
	 *g2 = *g;
	 addlist(&P->groups, g2);
	 g->ships -= i;
	 g2->ships = i;
	 g = g2;
      }
   }
   g->from = p;
   g->dist = -1;
   g->thefleet = 0;
}

#ifdef __STDC__
void
j_order(player * P, strlist ** s)
#else
void
j_order(P, s)
strlist ** s;
player * P;
#endif
{
planet     *p;
planet     *p2;
char       *ns;
group      *g;
group      *g2;
double      dist;
double      dist2;
fleetname  *fl;
fleetname  *fl2;
int         i;
int         j;

   ns = getstr(0);
   g = findgroup (P,ns);
   fl = identify (P->fleetnames, ns);
   if (!g && !fl) {
      mistake (P, *s,"Source Group or fleet not recognized");
      return;
   }
   if (fl) {
      fl2 = identify (P->fleetnames, getstr(0));

      if (!fl2) {
	mistake (P, *s, "Destination fleet not recognized");
	return;
      }
      dist = 0.0;
      dist2 = 0.0;
      p2 = 0;
      for (g=P->groups; g; g=g->next) {
	 if (g->thefleet == fl) {
	    p = g->where;
	    dist = g->dist;
	 }
	 if (g->thefleet == fl2) {
	    p2 = g->where;
	    dist2 = g->dist;
	 }
      }
      if (dist) {
	 mistake (P, *s, "First fleet is in hyperspace");
	 return;
      }
      if (dist2) {
	 mistake (P, *s, "Second fleet is in hyperspace");
	 return;
      }
      if ((p != p2)&&(p2)) {
	 mistake (P, *s, "Fleets are not at the same planet");
	 return;
      }
      for (g=P->groups; g; g=g->next)
         if (g->thefleet == fl)
            g->thefleet = fl2;
      return;
   }
   if (g->dist) {
      mistake (P, *s, "Group is in hyperspace");
      return;
   }
   fl = identify (P->fleetnames,getstr (0)); 
   if (!fl) {
      mistake (P, *s,"Fleet type not recognized"); 
      return;
   }
   if ((j = atoi (getstr (0))) != 0) {
      i = j;
      if (i > g->ships) {
         mistake (P, *s,"Not enough ships, all available used");
         i = g->ships;
      }
      if (i != g->ships) {
	 g2 = alloc(sizeof(group));
         *g2 = *g;
         addlist (&P->groups, g2);
         g->ships -= i;
         g2->ships = i;
         g = g2;
      }
   }
   for (g2=P->groups; g2; g2=g2->next) {
      if ((g2->thefleet == fl)&&(g2->dist)) {
	 mistake (P, *s, "Fleet is in hyperspace");
	 return;
      }
      if ((g2->thefleet == fl)&&(!g2->dist)&& (g2->where != g->where)) {
         mistake (P, *s, "Group is at the wrong planet");
         return;
      }
   }
   g->thefleet = fl;
}
   
#ifdef __STDC__
void
l_order(player * P, strlist ** s)
#else
void
l_order(P, s)
strlist ** s;
player * P;
#endif
{
group      *g;
group      *g2;
double     x;
double     y;
planet *   p;
int        i;
int        j;
int        k;

   g = findgroup(P, getstr(0));
   if (!g) {
      mistake(P, *s, "Group not recognized");
      return;
   }
   if (g->type->cargo == 0) {
      mistake(P, *s, "Group cannot carry cargo");
      return;
   }
   if (g->dist) {
      mistake(P, *s, "Group is in hyperspace");
      return;
   }
   x = cargospace(g);
   if (x <= g->load) {
      mistake(P, *s, "Group is fully loaded");
      return;
   }
   p = g->where;
   if (p->owner != P) {
      mistake(P, *s, "Group is not at one of your planets");
      return;
   }
   k = nametocargotype(getstr(0));
   if (k < 0 || k > 2) {
      mistake(P, *s, "Cargo type not recognized");
      return;
   }
   if (g->load && g->loadtype != k) {
      mistake(P, *s, "Group is already carrying a different load");
      return;
   }
   i = g->ships;
   if ((j = atoi(getstr(0))) != 0) {
      i = j;
      if (i > g->ships) {
	 mistake(P, *s, "Not enough ships, all available used");
	 i = g->ships;
      }
      if (i != g->ships) {
	 g2 = alloc(sizeof(group));
	 *g2 = *g;
	 addlist(&P->groups, g2);
	 g->ships -= i;
	 g2->ships = i;
	 g = g2;
      }
   }
   x = (x - g->load) * g->ships;
   switch (k) {
   case CG_CAP:
      y = p->cap;
      if (!y) {
	 mistake(P, *s, "No capital available");
	 break;
      }
      if (y > x)
	 y = x;
      g->load += y / g->ships;
      p->cap -= y;
      break;
   case CG_MAT:
      y = p->mat;
      if (!y) {
	 mistake(P, *s, "No materials available");
	 break;
      }
      if (y > x)
	 y = x;
      g->load += y / g->ships;
      p->mat -= y;
      break;
   case CG_COL:
      y = p->col;
      if (!y) {
	 mistake(P, *s, "No colonists available");
	 break;
      }
      if (y > x)
	 y = x;
      g->load += y / g->ships;
      p->col -= y;
      break;
   }
   g->loadtype = k;
}

#ifdef __STDC__
void
m_order(player * P, strlist ** s)
#else
void
m_order(P, s)
strlist ** s;
player * P;
#endif
{
double     x;
double     y;
double     z;

   x = atof(getstr(0));
   y = atof(getstr(0));
   z = atof(getstr(0));
   if (z < 1) {
      mistake(P, *s, "Size must be at least 1");
      return;
   }
   P->mx = x;
   P->my = y;
   P->msize = z;
}

#ifdef __STDC__
void
n_order(player * P, strlist ** s)
#else
void
n_order(P, s)
strlist ** s;
player * P;
#endif
{
planet * p;
char *   ns;

   p = identify(planets, getstr(0));
   if (!p) {
      mistake(P, *s, "Planet not recognized");
      return;
   }
   if (p->owner != P) {
      mistake(P, *s, "Planet not owned by you");
      return;
   }
   ns = getstr(0);
   if (!ns[0]) {
      mistake(P, *s, "New planet name not provided");
      return;
   }
   if (nametop(planets, ns)) {
      mistake(P, *s, "Name already in use");
      return;
   }
   nstrcpy(p->name, ns, NAMESIZE);
   if (P->namecase)
      ckcase(p->name);
}

#ifdef __STDC__
void
o_order(player * P, strlist ** s)
#else
void
o_order(P, s)
strlist ** s;
player * P;
#endif
{
char *   ns;
int      i;

   ns = getstr(0);
   i = 1;
   if (!strcmpl(ns, "no")) {
      i = 0;
      ns = getstr(0);
   }
   if (!strcmpl(ns, "fleettables")) {
      P->fleettables = i;
      return;
   }
   if (!strcmpl(ns, "sortgroups")) {
      P->sortgroups = i;
      return;
   }
   if (!strcmpl(ns, "prodtable")) {
      P->prodtable = i;
      return;
   }
   if (!strcmpl(ns, "autounload")) {
      P->autounload = i;
      return;
   }
   if (!strcmpl(ns, "underscores")) {
      P->underscores = i;
      return;
   }
   if (!strcmpl(ns, "twocol")) {
      P->twocol = i;
      return;
   }
   if (!strcmpl(ns, "namecase")) {
      P->namecase = i;
      return;
   }
   mistake(P, *s, "Option not recognized");
}

#ifdef __STDC__
void
p_order(player * P, strlist ** s)
#else
void
p_order(P, s)
strlist ** s;
player * P;
#endif
{
char *   ns;
planet * p;
shiptype * t;

   p = identify(planets, getstr(0));
   if (!p) {
      mistake(P, *s, "Planet not recognized");
      return;
   }
   if (p->owner != P) {
      mistake(P, *s, "Planet not owned by you");
      return;
   }
   ns = getstr(0);
   if (!strcmpl(ns, "cap")) {
      setproduction(p, PR_CAP);
      return;
   }
   if (!strcmpl(ns, "mat")) {
      setproduction(p, PR_MAT);
      return;
   }
   if (!strcmpl(ns, "drive")) {
      setproduction(p, PR_DRIVE);
      return;
   }
   if (!strcmpl(ns, "weapons")) {
      setproduction(p, PR_WEAPONS);
      return;
   }
   if (!strcmpl(ns, "shields")) {
      setproduction(p, PR_SHIELDS);
      return;
   }
   if (!strcmpl(ns, "cargo")) {
      setproduction(p, PR_CARGO);
      return;
   }
   t = identify(P->shiptypes, ns);
   if (!t) {
      mistake(P, *s, "Production type not recognized");
      return;
   }
   if (p->producing != PR_SHIP || p->producingshiptype != t) {
      setproduction(p, PR_SHIP);
      p->producingshiptype = t;
   }
}

#ifdef __STDC__
void
q_order(player * P, strlist ** s)
#else
void
q_order(P, s)
strlist ** s;
player * P;
#endif
{

   if (identify(players, getstr(0)) != P) {
      mistake(P, *s, "Player identification not given");
      return;
   }
   P->addr[0] = 0;
   printf("%s is quitting the game\n", P->name);
}

#ifdef __STDC__
void
r_order(player * P, strlist ** s)
#else
void
r_order(P, s)
strlist ** s;
player * P;
#endif
{
char *   ns;
planet * p;
planet * p2;
int      i;

   p = identify(planets, getstr(0));
   if (!p) {
      mistake(P, *s, "Source planet not recognized");
      return;
   }
   if (p->owner != P) {
      mistake(P, *s, "Planet not owned by you");
      return;
   }
   i = nametocargotype(getstr(0));
   if (i < 0) {
      mistake(P, *s, "Cargo type not recognized");
      return;
   }
   p2 = 0;
   ns = getstr(0);
   if (ns[0]) {
      p2 = identify(planets, ns);
      if (!p2) {
	 mistake(P, *s, "Destination planet not recognized");
	 return;
      }
   }
   p->routes[i] = p2;
}

#ifdef __STDC__
void
s_order(player * P, strlist ** s)
#else
void
s_order(P, s)
strlist ** s;
player * P;
#endif
{
group *  g;
group *  g2;
planet * p;
int      i;
int      j;
fleetname  *fl;
char    *ns;

   ns = getstr(0);
   g = findgroup(P, ns);
   fl = identify (P->fleetnames, ns);
   if (!g && !fl) {
      mistake(P, *s, "Group or fleet not recognized");
      return;
   }
   if (fl) {
      p = identify (planets, getstr(0));
      if (!p) {
	 mistake (P, *s, "Planet not recognized");
	 return;
      }
      for (g=P->groups; g; g=g->next) {
	 if ((g->thefleet == fl)&&(g->dist)) {
	    mistake (P, *s, "Fleet is in hyperspace");
	    return;
         }
	 if ((g->thefleet == fl)&&(!g->type->drive)) {
	    mistake (P, *s, "Fleet cannot move");
	    return;
         }
      }
      for (g=P->groups; g; g=g->next)
	 if (g->thefleet == fl)
	    send (g, p);
      return;
   }
   if (g->type->drive == 0) {
      mistake(P, *s, "Ships in this group can't move");
      return;
   }
   if (g->dist) {
      mistake(P, *s, "Group is in hyperspace");
      return;
   }
   p = identify(planets, getstr(0));
   if (!p) {
      mistake(P, *s, "Planet not recognized");
      return;
   }
   i = g->ships;
   if ((j = atoi(getstr(0))) != 0) {
      i = j;
      if (i > g->ships) {
	 mistake(P, *s, "Not enough ships, all available used");
	 i = g->ships;
      }
      if (i != g->ships) {
	 g2 = alloc(sizeof(group));
	 *g2 = *g;
	 addlist(&P->groups, g2);
	 g->ships -= i;
	 g2->ships = i;
	 g = g2;
      }
   }
   g->thefleet = 0;
   send(g, p);
}

#ifdef __STDC__
void
t_order(player * P, strlist ** s)
#else
void
t_order(P, s)
strlist ** s;
player * P;
#endif
{
char *      ns;
fleetname  *fl;
shiptype *  t;

   ns = getstr (0);
   t = identify(P->shiptypes, ns);
   fl = identify(P->fleetnames, ns);
   if (!t && !fl) {
      mistake(P, *s, "Ship or fleet type not recognized");
      return;
   }
   ns = getstr(0);
   if (!ns[0]) {
      mistake(P, *s, "New name not provided");
      return;
   }
   if (identify(P->fleetnames, ns)) {
      mistake(P, *s, "Name already in use for fleet type");
      return;
   }
   if (nametop(P->shiptypes, ns)) {
      mistake(P, *s, "Name already in use for ship type");
      return;
   }
   if (fl) {
      nstrcpy (fl->name, ns, NAMESIZE);
      if (P->namecase)
	 ckcase (fl->name);
   }
   else {
      nstrcpy(t->name, ns, NAMESIZE);
      if (P->namecase)
         ckcase(t->name);
   }
}

#ifdef __STDC__
void
u_order(player * P, strlist ** s)
#else
void
u_order(P, s)
strlist ** s;
player * P;
#endif
{
group *  g;
group *  g2;
/* planet * p; */
int      i;
int      j;

   g = findgroup(P, getstr(0));
   if (!g) {
      mistake(P, *s, "Group not recognized");
      return;
   }
   if (g->loadtype == CG_EMPTY) {
      mistake(P, *s, "No cargo on board");
      return;
   }
   if (g->dist) {
      mistake(P, *s, "Group is in hyperspace");
      return;
   }
   if (g->loadtype == CG_COL && g->where->owner &&
       g->where->owner != P) {
      mistake(P, *s, "Can't unload colonists onto an alien planet");
      return;
   }
   i = g->ships;
   if ((j = atoi(getstr(0))) != 0) {
      i = j;
      if (i > g->ships) {
	 mistake(P, *s, "Not enough ships, all available used");
	 i = g->ships;
      }
      if (i != g->ships) {
	 g2 = alloc(sizeof(group));
	 *g2 = *g;
	 addlist(&P->groups, g2);
	 g->ships -= i;
	 g2->ships = i;
	 g = g2;
      }
   }
   unloadgroup(g, P);
}

#ifdef __STDC__
void
w_order(player * P, strlist ** s)
#else
void
w_order(P, s)
strlist ** s;
player * P;
#endif
{
player *    P2;
alliance *  a;

   P2 = identify(players, getstr(0));
   if (!P2) {
      mistake(P, *s, "Player not recognized");
      return;
   }
   for (a = P->allies; a; a = a->next)
      if (a->who == P2) {
	 removelist(&P->allies, a);
	 return;
      }
}

#ifdef __STDC__
void
x_order(player * P, strlist ** s)
#else
void
x_order(P, s)
strlist ** s;
player * P;
#endif
{
group *    g;
group *    g2;
int        i;
int        j;

   g = findgroup(P, getstr(0));
   if (!g) {
      mistake(P, *s, "Group not recognized");
      return;
   }
   if (g->dist) {
      mistake(P, *s, "Group is in hyperspace");
      return;
   }
   if (g->loadtype == CG_COL && g->where->owner &&
       g->where->owner != P) {
      mistake(P, *s, "Can't unload colonists onto an alien planet");
      return;
   }
   i = g->ships;
   if ((j = atoi(getstr(0))) != 0) {
      i = j;
      if (i > g->ships) {
	 mistake(P, *s, "Not enough ships, all available used");
	 i = g->ships;
      }
      if (i != g->ships) {
	 g2 = alloc(sizeof(group));
	 *g2 = *g;
	 addlist(&P->groups, g2);
	 g->ships -= i;
	 g2->ships = i;
	 g = g2;
      }
   }
   unloadgroup(g, P);
   g->where->mat += shipmass(g) * g->ships;
   g->ships = 0;
   g = findgroup(P, getstr(0));
   if (!g) {
      mistake(P, *s, "Group not recognized");
      return;
   }
   if (g->dist) {
      mistake(P, *s, "Group is in hyperspace");
      return;
   }
   if (g->loadtype == CG_COL && g->where->owner &&
       g->where->owner != P) {
      mistake(P, *s, "Can't unload colonists onto an alien planet");
      return;
   }
   i = g->ships;
   if ((j = atoi(getstr(0))) != 0) {
      i = j;
      if (i > g->ships) {
	 mistake(P, *s, "Not enough ships, all available used");
	 i = g->ships;
      }
      if (i != g->ships) {
	 g2 = alloc(sizeof(group));
	 *g2 = *g;
	 addlist(&P->groups, g2);
	 g->ships -= i;
	 g2->ships = i;
	 g = g2;
      }
   }
   unloadgroup(g, P);
   g->where->mat += shipmass(g) * g->ships;
   g->ships = 0;
}

#ifdef __STDC__
void
y_order(player * P, strlist ** s)
#else
void
y_order(P, s)
strlist ** s;
player * P;
#endif
{
char       *ns;
   ns = getstr (0);
   nstrcpy (P->pswd, ns, NAMESIZE);
   if (ns[0])
      P->pswdstate = 1;
   else
      P->pswdstate = 2;
}

#ifdef __STDC__
void
z_order(player * P, strlist ** s)
#else
void
z_order(P, s)
strlist ** s;
player * P;
#endif
{
char *    ns;

   ns = getstr(0);
   if (!ns[0]) {
      mistake(P, *s, "No new address given");
      return;
   }
   nstrcpy(P->addr, ns, ADDRSIZE);
}

#ifdef __STDC__
void
processturns(char *InFile, char *glist[MAXGAMES])
#else
void
processturns(InFile,glist)
char *InFile,*glist[MAXGAMES];
#endif
{
/*   int             i, j, k; */
/*   double          x, y, z; */
   char           *ns;
   strlist        *s;
   strlist       **sp;
   player         *P, *P2, *P3;
/*   group          *g, *g2; */
   planet         *p;
/*   shiptype       *t; */
/*   battle         *b; */
/*   participant    *r; */
   alliance       *a;
   char           *F;
   static char     ordersfilename[256];

   if(InFile){
      strcpy(ordersfilename,InFile);
   } else {
      printf("Name of orders file? ");
      gets(ordersfilename);
   }
   if (!ordersfilename[0])
      return;
   unlink("send");

   while (!nextgame(glist) ) {
      f = Fopen(ordersfilename, "r");
      printf("Reading orders from file...\n");

/* This is clumsy! Basically, its an infinite loop, with a termination
 * condition of buf[0] == EOF. Wonder why its done that way? Anyway I'm
 * going to swap the two and stare real hard at it
 */
/* Hmm, lets split it into a loop which keeps getbuffing till it finds
 * a buf[0] == 0. Wonder whether that would do the trick
 */
      getbuf();
      while(!feof(f)) {
	 while ((!memicmp(buf, "#galaxy", 7)) && (!feof(f))) {
	 /* found a new player */
	    getstr(buf);
	    if (!strcmpl(getstr(0), gamename)) {
	       ns = getstr(0);
	       P = identify(players, ns);
	       if (P) {
		  ns = getstr(0);
		  if ((!strcmpl(P->pswd, ns))||(!(P->pswd[0]))) {
		     printf("Reading orders for %s...\n", P->name);
		     P->lastorders = turn + 1;
		     if (P->orders) {
		        freestrlist(P->orders);
		        P->orders = 0;
		     }
		     sp = &P->orders;
		     getbuf();
		     while (memicmp(buf, "#galaxy", 7) &&  (!feof(f)) &&
		        buf[0] != '\f' && memicmp(buf, "#end", 4)) {
		        s = makestrlist(buf);
		        addlist2(sp, s);
		        getbuf();
		     }
		     *sp = 0;
		  }
		  else {
		     printf("Incorrect password for player '%s'\n", P->name);
		     getbuf();
		     while (memicmp(buf, "#galaxy", 7) &&  (!feof(f)) &&
		        buf[0] != '\f' && memicmp(buf, "#end", 4)) {
		        getbuf();
		     }
		  }
	       }
	       else {
	    /* oops, can't find this player */
		  printf("Unrecognized player '%s'\n", ns);
		  break;
	       }
	    }
	    else {
	       buf[0]='\0';
	 /* from some other game, ignore....*/
	    }
	 }
         getbuf();
      }

      fclose(f);
      freemessages();
      freebattles();
      printf("Orders read, processing...\n");

      turn++;

      /* Do all orders except renaming */

      for (P = players; P; P = P->next) {
	 for (s = P->orders; s; s = s->next) {
	 orderinfo * op;
	 char *      order = getstr(s->s[0]);
	 int         i;
	    for( i = 0; i < ORDER_SIZE; i++ ) {
	       order[i] = tolower(order[i]);
	    }
	    for( op = phase1orders; op->name != 0; op++ ) {
	       if( strncmp(op->name, order, ORDER_SIZE) == 0) {
		  op->func(P, &s);
		  break;
	       }
	    }
	 }
      }

      /* Do renaming and upgrade orders */

      for (P = players; P; P = P->next) {
	 for (s = P->orders; s; s = s->next) {
	 orderinfo * op;
	 char *      order = getstr(s->s[0]);
	 int         i;
	    for( i = 0; i < ORDER_SIZE; i++ ) {
	       order[i] = tolower(order[i]);
	    }
	    for( op = phase2orders; op->name != 0; op++ ) {
	       if( strncmp(op->name, order, ORDER_SIZE) == 0) {
		  op->func(P, &s);
		  break;
	       }
	    }
	 }
      }

      /* Remove dead players */

      for (P = players; P;) {
	 int idle_turns;

	 P3 = P->next;

         idle_turns = (turn - P->lastorders);

	 if(idle_turns != 0) {
	    if (idle_turns < ORDERGAP && P->addr[0]) {
	       sprintf(buf,
"\n\
*** NOTE: You didn't send orders this turn.  You have %d more turn(s) to\n\
*** remain idle before you forfeit your position.",ORDERGAP-idle_turns);
	       addlist(&P->messages, makestrlist(buf));
	    } else if (idle_turns == ORDERGAP && P->addr[0]) {
	       addlist(&P->messages, makestrlist(
"\n\
*** WARNING: If you do not send orders for this next turn then you will\n\
*** forfeit your position in the game!  Please send orders next turn if you\n\
*** wish to continue playing."));
	    } else if (idle_turns > ORDERGAP && P->addr[0]) {
	       printf("Discontinuing reports for %s\n", P->name);
	       P->addr[0] = 0;
	    }
	 }
	 if (P->groups) {
	    P = P3;
	    continue;
	 }
	 for (p = planets; p && p->owner != P; p = p->next);
	 if (p) {
	    P = P3;
	    continue;
	 }
	 freelist(P->shiptypes);
	 for (P2 = players; P2; P2 = P2->next)
	    for (a = P2->allies; a; a = a->next)
	       if (a->who == P) {
		  removelist(&P2->allies, a);
		  break;
	       }
	 printf("Removing %s\n", P->name);
	 freelist(P->allies);
	 removelist(&players, P);
	 P = P3;
      }

      joinphase();
      fightphase();
      bombphase();
      loadphase();
      fleetphase ();
      interceptphase();
      movephase();
      joinphase();
      fightphase();
      bombphase();
      producephase();
      unloadphase();
      joinphase();
      sortphase();
      fleetphase ();

      reports();
      savegame(gamename);
      freegame();
/* This is the end of the end of loop stuff */
   }
}



#ifdef __STDC__
int
nextgame (char *glist[MAXGAMES])
#else
int
nextgame (glist)
char *glist[MAXGAMES];
#endif
{
   char           *F;
   static char     lgamename[256];
   int             i, redo=1;

   assert(gamename[0] == 0);
   F = findfirst("data");
   while (F && F[0] == '.')
      F = findnext();
   if (!F) {
      lgamename[0] = 0;
      return 1;
   }
   if (lgamename[0]) {
      while (strcmp(lgamename, F)) {
         F = findnext();
         assert(F);
      }
      F = findnext();
      if (!F) {
         lgamename[0] = 0;
         return 1;
      }
   }
   if(glist[0]!=NULL){
      do{
         for(i=0;i<MAXGAMES;i++){
   	      if(glist[i]==NULL){
   	   	   F=findnext();
   		   if(!F){
   		      lgamename[0]=0;
   		      return 1;
		   }
		   break;
	      }
	      if(!strcmp(F,glist[i])){
	         redo=0;
               break;
	      }
	   }
	   if(i>=MAXGAMES){
   	      F=findnext();
            if(!F){
		   lgamename[0]=0;
		   return 1;
	      }
	   }
      }while(redo);
   }
   strcpy(gamename, F);
   strcpy(lgamename, F);
   i = loadgame(gamename);
   if (i)
      lgamename[0] = 0;
   return i;
}
