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

#ifdef __STDC__
void 
giveposition (void)
#else
void 
giveposition ()
#endif
{
   player         *P;

   do {
      printf("Game? ");
      gets(gamename);
      if (gamename[0] == 0)
         return;
   }
   while (loadgame(gamename));
PLAYERNAME:
   printf("Player? ");
   gets(buf);
   if (buf[0] == 0) {
      freegame();
      return;
   }
   P = nametop(players, buf);
   if (P == 0) {
      printf("Player not found\n");
      goto PLAYERNAME;
   }
   printf("New address? ");
   gets(P->addr);
   sprintf(P->pswd, "\0");
   P->underscores = 0;
   P->twocol = 0;
   P->namecase = 1;
   P->lastorders = turn;
   savegame(gamename);
   freegame();
}

#ifdef __STDC__
void 
convertcap (planet * p)
#else
void 
convertcap (p)
planet * p;
#endif
{
   double          indinc;

   indinc = p->pop - p->ind;
   if (indinc > p->cap)
      indinc = p->cap;
   p->cap -= indinc;
   p->ind += indinc;
}

#ifdef __STDC__
void 
unloadcap (planet * p, double x)
#else
void 
unloadcap (p, x)
planet * p;
double x;
#endif
{
   p->cap += x;
   convertcap(p);
}

#ifdef __STDC__
void 
unloadcol (planet * p, double x, player * P)
#else
void 
unloadcol (p, x, P)
planet * p;
double x;
player * P;
#endif
{
   double          y;

   x *= POPPERCOL;
   y = p->size - p->pop;
   if (y > x)
      y = x;
   p->pop += y;
   x -= y;
   p->col += x / POPPERCOL;
   if (!p->owner)
      p->owner = P;
   convertcap(p);
}

#ifdef __STDC__
void 
unloadgroup (group * g, player * P)
#else
void 
unloadgroup (g, P)
group * g;
player * P;
#endif
{
   double          x;
   planet         *p;

   x = g->load * g->ships;
   p = g->where;
   switch (g->loadtype) {
   case CG_CAP:
      unloadcap(p, x);
      break;
   case CG_MAT:
      p->mat += x;
      break;
   case CG_COL:
      unloadcol(p, x, P);
      break;
   }
   g->load = 0;
   g->loadtype = CG_EMPTY;
}

#ifdef __STDC__
void 
joinphase (void)
#else
void 
joinphase ()
#endif
{
   player         *P;
   group          *g, *g2, *g3;

   for (P = players; P; P = P->next)
      for (g = P->groups; g;)
         if (g->ships) {
            for (g2 = P->groups; g2;) {
               g3 = g2->next;
               if (g != g2 &&
		   g->thefleet == g2->thefleet &&
                   g->type == g2->type &&
                   g->drive == g2->drive &&
                   g->weapons == g2->weapons &&
                   g->shields == g2->shields &&
                   g->cargo == g2->cargo &&
                   g->loadtype == g2->loadtype &&
                   g->load == g2->load &&
		   g->from == g2->from &&
                   g->where == g2->where &&
                   g->dist == g2->dist) {
                  g->ships += g2->ships;
                  removelist(&P->groups, g2);
               }
               g2 = g3;
            }
            g = g->next;
         } else {
            g2 = g->next;
            removelist(&P->groups, g);
            g = g2;
         }
}

#ifdef __STDC__
double 
calcdefense (group * target)
#else
double 
calcdefense (target)
group * target;
#endif
{
   return target->type->shields * target->shields * BATTLEMAGIC /
   pow(shipmass(target), .333333333333333);
}

#ifdef __STDC__
int
cankill (group * attack, group * target)
#else
int
cankill (attack, target)
group * attack;
group * target;
#endif
{
   double          defense, ratio;

   if (!attack->type->attacks)
      return 0;
   defense = calcdefense(target);
   if (!defense)
      return 1;
   ratio = attack->weapons * attack->type->weapons / defense;
   return ratio > .251;
}

#ifdef __STDC__
int
kill (group * attack, group * target)
#else
int
kill (attack, target)
group * attack;
group * target;
#endif
{
   double          defense, ratio;

   if (!attack->type->attacks)
      return 0;
   defense = calcdefense(target);
   if (!defense)
      return 1;
   ratio = attack->weapons * attack->type->weapons / defense;
   return ratio > pow(4.0, frand2());
}

#ifdef __STDC__
void 
fightphase (void)
#else
void 
fightphase ()
#endif
{
   int             i, j, ngroups, nships, nshipstofire, agroup, tgroup,
                   shipno, involved;
   int             moretargets, foundtarget;
   int            *shipstofire;
   planet         *p;
   player         *P, *P2;
   group          *g, *g2;
   group         **fightgroups;
   player        **groupplayers;
   battle         *b;
   participant    *r;

   for (p = planets; p; p = p->next) {
      ngroups = 0;
      nships = 0;

      /* Calculate number of groups involved */

      for (P = players; P; P = P->next)
         for (g = P->groups; g; g = g->next)
            if (g->where == p && g->dist == 0) {
               involved = 0;
               for (P2 = players; P2 && !involved; P2 = P2->next)
                  for (g2 = P2->groups; g2; g2 = g2->next)
                     if (g2->where == p && g2->dist == 0 &&
                         ((g->type->attacks && atwar(P, P2)) ||
                          (g2->type->attacks && atwar(P2, P)))) {
                        involved = 1;
                        break;
                     }
               if (involved) {
                  ngroups++;
                  nships += g->ships;
               } else
                  g->dist = -2;
            }
      for (P = players; P; P = P->next)
         for (g = P->groups; g; g = g->next)
            if (g->dist == -2)
               for (g2 = P->groups; g2; g2 = g2->next)
                  if (g2->where == p && g2->dist == 0 && g2 != g) {
                     g->dist = 0;
                     ngroups++;
                     nships += g->ships;
                     break;
                  }
      for (P = players; P; P = P->next)
         for (g = P->groups; g; g = g->next)
            if (g->dist == -2)
               g->dist = 0;

      if (ngroups) {

         /* Collect data on all groups involved */

         fightgroups = alloc(ngroups * sizeof(group *));
         shipstofire = alloc(ngroups * sizeof(int));
         groupplayers = alloc(ngroups * sizeof(player *));
         i = 0;
         for (P = players; P; P = P->next)
            for (g = P->groups; g; g = g->next)
               if (g->where == p && g->dist == 0) {
                  involved = 0;
                  for (P2 = players; P2 && !involved; P2 = P2->next)
                     for (g2 = P2->groups; g2; g2 = g2->next)
                        if (g2->where == p && g2->dist == 0 &&
                            ((g->type->attacks && atwar(P, P2)) ||
                             (g2->type->attacks && atwar(P2, P)))) {
                           involved = 1;
                           break;
                        }
                  if (involved) {
                     groupplayers[i] = P;
                     shipstofire[i] = 0;
                     fightgroups[i] = g;
                     i++;
                  } else
                     g->dist = -2;
               }
         for (P = players; P; P = P->next)
            for (g = P->groups; g; g = g->next)
               if (g->dist == -2)
                  for (g2 = P->groups; g2; g2 = g2->next)
                     if (g2->where == p && g2->dist == 0 && g2 != g) {
                        g->dist = 0;
                        groupplayers[i] = P;
                        shipstofire[i] = 0;
                        fightgroups[i++] = g;
                        break;
                     }
         for (P = players; P; P = P->next)
            for (g = P->groups; g; g = g->next)
               if (g->dist == -2)
                  g->dist = 0;
         assert(i == ngroups);

         /* Initialize structure for battle data */

         b = alloc(sizeof(battle));
         b->where = p;
         b->participants = 0;
         for (P = players; P; P = P->next)
            if (canseeplanet(P, p)) {
               r = alloc(sizeof(participant));
               r->who = P;
               r->groups = 0;
               for (g = P->groups; g; g = g->next)
                  if (g->where == p && g->dist == 0) {
                     g2 = alloc(sizeof(group));
                     *g2 = *g;
                     g2->alias = g;
                     addlist(&r->groups, g2);
                  }
               addlist(&b->participants, r);
            }
         addlist(&battles, b);

         /* Do combat */

         do {
            /* Calculate number of ships to fire */

            nshipstofire = 0;
            for (i = 0; i != ngroups; i++)
               if (fightgroups[i]->type->attacks) {
                  shipstofire[i] = fightgroups[i]->ships;
                  nshipstofire += fightgroups[i]->ships;
               }
            assert(nshipstofire);

            /* Do one round of combat */

            do {
               /* Select a ship to fire */

               shipno = rand() % nshipstofire;
               agroup = 0;
               while (shipno >= shipstofire[agroup]) {
                  shipno -= shipstofire[agroup++];
                  assert(agroup < ngroups);
               }
               nshipstofire--;
               shipstofire[agroup]--;

               /* For each attack this ship has */

               for (i = fightgroups[agroup]->type->attacks; i; i--) {
                  /*
                   * Determine whether it has
                   * any available target
                   */

                  moretargets = 0;
                  for (tgroup = 0; tgroup < ngroups && !moretargets; tgroup++) {
                     if (!fightgroups[tgroup]->ships)
                        continue;
                     if (!cankill(fightgroups[agroup], fightgroups[tgroup]))
                        continue;
                     if (atwar(groupplayers[agroup], groupplayers[tgroup]) ||
                         atwar(groupplayers[tgroup], groupplayers[agroup]) &&
                         fightgroups[tgroup]->type->attacks)
                        moretargets = 1;
                     else if (atwar(groupplayers[tgroup], groupplayers[agroup]))
                        for (j = 0; j != ngroups; j++)
                           if (groupplayers[j] == groupplayers[tgroup] &&
                               fightgroups[j]->type->attacks) {
                              moretargets = 1;
                              break;
                           }
                  }
                  if (!moretargets)
                     break;

                  /* Select a target */

                  foundtarget = 0;
                  do {
                     shipno = rand() % nships;
                     tgroup = 0;
                     while (shipno >= fightgroups[tgroup]->ships) {
                        shipno -= fightgroups[tgroup++]->ships;
                        assert(tgroup < ngroups);
                     }
                     assert(fightgroups[tgroup]->ships);
                     if (atwar(groupplayers[agroup], groupplayers[tgroup]) ||
                         atwar(groupplayers[tgroup], groupplayers[agroup]) &&
                         fightgroups[tgroup]->type->attacks)
                        foundtarget = 1;
                     else if (atwar(groupplayers[tgroup], groupplayers[agroup]))
                        for (j = 0; j != ngroups; j++)
                           if (groupplayers[j] == groupplayers[tgroup] &&
                               fightgroups[j]->type->attacks) {
                              foundtarget = 1;
                              break;
                           }
                  }
                  while (!foundtarget);

                  /*
                   * Determine whether target
                   * destroyed
                   */

                  printf("%s %s fires on %s %s : ",
                   groupplayers[agroup]->name,
                         fightgroups[agroup]->type->name,
                   groupplayers[tgroup]->name,
                         fightgroups[tgroup]->type->name);
                  if (kill(fightgroups[agroup], fightgroups[tgroup])) {
                     if (rand() % fightgroups[tgroup]->ships < shipstofire[tgroup]) {
                        shipstofire[tgroup]--;
                        nshipstofire--;
                     }
                     fightgroups[tgroup]->ships--;
                     nships--;
                     printf("Destroyed\n");
                  } else
                     printf("Shields\n");
               }
            }
            while (nshipstofire);

            /*
             * Determine whether combat needs to be
             * continued
             */

            moretargets = 0;
            for (agroup = 0; agroup != ngroups && !moretargets; agroup++)
               if (fightgroups[agroup]->ships)
                  for (tgroup = 0; tgroup != ngroups && !moretargets; tgroup++) {
                     if (!fightgroups[tgroup]->ships ||
                         !cankill(fightgroups[agroup], fightgroups[tgroup]))
                        continue;
                     if (atwar(groupplayers[agroup], groupplayers[tgroup]) ||
                         atwar(groupplayers[tgroup], groupplayers[agroup]) &&
                         fightgroups[tgroup]->type->attacks)
                        moretargets = 1;
                     else if (atwar(groupplayers[tgroup], groupplayers[agroup]))
                        for (j = 0; j != ngroups; j++)
                           if (groupplayers[j] == groupplayers[tgroup] &&
                               fightgroups[j]->type->attacks) {
                              moretargets = 1;
                              break;
                           }
                  }
         }
         while (moretargets);

         free(groupplayers);
         free(shipstofire);
         free(fightgroups);

         /* Collect information on number of survivors */

         for (r = b->participants; r; r = r->next)
            for (g = r->groups; g; g = g->next)
               g->left = g->alias->ships;
      }
   }
}

#ifdef __STDC__
void 
bombphase (void)
#else
void 
bombphase ()
#endif
{
   player         *P, *P2;
   group          *g;
   planet         *p;
   bombing        *B;
   alliance       *a;

   for (P = players; P; P = P->next)
      for (g = P->groups; g; g = g->next) {
         p = g->where;
         if (g->dist == 0 && g->ships && g->type->attacks && p->owner && atwar(P, p->owner)) {
            B = alloc(sizeof(bombing));
            strcpy(B->name, p->name);
            B->owner = p->owner;
            B->pop = p->pop;
            B->ind = p->ind;
            B->producing = p->producing;
            B->producingshiptype = p->producingshiptype;
            B->cap = p->cap;
            B->mat = p->mat;
            B->col = p->col;
            B->who = P;
            B->viewers = 0;
            for (P2 = players; P2; P2 = P2->next)
               if (canseeplanet(P2, p)) {
                  a = alloc(sizeof(alliance));
                  a->who = P2;
                  addlist(&B->viewers, a);
               }
            addlist(&bombings, B);
            printf("%s was bombed by %s\n", B->name, P->name);
            p->owner = 0;
            p->pop = 0;
            p->ind = 0;
            p->producing = PR_CAP;
            p->producingshiptype = 0;
            p->cap = 0;
            p->mat = 0;
            p->col = 0;
            p->inprogress = 0;
            memset(p->routes, 0, sizeof(p->routes));
         }
      }
}

#ifdef __STDC__
double 
cargospace (group * g)
#else
double 
cargospace (g)
group * g;
#endif
{
   double          size;

   size = g->type->cargo;
   return g->cargo * size * (1 + size / 10);
}

#ifdef __STDC__
void 
loadphase (void)
#else
void 
loadphase ()
#endif
{
   player         *P;
   group          *g, *g2;
   int             i;
   planet         *p;
   double          qty, shipspace, availspace;

   for (p = planets; p; p = p->next)
      if ((P = p->owner) != 0) {
         if (p->routes[CG_COL])
            for (g = P->groups; g; g = g->next)
               if (g->where == p && g->type->cargo && g->dist == 0 && g->type->drive && !g->thefleet) {
                  if (g->loadtype == CG_EMPTY && p->col) {
                     qty = p->col;
                     shipspace = cargospace(g);
                     availspace = g->ships * shipspace;
                     if (qty > availspace)
                        qty = availspace;
                     p->col -= qty;
                     availspace -= qty;
                     i = availspace / shipspace;
                     if (i) {
                        g->ships -= i;
                        g2 = alloc(sizeof(group));
                        *g2 = *g;
                        addlist(&P->groups, g2);
                        g2->ships = i;
                     }
                     g->loadtype = CG_COL;
                     g->load = qty / g->ships;
                  }
                  if (g->loadtype == CG_COL)
                     send(g, p->routes[CG_COL]);
               }
         if (p->routes[CG_CAP])
            for (g = P->groups; g; g = g->next)
               if (g->where == p && g->type->cargo && g->dist == 0 && g->type->drive && !g->thefleet) {
                  if (g->loadtype == CG_EMPTY && p->cap) {
                     qty = p->cap;
                     shipspace = cargospace(g);
                     availspace = g->ships * shipspace;
                     if (qty > availspace)
                        qty = availspace;
                     p->cap -= qty;
                     availspace -= qty;
                     i = availspace / shipspace;
                     if (i) {
                        g->ships -= i;
                        g2 = alloc(sizeof(group));
                        *g2 = *g;
                        addlist(&P->groups, g2);
                        g2->ships = i;
                     }
                     g->loadtype = CG_CAP;
                     g->load = qty / g->ships;
                  }
                  if (g->loadtype == CG_CAP)
                     send(g, p->routes[CG_CAP]);
               }
         if (p->routes[CG_MAT])
            for (g = P->groups; g; g = g->next)
               if (g->where == p && g->type->cargo && g->dist == 0 && g->type->drive && !g->thefleet) {
                  if (g->loadtype == CG_EMPTY && p->mat) {
                     qty = p->mat;
                     shipspace = cargospace(g);
                     availspace = g->ships * shipspace;
                     if (qty > availspace)
                        qty = availspace;
                     p->mat -= qty;
                     availspace -= qty;
                     i = availspace / shipspace;
                     if (i) {
                        g->ships -= i;
                        g2 = alloc(sizeof(group));
                        *g2 = *g;
                        addlist(&P->groups, g2);
                        g2->ships = i;
                     }
                     g->loadtype = CG_MAT;
                     g->load = qty / g->ships;
                  }
                  if (g->loadtype == CG_MAT)
                     send(g, p->routes[CG_MAT]);
               }
         if (p->routes[CG_EMPTY])
            for (g = P->groups; g; g = g->next)
               if (g->where == p && g->type->cargo && g->dist == 0 && g->loadtype == CG_EMPTY && !g->thefleet)
                  send(g, p->routes[CG_EMPTY]);
      }
}

#ifdef __STDC__
void 
interceptphase (void)
#else
void 
interceptphase ()
#endif
{
   int             i, j;
   double          maxmass, maxdist, *v;
   player         *P, *P2;
   group          *g, *g2;
   planet         *p, *p2;

   for (p = planets, i = 1; p; p = p->next, i++);
   v = alloc(i * sizeof(double));
   for (P = players; P; P = P->next)
      for (g = P->groups; g; g = g->next)
         if (g->dist < 0) {
	    if (g->thefleet)
	       maxdist = 2 * g->thefleet->fleetspeed;
	    else
               maxdist = 2 * g->type->drive * g->drive * DRIVEMAGIC / shipmass(g);
            p = g->from;
            memset(v, 0, i * sizeof(double));
            for (P2 = players; P2; P2 = P2->next)
               if (P2 != P)
                  for (g2 = P2->groups; g2; g2 = g2->next)
                     if (g2->from == p && g2->where != p &&
                         g2->dist == dist(p, g2->where) &&
                         dist(g->where, g2->where) < maxdist)
                        v[ptonum(planets, g2->where)] += g2->ships * shipmass(g2);
            maxmass = 0;
            for (j = 1, p2 = planets; p2; j++, p2 = p2->next)
               if (v[j] > maxmass) {
                  maxmass = v[j];
                  p = p2;
               }
            send(g, p);
         }
   free(v);
}

#ifdef __STDC__
void 
fleetphase (void)
#else
void 
fleetphase ()
#endif
{
   player         *P;
   fleetname      *fl;
   group          *g;
   float           shipspeed;
   int             hasships;

   for (P = players; P; P=P->next)
      for (fl = P->fleetnames; fl; fl=fl->next) {
	 hasships = 0;
	 for (g=P->groups; g; g=g->next) {
	    if (g->thefleet == fl) {
	       hasships = 1;
	       shipspeed = g->type->drive * g->drive * DRIVEMAGIC / shipmass (g);
	       if (shipspeed < fl->fleetspeed)
		  fl->fleetspeed = shipspeed;
            }
         } 
	 if (!hasships)
	    removelist (&P->fleetnames, fl);
      }
}

#ifdef __STDC__
void 
movephase (void)
#else
void 
movephase ()
#endif
{
   player         *P;
   group          *g;

   for (P = players; P; P = P->next)
      for (g = P->groups; g; g = g->next) {
	 if (g->thefleet)
	    g->dist -= g->thefleet->fleetspeed;
         else
            g->dist -= g->type->drive * g->drive * DRIVEMAGIC / shipmass(g);
         if (g->dist < 0) {
            g->dist = 0;
	    g->from = g->where;
         }
      }
}

#ifdef __STDC__
void 
unloadphase (void)
#else
void 
unloadphase ()
#endif
{
   planet         *p, *p2;
   group          *g;
   int             i;

   for (p = planets; p; p = p->next)
      if (p->owner)
         for (i = 0; i != CG_EMPTY; i++) {
            p2 = p->routes[i];
            for (g = p->owner->groups; g; g = g->next) {
               if (g->where == p2 &&
                   g->dist == 0 &&
                   g->loadtype == i &&
                   g->ships &&
                   !(g->loadtype == CG_COL && g->where->owner &&
                     g->where->owner != p->owner))
                  unloadgroup(g, p->owner);
	       if (p->owner->autounload &&
		   (g->where == p) &&
		   (g->dist == 0) &&
		   (g->ships))
                  unloadgroup(g, p->owner);
	    }
         }
}

#ifdef __STDC__
double 
ftrunc2(double x)
#else
double 
ftrunc2(x)
double x;
#endif
{
   char            buf[32];

   sprintf(buf, "%0.2lf", x);
   return atof(buf);
}

#ifdef __STDC__
void 
cktech (group * g)
#else
void 
cktech (g)
group * g;
#endif
{
   shiptype       *t;

   t = g->type;
   g->drive = ftrunc2(g->drive);
   g->weapons = ftrunc2(g->weapons);
   g->shields = ftrunc2(g->shields);
   g->cargo = ftrunc2(g->cargo);
   if (!t->drive)
      g->drive = 0;
   if (!t->attacks)
      g->weapons = 0;
   if (!t->shields)
      g->shields = 0;
   if (!t->cargo)
      g->cargo = 0;
}

#ifdef __STDC__
void 
producephase (void)
#else
void 
producephase ()
#endif
{
   planet         *p;
   double          ind, shipcost, nships, matdemand, popinc, poproom;
   shiptype       *t;
   player         *P;
   int             inships;
   group          *g;

   for (p = planets; p; p = p->next)
      if (p->owner && p->producing == PR_SHIP) {
         ind = p->ind * .75 + p->pop * .25 - p->spent + p->inprogress;
         if (ind < 0)
            ind = 0;
         P = p->owner;
         t = p->producingshiptype;
         shipcost = typemass(t);
         nships = ind / shipcost / INDPERSHIP;
         matdemand = nships * shipcost;
         if (matdemand > p->mat) {
            nships = nships * p->mat / matdemand;
            matdemand = p->mat;
         }
         inships = (int) nships;
         nships = inships;
         ind -= nships * shipcost * INDPERSHIP;
         p->mat -= nships * shipcost;
         g = alloc(sizeof(group));
         g->ships = inships;
         inships = (int) (ind / shipcost / (1 / p->resources + INDPERSHIP));
         g->ships += inships;
         ind -= inships * shipcost * (1 / p->resources + INDPERSHIP);
         p->inprogress = ind;
         g->type = t;
         memcpy(&g->drive, &P->drive, 4 * sizeof(double));
         cktech(g);
         g->load = 0;
         g->loadtype = CG_EMPTY;
         g->from = g->where = p;
         g->dist = 0;
	 g->thefleet = 0;
         addlist(&P->groups, g);
      }
   for (p = planets; p; p = p->next)
      if (p->owner && p->producing != PR_SHIP) {
         ind = p->ind * .75 + p->pop * .25 - p->spent;
         if (ind < 0)
            ind = 0;
         P = p->owner;
         switch (p->producing) {
         case PR_CAP:
            matdemand = ind / INDPERCAP;
            if (matdemand > p->mat)
               matdemand = p->mat;
            ind -= matdemand * INDPERCAP;
            p->cap += matdemand;
            p->mat -= matdemand;
            matdemand = ind / (INDPERCAP + 1 / p->resources);
            p->cap += matdemand;
            break;
         case PR_MAT:
            p->mat += ind * p->resources;
            break;
         case PR_DRIVE:
            P->drive += ind / 5000;
            break;
         case PR_WEAPONS:
            P->weapons += ind / 5000;
            break;
         case PR_SHIELDS:
            P->shields += ind / 5000;
            break;
         case PR_CARGO:
            P->cargo += ind / 5000;
            break;
         default:
            assert(0);
         }
      }
   for (p = planets; p; p = p->next)
      if (p->owner) {
         popinc = p->pop * POPINC;
         poproom = p->size - p->pop;
         if (poproom > popinc)
            poproom = popinc;
         p->pop += poproom;
         p->col += (popinc - poproom) / POPPERCOL;
         convertcap(p);
      }
}

#ifdef __STDC__
void 
sortphase(void)
#else
void 
sortphase()
#endif
{
   group *g, *g2, *newgroup;
   fleetname *fl;
   player *P;
   planet *Pl;
   int first;
   int HasBeenSorted;

   first = 1;
   HasBeenSorted = 0;
   for (P=players; P; P=P->next) {
      if (P->sortgroups) {
         /* sorting for groups at your own planet */
         for (Pl=planets; Pl; Pl=Pl->next) {
            for (g=P->groups; g;g=g->next) 
               if ((!g->thefleet)&&(g->where==Pl)&&(Pl->owner == P)) {
                  newgroup = addgroup(g, newgroup, first);
                  first = 0;
                  HasBeenSorted = 1;
               }
            for (fl=P->fleetnames; fl; fl=fl->next)
               for (g=P->groups; g;g=g->next) 
                  if ((g->thefleet==fl)&&(g->where==Pl)&&(Pl->owner == P)) {
                     newgroup = addgroup(g, newgroup, first);
                     first = 0;
                     HasBeenSorted = 1;
                  }
         }

         /* sorting for groups at your somebody else's planet */
         for (Pl=planets; Pl; Pl=Pl->next) {
            for (g=P->groups; g;g=g->next) 
               if ((!g->thefleet)&&(g->where==Pl)&&(Pl->owner != P)&&(!isuninhabited (P,Pl))) {
                  newgroup = addgroup(g, newgroup, first);
                  first = 0;
                  HasBeenSorted = 1;
               }
            for (fl=P->fleetnames; fl; fl=fl->next)
               for (g=P->groups; g;g=g->next) 
                  if ((g->thefleet==fl)&&(g->where==Pl)&&(Pl->owner != P)&&(!isuninhabited (P,Pl))) {
                     newgroup = addgroup(g, newgroup, first);
                     first = 0;
                     HasBeenSorted = 1;
                  }
         }

         /* sorting for groups at uninhabitted planets */
         for (Pl=planets; Pl; Pl=Pl->next) {
            for (g=P->groups; g;g=g->next) 
               if ((!g->thefleet)&&(g->where==Pl)&&(isuninhabited (P,Pl))) {
                  newgroup = addgroup(g, newgroup, first);
                  first = 0;
                  HasBeenSorted = 1;
               }
            for (fl=P->fleetnames; fl; fl=fl->next)
               for (g=P->groups; g;g=g->next) 
                  if ((g->thefleet==fl)&&(g->where==Pl)&&(isuninhabited (P,Pl))) {
                     newgroup = addgroup(g, newgroup, first);
                     first = 0;
                     HasBeenSorted = 1;
                  }
         }

         if (HasBeenSorted) {
            HasBeenSorted = 0;
            P->groups = newgroup;
         }
      }
      first = 1;
   }
}

#ifdef __STDC__
void 
mistake (player * P, strlist * s, char *comment)
#else
void 
mistake (P, s, comment)
player * P;
strlist * s;
char *comment;
#endif
{
   addlist(&P->mistakes, makestrlist(s->s[0]));
   addlist(&P->mistakes, makestrlist(comment));
}

#ifdef __STDC__
void 
ckcase (char *s)
#else
void 
ckcase (s)
char *s;
#endif
{
   int             i;

   i = 0;
   while (s[i]) {
      s[i] = toupper(s[i]);
      do {
         i++;
         if (!s[i])
            return;
      }
      while (!isspace(s[i]));
      do
         i++;
      while (isspace(s[i]));
   }
}

#ifdef __STDC__
int
nametocargotype (char *s)
#else
int
nametocargotype (s)
char *s;
#endif
{
   int             i;
   static char    *cargonames[] =
   {
      "cap",
      "mat",
      "col",
      "emp",
   };
   for (i = 0; i != MAXCARGO; i++)
      if (!strcmpl(cargonames[i], s))
         return i;
   return -1;
}

#ifdef __STDC__
group          *
findgroup (player * P, char *s)
#else
group          *
findgroup (P, s)
player * P;
char *s;
#endif
{
   group          *g;

   if (!strcmpl(s, "max")) {
      if (!P->groups)
         return 0;
      for (g = P->groups; g->next; g = g->next);
      return g;
   }
   return numtop(P->groups, s);
}
