static char *rcsid = "$Header: /plaid/homes/zeus/Blind-2.47/report/RCS/status.c,v 2.46 1997/04/18 12:25:12 zeus Exp $";

/*
 * $Log: status.c,v $
 * Revision 2.46  1997/04/18 12:25:12  zeus
 * *** empty log message ***
 *
 * Revision 2.45  1997/01/01  00:31:10  zeus
 * Revision 2.43  1995/03/20  01:43:09  zeus
 *
 */

#define NOTIMEB
#include "common.h"
#include "prototypes.h"
#include "report-g.h"
#include "report.h"
#include "misc-g.h"
#include "options.h"

extern player *players;
extern planet *planets;
extern battle *battles;
extern bombing *bombings;

#ifdef FORECAST
extern int seenlist[];

#endif

void report_status_rcsid (void);

void
report_status_rcsid (void)
{
  printf ("%s\n", rcsid);
}

int
status (player * P1, player * P2)
{
  alliance *a;
  defensive *d;

  if (P1 == P2)
    return 0;
  else
  {
    for (a = P1->allies; a; a = a->next)
      if (a->ally == P2)
      {
	return PEACE;
      }
    for (d = P1->defend; d; d = d->next)
      if (d->defend == P2)
      {
	return GUARD;
      }
  }
  return WAR;
}

/* Someday:
   double blind carryover- only print ones seen this turn. */

void
report_player_status (double *max, double *pop, double *ind, int *i, int *j,
		      player * P, player * P2, int gm)
{
  /* if gm != 0, then we are the GM (i.e. omnipetent) */
  /*
   * P = player we are generating the report for, P2 = Player we are looking
   * for
   */

  planet *p;
  group *g;
  battle *B;
  participant *PA;
  viewer *V;
  bombing *b;

  *pop = *ind = *max = 0.0;
  *j = *i = 0;

  /* Go through each planet, and if you can see it, add to total */
  for (p = planets; p; p = p->next)

#ifdef FORECAST
    if ((p->owner == P2) && (gm || (seenlist[ptonum (planets, p)])))
#else
    if ((p->owner == P2) && (gm || (canseeplanet (P, p,1))))
#endif

    {
      *max += p->size;
      *pop += p->pop;
      *ind += p->ind;
      (*i)++;
    }

#ifndef BLINDCARRY
  {
    techinfo *t;

    for (t = P->othertechs; t; t = t->next)
      if (t->whoose == P2)
      {
	(*j) = 1;
	return;
      }
  }
#endif

  if (!(gm || *i))
    /* Does player have any groups we can see? */
    for (g = P2->groups; g; g = g->next)
      if (canseegroup (P, g))
	(*j)++;
  for (B = battles; B; B = B->next)
  {
    for (V = B->viewers; V; V = V->next)
      if (V->who == P)
	break;
    if (V)
    {
      for (PA = B->participants; PA; PA = PA->next)
      {
	if (PA->who == P2)
	  (*j)++;
      }
    }
  }

  for (b = bombings; b; b = b->next)
  {
    for (V = b->viewers; V; V = V->next)
      if ((b->whoose == P2) && (V->who == P))
	(*j)++;
  }
}

void
guess_techs (player * P, player * P2)
{
  double d, w, s, c;
  group *g;
  battle *B;
  participant *PA;
  viewer *V;
  techinfo *t;

  for (t = P->othertechs; t; t = t->next)
    if (t->whoose == P2)
      break;
  if (t)
  {
    d = t->tech.drive;
    w = t->tech.guns;
    s = t->tech.shields;
    c = t->tech.cargo;
  }
  else
  {
    d = w = s = c = 1.0;
    t = alloc (sizeof (techinfo));
    t->whoose = P2;
    addlist (&P->othertechs, t);
  }

  for (g = P2->groups; g; g = g->next)
    if (canseegroup (P, g))
    {
      d = max (g->tech.drive, d);
      w = max (g->tech.guns, w);
      s = max (g->tech.shields, s);
      c = max (g->tech.cargo, c);
    }
  for (B = battles; B; B = B->next)
  {
    for (V = B->viewers; V; V = V->next)
      if (V->who == P)
	break;
    if (V)
    {
      for (PA = B->participants; PA; PA = PA->next)
      {
	if (PA->who == P2)
	  for (g = PA->groups; g; g = g->next)
	  {
	    d = max (g->tech.drive, d);
	    w = max (g->tech.guns, w);
	    s = max (g->tech.shields, s);
	    c = max (g->tech.cargo, c);
	  }
      }
    }
  }
  ff (d);
  ff (w);
  ff (s);
  ff (c);

/* Should be set already. */
  assert (t != NULL);
  t->tech.drive = d;
  t->tech.guns = w;
  t->tech.shields = s;
  t->tech.cargo = c;
}

void
calc_status_mass (player * P, player * P2, int *num, double *mass, double *techmass, int flag)
{
  double tmass;
  group *g;

  *mass = *techmass = 0.0;
  *num = 0;
  for (g = P2->groups; g; g = g->next)
  {
    if ((P == P2) || (flag || canseegroup (P, g)))
    {
      *num += g->ships;
      tmass = g->ships * typemass (g->type);
      *mass += tmass;
      *techmass += g->ships * ttechmass(g);
    }
  }
}

void
print_status (player * P, int num)
{				/* num = 0 -> forecast, 1 -> normal */
  player *P2;
  double max, pop, ind;
  int i, j;

  assert ((num==NORM_STS)||(num==FORE_STS));
  if (P->opts2 & TECHPLUS)
  {
    fbegin ("Status of Players", "xfffffffixiff");
    fhead ("NDWSCMPI#R&MT");
  }
  else
  {
    fbegin ("Status of Players", "xfffffffix");
    fhead ("NDWSCMPI#R");
  }
  report_player_status (&max, &pop, &ind, &i, &j, P, P, 0);
  fs (P->name);
  ff (P->tech.drive);
  ff (P->tech.guns);
  ff (P->tech.shields);
  ff (P->tech.cargo);
  ff (max);
  ff (pop);
  ff (ind);
  fi (i);
  fs ("");
  if (P->opts2 & TECHPLUS)	/* Tech stuff for you */
  {
    int nums;
    double mass, techmass;

    calc_status_mass (P, P, &nums, &mass, &techmass, 0);
    fi (nums);
    ff (mass);
    ff (techmass);
  }
  if (num==NORM_STS)			/* Normal report */
  {
    for (P2 = players; P2; P2 = P2->next)
    {
      /*
       * If you cannot see any planets or ships belonging to a player, don't
       * show anything about them
       */
      if (P != P2)
      {
	report_player_status (&max, &pop, &ind, &i, &j, P, P2, 0);
	if (i || j)
	{
	  fs (P2->name);
	  guess_techs (P, P2);	/* Determine & print tech info */
	  ff (max);
	  ff (pop);
	  ff (ind);
	  fi (i);
	  switch (status (P, P2))
	  {
	  case PEACE:
	    fs ("P");
	    break;
	  case GUARD:
	    fs ("G");
	    break;
	  case WAR:
	    fs ("W");
	    break;
	  }
	  if (P->opts2 & TECHPLUS)
	  {
	    int nums;
	    double mass, techmass;

	    calc_status_mass (P, P2, &nums, &mass, &techmass, 0);
	    fi (nums);
	    ff (mass);
	    ff (techmass);
	  }
	}
      }
    }
  }

#ifndef BLINDCARRY
  else
  { /* This is a forecast */
    techinfo *t;

    for (t = P->othertechs; t; t = t->next)
      if (t->whoose)
      {
	fs (t->whoose->name);
	ff (t->tech.drive);
	ff (t->tech.guns);
	ff (t->tech.shields);
	ff (t->tech.cargo);
        report_player_status (&max, &pop, &ind, &i, &j, P, t->whoose, 0);
        ff (max);ff(pop);ff(ind);fi(i);
	switch (status (P, t->whoose))
	{
	case PEACE:
	  fs ("P");
	  break;
	case GUARD:
	  fs ("G");
	  break;
	case WAR:
	  fs ("W");
	  break;
	}
	if (P->opts2 & TECHPLUS)
	{
	  fi (0);
	  ff (0.0);
	  ff (0.0);
	}
      }
  }
#endif

  fend ();
}
