#include <stdio.h>
#include <string.h>
#include "sect.h"
#include "util.h"
#include "empire.h"

/*
 * This program generates move commands for feeding sectors that
 * Empire distributions didn't quite handle.
 * The program takes its input in the form of a dump file
 * (default is .dump), and a version file, which must be "ver".
 * Dist-like paths are set up for every sector in the dump file
 * for a minimum cost/shortest path to a warehouse-like sector specified
 * with territory 98, which is assumed to have enough food and mobility.
 * 
 * Territory 98 means a place to send out food from. (I.e. can't be an
 *      autodist distribution center, in order to save mob there.
 */

/*
   This version of autofeed was written by J. Gillogly based on autodist
   code by C. Chase based on inspiration (and an earlier version) by Cowboy Bob
   May 1991
*/

FILE *outfile, *fopen(), *verfile;

#define MAX_PATH_LENGTH 80

#define MAXLINE 128     /* Input line from version */

struct tpathstr {
  char path[MAX_PATH_LENGTH];
  int cost;
  int length;
  sctlst_t  *sct;
} *t_vec; /* an array of the paths to move everywhere */

typedef struct warehouse {
  int x;
  int y;
  sctlst_t * p;
} warehouse;
#define MAXWARES 400

int maxpath = 80;       /* Don't need to be limited to the dist length */
int maxcost = 10000; /* useful for avoiding dist paths to mountains */


/* country is the complete list of the whole country */
sctlst_t  *country, *read_dump();
int c_size; /* number of sectors in the country */

/* Stuff to determine food consumption */
float d, rate, fcrate, obrate, uwbrate, eatrate, babyeat, fgrate, etu;

main(argc,argv)
int argc;
char **argv;
{
  char output_file[80];
  char dump_file[80];
  sctlst_t * p;
  int i;
  warehouse wlist[MAXWARES];
  int warehs; /* number of warehouses in dump file */
  int w;
  char buf[MAXLINE];

  strcpy(output_file,"-");
  strcpy(dump_file,"dump");

  /* read in args */
  while(argc > 1) {
    if (argv[1][0] == '-') {
      switch(argv[1][1]) {
      case 'o': /* output file arg */
        argc--; argv++;
        strcpy(output_file,argv[1]);
        break;
      case 'd': /* dump file arg */
        argc--; argv++;
        strcpy(dump_file,argv[1]);
        break;
      default:
        fprintf(stderr,
                "USAGE: autodist -w x,y [-o outfile ] [-d dumpfile]\n");
        exit(1);
      }
      argc--;
      argv++;
    }
  }
  
  if (0 == strcmp(output_file,"-"))
    outfile = stdout;
  else
    if (NULL == (outfile = fopen(output_file,"w"))) {
      fprintf(stderr,"cannot open %s for output\n",output_file);
      exit(1);
    }

  country = read_dump(dump_file);
  init_country();

  /* Check the version to find out about growth and stuff */
  if ((verfile = fopen("ver", "r")) == NULL)
  {     fprintf(stderr, "Can't open version file \"ver\" for reading.\n");
	fclose(outfile);
	exit(1);
  }
  while (fgets(buf, MAXLINE, verfile) != NULL)
  {
	if (sscanf(buf, "%f civilians will harvest %f food per etu", &d, &rate) == 2)
		fcrate = rate / d;
	if (sscanf(buf, "%f civilians will give birth to %f babies", &d, &rate) == 2)
		obrate = rate / d;
	if (sscanf(buf, "%f uncompensated workers will give birth to %f babies", &d, &rate) == 2)
		uwbrate = rate / d;
	if (sscanf(buf, "In one time unit, %f people eat %f units", &d, &rate) == 2)
		eatrate = rate / d;
	if (sscanf(buf, "%f babies eat %f units", &d, &rate) == 2)
		babyeat = rate / d;
	if (sscanf(buf, "A non-aggi, 100 fertility sector can grow %f food per etu", &d) == 1)
		fgrate = d;
	if (sscanf(buf, "An update consists of %f empire", &d) == 1)
		etu = d;
  }
  fclose(verfile);
/*
  printf("fcrate = %.4f, obrate = %.4f, uwbrate = %.4f, eatrate = %.4f\n",
		fcrate, obrate, uwbrate, eatrate);
  printf("babyeat = %.4f, fgrate = %.4f, etu = %.4f\n", babyeat, fgrate, etu);
 */

  /* Hacks to see how hungry everything is: same code as autodist but with
   * territory 98 instead of 99, so we don't use up mob in the distrib
   * sector.  Typically these really *will* be warehouses.
   */

  /* search through the sector list to find all free food sectors */
  warehs = 0;
  for (p = country; p; p = p->next) 
    if (p->data->sct_terr == 98) {      /* Usually warehouses */
      wlist[warehs].x = p->data->sct_x;
      wlist[warehs].y = p->data->sct_y;
      wlist[warehs].p = p;
      warehs++;
    }

  /* initialize the tree */
  for (i = 0; i < c_size; i++) {
    t_vec[i].cost = -1;
    t_vec[i].length = -1;
    *(t_vec[i].path) = '\0';
  }

  /* construct the dist paths with make_tree */
  for (w = 0; w < warehs; w++) {
    make_tree(wlist[w].p);
  }
  
  /* reverse all the paths so they go from warehouse to destination */
  for (i = 0; i < c_size; i++)
  {     char *s;
	int x, y;

	if (strlen(t_vec[i].path) > 0)
	{
/*              fprintf(outfile, "; path from %d,%d to warehouse: %sh\n",
 *                      t_vec[i].sct->data->sct_x,
 *                      t_vec[i].sct->data->sct_y,
 *                      t_vec[i].path);
 */
		strrev(t_vec[i].path);
/*              fprintf(outfile, ";   reversed: %sh\n", t_vec[i].path); */

		/* Should be an easy way to tell where it goes. */
		x = t_vec[i].sct->data->sct_x;
		y = t_vec[i].sct->data->sct_y;

		for (s = t_vec[i].path; *s; s++)
		{   switch(*s)
		    {   case 'y': *s = 'n'; x--; y--; break;
			case 'u': *s = 'b'; x++; y--; break;
			case 'j': *s = 'g'; x += 2;   break;
			case 'n': *s = 'y'; x++; y++; break;
			case 'b': *s = 'u'; x--; y++; break;
			case 'g': *s = 'j'; x -= 2;   break;
		    }
		}
		t_vec[i].sct->data->dist_x = x;
		t_vec[i].sct->data->dist_y = y;
/*
 *              fprintf(outfile, "; %d,%d gets it from %d,%d.\n",
 *                      t_vec[i].sct->data->sct_x, t_vec[i].sct->data->sct_y,
 *                      x, y);
 *              fprintf(outfile, ";   fixed   : %sh\n", t_vec[i].path);
 */
	}
  }

/*fprintf(outfile, ";Checking hunger.\n");     */
/*for (p = country; p; p = p->next)     */
  for (i = 0; i < c_size; i++)
  {
	/* Variable names correspond pretty well to "Innards" */
	float dd, food, foodtmp, civ, mil, uw, oldfood, fert, dtemp, work;
	int x, y, need;

	p = t_vec[i].sct;

	x    = p->data->sct_x;
	y    = p->data->sct_y;
	food = p->data->coms[FOOD];
	civ  = p->data->coms[CIV];
	mil  = p->data->coms[MIL];
	uw   = p->data->coms[UNC];
	fert = p->data->sct_fertil;
	work = p->data->sct_work;
	oldfood = food;
	dd = etu * fert * fgrate / 100.;
	dtemp = work * fcrate;
	if (dtemp < dd) dd = dtemp;
	foodtmp = food + dd;
	dd = etu * (civ + mil + uw) * eatrate;
	if (dd > foodtmp)
	{ /*    fprintf(outfile, ";%d,%d will starve: %.2f > %.2f.\n", */
	  /*            x, y, dd, foodtmp);                            */
		need = 10 + dd - foodtmp;
		fprintf(outfile, "mo f %d,%d %d %sh\n",
		  p->data->dist_x, p->data->dist_y, need, t_vec[i].path);
	}
  }
  fclose(outfile);

}


init_country()
{
  int i;
  sctlst_t  *p;

  /* count the number of sectors */
  c_size = 0;
  for (p = country; p; p = p->next) 
    p->spec.d = c_size++;
  t_vec = NEWN(struct tpathstr, c_size);
  
  for (i = 0,p = country; i < c_size; i++, p = p->next)
    t_vec[i].sct = p;
    
#ifdef DEBUG
  fprintf(stderr,"%d sectors read from file\n",c_size);
#endif
}


/* set the t_vec array to hold paths to the root node from all sectors */
make_tree(root)
sctlst_t  *root; /* a point on the tree */
{
  int root_id;
  int s_id, d_id;
  int i;
  int thislength;
  int thiscost;
  sctlst_t  *todo; /* the list of sectors to visit */
  sctlst_t  *tail; /* the last sector in the todo list */
  sctlst_t  *tmp; /* used to clear the aux pointer in todo list */
  static char pathdir[7]="nbgyuj";
  char incpath[2]; /* incremental path */
  struct sctstr *sct;

  root_id = root->spec.d;

  sct = root->data;
  t_vec[root_id].cost = 0;
  t_vec[root_id].length = 0;
  *(t_vec[root_id].path) = '\0';

  /* make the root node the only thing on the tree */
  root->aux = NULL;
  todo = root;
  tail = root;
  
  /* build the tree */
  for (; todo != NULL; tmp = todo, todo = todo->aux, tmp->aux = NULL) {
    s_id = todo->spec.d;
    thislength = t_vec[s_id].length + 1;
    if (thislength <= maxpath) {
      for (i = 0; i < 6; i++) {
        if (todo->neighbor[i] != NULL) {
          d_id = todo->neighbor[i]->spec.d;
          sct = todo->neighbor[i]->data;
          thiscost = t_vec[s_id].cost + COST(sct);
          if (thiscost < maxcost) {
            if (t_vec[d_id].cost < 0) {
              /* add it to the tree and put it on the todo list */
              t_vec[d_id].cost = thiscost;
              t_vec[d_id].length = thislength;
              incpath[0] = pathdir[i];
              incpath[1] = '\0';
              strcpy(t_vec[d_id].path,incpath);
              strcat(t_vec[d_id].path,t_vec[s_id].path);
              /* add it to todo list if it's not already there */
              if (!(todo->neighbor[i]->aux)) {
                tail->aux = todo->neighbor[i];
                todo->neighbor[i]->aux = NULL;
                tail = todo->neighbor[i];
              }
            }
            else if (t_vec[d_id].cost > thiscost ||
                     (t_vec[d_id].cost == thiscost && 
                      t_vec[d_id].length > thislength)) {
              /* we've found a better path, make it so */
              t_vec[d_id].cost = thiscost;
              t_vec[d_id].length = thislength;
              incpath[0] = pathdir[i];
              incpath[1] = '\0';
              strcpy(t_vec[d_id].path,incpath);
              strcat(t_vec[d_id].path,t_vec[s_id].path);
              /* add it to todo list if it's not already there */
              if (!(todo->neighbor[i]->aux)) {
                tail->aux = todo->neighbor[i];
                todo->neighbor[i]->aux = NULL;
                tail = todo->neighbor[i];
              }
            }
          }
        }
      }
    }
  }
}

strrev(char *string)  /* Reverse a string */
{
	char *s, *dup, *t;
	int n;

	dup = strdup(string);
	n = strlen(string);
	for (t = &string[n - 1], s = dup; *s; *t-- = *s++);
	Free(dup);      /* From the package that comes with autodist */
}
