static char *rcsid = "$Header: /plaid/homes/zeus/Blind-2.47/cmds/RCS/g.c,v 2.47 1998/04/15 21:34:50 zeus Exp zeus $";

/*
 *
 * $Log: g.c,v $
 * Revision 2.47  1998/04/15 21:34:50  zeus
 * *** empty log message ***
 *
 * Revision 2.45  1997/04/18 12:13:15  zeus
 * *** empty log message ***
 *
 * Revision 2.44  1995/12/31  19:45:18  zeus
 * Revision 2.43  1995/03/20  01:43:09  zeus
 *
 */

#define NOTIMEB
 
#include "common.h"
#include "prototypes.h"
#include "cmds.h"
#include "cmds-g.h"
#include "enterturn-g.h"
#include "misc-g.h"

extern char err_tmp[];
extern int groupno;
extern int comment;

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

void
upgrade_group (player * P, player * Px, group * g, planet * p, int num_to_do)
{
  double cost_each, ind_avail, z;

  ind_avail = effective_ind (p) - p->spent;
  if (ind_avail <= 0.0)
  {
    sprintf (err_tmp, "Planet %s has no remaining industry\n", p->num);
    error (err_tmp);
    return;
  }
  if (P == Px)
    cost_each = upgrade_cost (P, g);
  else

#ifdef PARTTECH
    cost_each = upgrade_partial_tech (P, Px, g);
#else
    assert (0);
#endif

  if (cost_each * num_to_do > ind_avail)	/* Can we do enitre group ? */
  {				/* no, so do as many as possible */
    num_to_do = ind_avail / cost_each;
    if (num_to_do == 0)
      num_to_do++;		/* BUGFIX HJB */
    if (g->ships > 1) /* Need a new group, yet another bugfix */
      g = new_group (P, g, num_to_do);
  }
  z = ind_avail / (double) num_to_do;
  if (z >= cost_each)		/* Can we do an enitire ship or group  ? */
  {
    if (P == Px)
      memcpy (&g->tech.drive, &P->tech.drive, 4 * sizeof (double));

    else
      memcpy (&g->tech.drive, &Px->tech.drive, 4 * sizeof (double));
  }
  else
  {				/* Nope, do partial */
    if (P != Px)
    {
      sprintf (err_tmp, "Cost for upgrade %7.2f, available industry %7.2f\n",
	       (float) cost_each, (float) ind_avail);
      error (err_tmp);
      return;
    }
    else
#ifdef FORECAST
      if (P->opts2 & PEDANTIC) /* Only check in forecaster */
      {
        sprintf (err_tmp, 
                 "Cost for full upgrade %7.2f, available industry %7.2f\n",
	         (float) cost_each, (float) ind_avail);
        error (err_tmp); /* Do _not_ return, this is a warning */
      }
#endif
    z /= cost_each;
    cost_each *= z;
    g->tech.drive = g->tech.drive + (P->tech.drive - g->tech.drive) * z;
    g->tech.guns = g->tech.guns + (P->tech.guns - g->tech.guns) * z;
    g->tech.shields = g->tech.shields + (P->tech.shields - g->tech.shields) * z;
    g->tech.cargo = g->tech.cargo + (P->tech.cargo - g->tech.cargo) * z;
  }
  cktech (g);
  g->dist = UPG;
  p->spent += cost_each * (double) num_to_do;
  assert (p->spent <= effective_ind (p) + ALMOSTZERO);
}

void
g_cmd (char *buf, player * P)
{
  int i;
  group *g;

  int num_to_do;
  planet *p;

#ifdef PARTTECH
  char v[MAXTEXT];

#endif

  cmd_init(buf);
  g = ninputgroup (P);
  if (!g)
  {
    error (err_tmp);
    return;
  }
  if (group_check (P, g, NULL, groupno, G_DIST | G_OWNPLANET))
  {
    error (err_tmp);
    return;
  }
  i = ngeti ();
  if (i == NAI)
    comment = 1;
  else 
    comment = 0;
  if (i == BADI)
  {
    error (err_tmp);
    return;
  }
  if (i < 0)
    i = 0;			/* Too few tokens */
  if ((i > 0) && (g->ships != i))
  {
    if (i >= g->ships)
    {
      sprintf (err_tmp, "Not enough ships in group %d.\n", groupno);
      error (err_tmp);
      return;
    }
    g = new_group (P, g, i);
  }
  if (i == 0)
    i = g->ships;
  p = g->where;

  num_to_do = i;

#ifdef PARTTECH
  if (!comment)
  {
  hstrncpy (v, next_token (),MAXTEXT);	/* Optional tech spec? */
  /* if ((v[0]) && (v[0] != ';') && (v[0] != '#')) */
  if (v[0])
  {
    player *Px;

    assert (v[0] != ';');
    assert (v[0] != '#');

    Px = alloc (sizeof (player));
    memset (Px, 0, sizeof (player));

    if ((Px->tech.drive = get_tech (v, P->tech.drive)) < 0.0)
    {
      error (err_tmp);
      return;
    }
    hstrncpy (v, next_token (),MAXTEXT);
    if ((Px->tech.guns = get_tech (v, P->tech.guns)) < 0.0)
    {
      error (err_tmp);
      return;
    }
    hstrncpy (v, next_token (),MAXTEXT);
    if ((Px->tech.shields = get_tech (v, P->tech.shields)) < 0.0)
    {
      error (err_tmp);
      return;
    }
    hstrncpy (v, next_token (),MAXTEXT);
    if ((Px->tech.cargo = get_tech (v, P->tech.cargo)) < 0.0)
    {
      error (err_tmp);
      return;
    }
    if (Px->tech.drive == 0.0)
      Px->tech.drive = g->tech.drive;
    if (Px->tech.guns == 0.0)
      Px->tech.guns = g->tech.guns;
    if (Px->tech.shields == 0.0)
      Px->tech.shields = g->tech.shields;
    if (Px->tech.cargo == 0.0)
      Px->tech.cargo = g->tech.cargo;

    if ((Px->tech.drive > P->tech.drive) || ((Px->tech.drive < 1.0) && (Px->tech.drive != 0.0)) ||
	((g->tech.drive > Px->tech.drive) && (g->tech.drive > 0.0)))
    {
      error ("Assigned drive tech invalid\n");
      return;
    }
    if ((Px->tech.guns > P->tech.guns) ||
	((Px->tech.guns < 1.0) && (Px->tech.guns != 0.0)) ||
	((g->tech.guns > Px->tech.guns) && (g->tech.guns > 0.0)))
    {
      error ("Assigned weapons tech invalid\n");
      return;
    }
    if ((Px->tech.shields > P->tech.shields) || ((Px->tech.shields < 1.0) &&
					       (Px->tech.shields != 0.0)) ||
	((g->tech.shields > Px->tech.shields) && (g->tech.shields > 0.0)))
    {
      error ("Assigned shield tech invalid\n");
      return;
    }
    if ((Px->tech.cargo > P->tech.cargo) || ((Px->tech.cargo < 1.0) && (Px->tech.cargo != 0.0)) ||
	((g->tech.cargo > Px->tech.cargo) && (g->tech.cargo > 0.0)))
    {
      error ("Assigned cargo tech invalid\n");
      return;
    }
    upgrade_group (P, Px, g, p, num_to_do);
    free (Px);
  }
  else
    comment = 1;
  }
  if (comment==1)
#endif
  {
    upgrade_group (P, P, g, p, num_to_do);
  }
  extra_token ();
}
