#define DISTANCE 6       /* The maximum distance we will move the civs (this
			    value can be over-ridden on the command line*/
#define FACTOR 100
#define NUMTOMOVE 100    /* The number of civs we move (it will be multiplied
			    by minmob/FACTOR where minmob is either specified
			    as the second argument to this program or if
			    there is no second argument, then minmob = 
			    MINMOBTOMOVE) */
#define MINMOBTOMOVE 100 /* only move civs from sectors with this much mob 
			    Note this is only a default--minmob can be passed
			    as a parameter. */

/*
                             cmvr

              written by Ken Stevens for chainsaw 3.0

DESCRIPTION:
This very simple program moves your civs from over-populated sectors into
under-populated sectors.  It works with the output of the census command
(i.e. not dump) so it should work for any version of empire which supports
moving by destination-sector.

INSTALLATION:
This file should be called "cmvr.c".
If you want, change the #defines for DISTANCE, FACTOR, NUMTOMOVE, and
MINMOBTOMOVE below.  (Note: the default values should be fine.)
Then in unix, type:
  chmod +x mvc
  make cmvr

SYNTAX:
    cmvr <safeciv> [<minmob>] [<distance>]
  where <safeciv> is the number of civs you would like to have per
  sector, and the optional argument <minmob> is the minimum
  mobility that a sector must have in order to move civs from it.
  If the optional argument <minmob> is not specified, then the value of
  the #define MINMOBTOMOVE is used.  The third optional argument <distance>
  is how many sectors your civs can move--note that the distance function
  used in this program is very primitive (it uses the box metric).

HOW TO RUN IT:
novice:
  In empire, type:
    cen # >! .cen
  Use the "nation" command to find out your max safe population.  Suppose that
  your max safe population is 666, then in unix you would type:
    cmvr 666 <.cen >! move_script
  Lastly, you would run the move_script in empire to move the civs.

expert:
  In your .eifrc file, put the lines:
    alias cmvr "cen # >! .cen; runfeed cmvr $1 ${2:+} ${3:+}"
    alias cmvr1 "cen * ?ter=1 >! .cen; runfeed cmvr $1 ${2:+} ${3:+}"
    alias cmvr2 "cen * ?ter=2 >! .cen; runfeed cmvr $1 ${2:+} ${3:+}"
    etc...
  Then in eif, you can just type:
    cmvr 666
  or if you want to allow moving from sectors with less mob, you could type
  something like:
    cmvr 666 71

lazy-hacker:
  In my .eifrc file, I have the lines:
alias cmvr "cen # >! .cen; nation >! .nation; runfeed mvc ${1:+} ${2:+} ${3:+}"
alias cmvr1 "cen * ?ter=1 >! .cen; nation >! .nation; runfeed mvc ${1:+} ${2:+} ${3:+}"
alias cmvr2 "cen * ?ter=2 >! .cen; nation >! .nation; runfeed mvc ${1:+} ${2:+} ${3:+}"
etc...
  The mvc script reads my .nation file, figures out my max safe civs, and then
  runs cmvr for me.  So I can just type:
    cmvr
  Or sometimes, to populate a newly conquered island:
    cmvr 200 40 20

BUG REPORTS:
mail your bug-reports and comments to:
stevens@math.utoronto.ca
*/

#include <stdio.h>
#define MAXSECTS 800   /* Our number of sectors must be smaller than this */
#define ABORTIFSAFECIV 50 /* if this program is called with safeciv less than
			      this number, abort the program */

char cor[MAXSECTS][10];
int mob[MAXSECTS];
int civ[MAXSECTS];
char des[MAXSECTS][3];
int eff[MAXSECTS];
int owned[MAXSECTS];
int start, safeciv, minmob;
int n, numtomove, distance;

/* near(a,b) calculates the distance between two sectors in the box metric */

near(a,b)
{
  int x1, y1, x2, y2, d;
  sscanf(a, "%d,%d", &x1,&y1);
  sscanf(b, "%d,%d", &x2,&y2);
  return (abs(x2-x1) < distance && abs(y2-y1) < distance);
}

main(argc,argv)
char **argv;
{
  char s[800], dum[800];
  int i,j,k;
  char d[MAXSECTS];
  
/* parse the command line arguments */

  if (argc < 2 || argc > 4) {
    printf("*#* CMVR ERROR: WRONG NUMBER OF ARGUMENTS *#*\n");
    printf("syntax: cmvr <safeciv> [<minmob>] [<distance>]\n");
    printf("where <safeciv> is the number of civs you would like to have per\n");
    printf("sector, and the optional argument <minmob> is the minimum\n");
    printf("mobility that a sector must have in order to move civs from it.\n");
    exit(1);
  }
  safeciv=atoi(argv[1]);
  if (safeciv < ABORTIFSAFECIV) {
    printf("*#* CMVR ERROR: <safeciv> argument was %d, it must be greater than %d *#*\n", safeciv, ABORTIFSAFECIV);
    exit(1);
  }
  minmob = (argc >= 3)?atoi(argv[2]):MINMOBTOMOVE;
  numtomove = (NUMTOMOVE*minmob)/FACTOR;
  distance = (argc == 4)?atoi(argv[3]):DISTANCE;
  
/* read the output from the census command */

  gets(s);
  while (!feof(stdin) && n < MAXSECTS) {
    sscanf(s, "%s %s %d%s %d %s", cor[n], des[n], &eff[n], d, &mob[n], d);
    if (!strcmp(des[n],"sectors"))
      break;
    sscanf(s + 33, " %d %s", &civ[n], dum);
    if (s[32] == '*')
      owned[n] = 0;
    else
      owned[n] = 1;
    gets(s);
    if (!strcmp(cor[n], "sect"))
      start = 1;
    if (start)
      ++n;
  }

  /* move the civs */

  for (k = 1; k <= 5; ++k)
    for (i = 1; i < n; ++i)
      if (from(i,k))
	if ((i+k)%2) {
	  for (j = 1; j < n; ++j)
	    if (to(j,k) && near(cor[i], cor[j])) {
	      mob[i] -= numtomove;
	      civ[i] -= numtomove;
	      civ[j] += numtomove;
	      printf("move c %s %d %s; &h\n", cor[i], numtomove, cor[j]);
	      break;
	    }	
	}
	else {
	  for (j = n - 1; j >= 1; --j)
	    if (to(j,k) && near(cor[i], cor[j])) {
	      mob[i] -= numtomove;
	      civ[i] -= numtomove;
	      civ[j] += numtomove;
	      printf("move c %s %d %s; &h\n", cor[i], numtomove, cor[j]);
	      break;
	    }	
	}
}

from(i,pass)
int i, pass;
{
  switch (pass) {
  case 3:
  case 4:
    /* If a sector has enough civs, is owned, mobile, not a warehouse, and
       either a 100% road or 100% radar station, move civs from there */
    if (civ[i]>numtomove && owned[i] && mob[i]>=minmob && strcmp(des[i],"w")
	&& eff[i]==100 && (!strcmp(des[i],"+") || !strcmp(des[i],")")))
      return 1;
  case 1:
  case 2:
  case 5:
/*  If a sector is overpopulated, owned, mobile, and not a warehouse,
    move civs from there */
    if (civ[i]>safeciv && owned[i] && mob[i]>=minmob && strcmp(des[i],"w"))
      return 1;
  }
  return 0;
}

to(i,pass)
int i, pass;
{
  switch (pass) {
  case 1:
  case 3:
/* if a sector is owned and underpopulated and that sector is:
     1. not a mountain
     2. not a road
     3. not a bridge
     4. not a radar station
     5. not a capitol
   then move civs there.
*/
    if (civ[i] + numtomove < safeciv && owned[i] &&
	(
	 strcmp(des[i],"^") &&
	 strcmp(des[i],"+") &&
	 strcmp(des[i],"=") &&
	 strcmp(des[i],")") &&
	 strcmp(des[i],"c")
	 )
	)
      return 1;
    break;

  case 2:
  case 4:
/* if a sector is owned and underpopulated and that sector is:
     1. not a mountain
     2. not a 80% road
     3. not a 80% bridge
     4. not a 80% radar station
     5. not a 80% capitol
   then move civs there.
*/
    if (civ[i] + numtomove < safeciv && owned[i] &&
	(
	 strcmp(des[i],"^") &&
	 (
	  (
	   strcmp(des[i],"+") &&
	   strcmp(des[i],"=") &&
	   strcmp(des[i],")") &&
	   strcmp(des[i],"c")
	   ) ||
	  eff[i]<80)
	 )
	)
      return 1;
    break;

  case 5:
/* if a sector is owned and underpopulated and that sector is not a mountain,
   then move civs there.
*/
    if (civ[i] + numtomove < safeciv && owned[i] && strcmp(des[i],"^"))
      return 1;
    break;
  }
  return 0;
}
