#!/bin/awk -f
#
#		strader [files]
#       navs and scuttles trade ships.
#
#
#
#	Reads the following file formats.
#		dump
#		nation
#		report
#		relations
#		ship
#		cargo
#		unit
#		lcargo
#		spy
#		look  
  
function max(x,y) {
  if (x>y) return x;
  return y;
}
function min (x,y) {
  if (x<y) return x;
  return y;
}

function num(str) {
  return substr(str,1,length(str)-1);
}
#
#	Turns a letter into a name.  Tries the first letter, if that
#	isn't a commodity, tries the last letter (useful for ship, unit,
#	and prod outputs)
#
function commstr(str) {
  char=substr(str,1,1);
  if (char == "c") return "civ";
  if (char == "m") return "mil";
  if (char == "u") return "uw";
  if (char == "f") return "food";
  if (char == "s") return "shell";
  if (char == "g") return "gun";
  if (char == "p") return "pet";
  if (char == "i") return "iron";
  if (char == "d") return "dust";
  if (char == "b") return "bar";
  if (char == "o") return "oil";
  if (char == "l") return "lcm";
  if (char == "h") return "hcm";
  if (char == "r") return "rad";

  char=substr(str,length(str),1);
  if (char == "c") return "civ";
  if (char == "m") return "mil";
  if (char == "u") return "uw";
  if (char == "f") return "food";
  if (char == "s") return "shell";
  if (char == "g") return "gun";
  if (char == "p") return "pet";
  if (char == "i") return "iron";
  if (char == "d") return "dust";
  if (char == "b") return "bar";
  if (char == "o") return "oil";
  if (char == "l") return "lcm";
  if (char == "h") return "hcm";
  if (char == "r") return "rad";
  return "";
}

#
#	Truncate starting and ending whitespace from a string
#
function truncwhite(str,  i,j) {
  for (i=1;i<=length(str) && substr(str,i,1) ~ "[ \t\r\n]";i++) ;
  for (j=length(str);j>i && substr(str,j,1) ~ "[ \t\r\n]";j--) ;
  return (substr(str,i,j-i+1));
}


BEGIN {
  SUBSEP=",";
  mode="";
  stat=0;
  
  ships=0;
  shipnamlen=16;
  
# some defaults so I don't have to parse *everything*
  width=192;
  height=96;

  weight["civ"]=1;	packing["civ"]=1;
  weight["mil"]=1;	packing["mil"]=1;
  weight["uw"]=2;	packing["uw"]=1;
  weight["food"]=1;	packing["food"]=10;
  weight["shell"]=1;	packing["shell"]=10;
  weight["gun"]=10;	packing["gun"]=10;
  weight["pet"]=1;	packing["pet"]=10;
  weight["iron"]=1;	packing["iron"]=10;
  weight["dust"]=5;	packing["dust"]=10;
  weight["bar"]=50;	packing["bar"]=5;
  weight["oil"]=1;	packing["oil"]=10;
  weight["lcm"]=1;	packing["lcm"]=10;
  weight["hcm"]=1;	packing["hcm"]=10;
  weight["rad"]=8;	packing["rad"]=10;
}



/.* Nation Report/ {
  if ($1 in number) coun=number[$1];
  country[coun]=$1;
  number[$1]=coun;
  next;
}


/^.+ \(#[0-9]+\) .+ [0-9]+% efficient .* @ .+,.+/ {
  
  i=1;
  while ($i == "ship(s)?") i++;
  
  i=index($0,"(#");
  j=index($0,")");
  c=truncwhite(substr($0,i+2,j-i-2));
  name=truncwhite(substr($0,1,i-1));
  country[coun]=name;
  number[name]=c;
  
  i=match($0,"[0-9]+%");
  sectype=substr($0,j+1,i-j-2);
  
  if (sectype == " sea") sec=".";
  else if (sectype == " mountain") sec="^";
  else if (sectype == " sanctuary") sec="s";
  else if (sectype == " wasteland") sec="/";
  else if (sectype == " wilderness") sec="-";
  else if (sectype == " capital") sec="c";
  else if (sectype == " uranium mine") sec="u";
  else if (sectype == " park") sec="p";
  else if (sectype == " defense plant") sec="d";
  else if (sectype == " shell industry") sec="i";
  else if (sectype == " mine") sec="m";
  else if (sectype == " gold mine") sec="g";
  else if (sectype == " harbor") sec="h";
  else if (sectype == " warehouse") sec="w";
  else if (sectype == " airfield") sec="*";
  else if (sectype == " agribusiness") sec="a";
  else if (sectype == " oil field") sec="o";
  else if (sectype == " light manufacturing") sec="j";
  else if (sectype == " heavy manufacturing") sec="k";
  else if (sectype == " fortress") sec="f";
  else if (sectype == " technical center") sec="t";
  else if (sectype == " research lab") sec="r";
  else if (sectype == " nuclear plant") sec="n";
  else if (sectype == " library/school") sec="l";
  else if (sectype == " highway") sec="+";
  else if (sectype == " radar installation") sec=")";
  else if (sectype == " weather stn (useless)") sec="!";
  else if (sectype == " retirement home (useless)") sec="!";
  else if (sectype == " headquarters") sec="!";
  else if (sectype == " bridge head") sec="#";
  else if (sectype == " bridge span") sec="=";
  else if (sectype == " bank") sec="b";
  else if (sectype == " refinery") sec="%";
  else if (sectype == " enlistment center") sec="e";
  else {
    printf("# Unknown sector type `%s'\n",sectype);
    printf("# %s\n",$0);
    sec="?";
  }

  j=index($0,"%");
  seceff = substr($0,i,j-i);

  for (i=1;i<=NF;i++) if ($i=="with") break;

  while ($i == "with") {
    approx=0;
    i++;
    if ($i == "approx") { i++; approx=4; }
    if ($(i+1)=="civ") {
      secciv = $i + approx;
    } else if ($(i+1)=="mil") {
      secmil = $i + approx;
    } else {
      printf("# Expected either civ or mil.  Got %s\n",$(i+1)) ;
    }
    i += 2;
  }
  
  i++;
  n=split($i,a,",");
  sect=$i;
  val[sect,"x"]=a[1];
  val[sect,"y"]=a[2];
  val[sect,"des"]=sec;
  val[sect,"eff"]=seceff;
  val[sect,"civ"]=secciv;
  val[sect,"mil"]=secmil;
  own[sect]=c;
  oldown[sect]=c;
}


/^bmap/ {    
  getline;
  header[0]=$0
  getline;
  header[1]=$0;

  colskip = match(header[0],"[0-9\-]");
  if (!colskip) printf("error reading bmap\n") >> "/dev/tty";
  columns = length(header[0])-colskip+1;
  
  left=substr(header[0],colskip,1)*10+substr(header[1],colskip,1);
  right=substr(header[0],length(header[0]),1)*10+substr(header[1],length(header[1]),1);
  left2=substr(header[0],colskip+1,1)*10+substr(header[1],colskip+1,1);
  right2=substr(header[0],length(header[0])-1,1)*10+substr(header[1],length(header[1])-1,1);
  
  if (left2<left) left = -left;
  if (right2>right) right = -right;

  getline;
  while (match($0,"[0-9\-]")<colskip) {
    y=$1;
    x=left;
    for (col=colskip;col<columns;col++) {
      if ( (x+y)/2 == int((x+y)/2) ) {
	des=substr($0,col,1);
	if (des=="?") des="+";
	if (match(des,"[s^cupdimghw\\*aojkftrnl+)!#=b%eX\-]")) {
          bdes[x,y]=des;
	}
      }
      x++;
      if (x>=width/2) x -= width;
    }
    getline;
  }
}

/shp#     ship type  orig x,y       x,y    \$\$/ {
  while (getline) {
    if (index($0,"ships")) break;
    shiporig[$1]=truncwhite(substr($0,23,8));
  }
}

/shp#     ship type       x,y   flt  dest1 pick dest2  pick dist eta/ {  
  while (getline) {
    if (index($0,"ships")) break;
    if ($NF == "path") {
      shipdest1[$1]="sail";
    } else {
      shipdest1[$1]=truncwhite(substr($0,36,7));
      shipeta[$1]=$NF;
      shipdist[$1]=$(NF-1);
    }
  }
}


/.* Diplomatic Relations Report/ {
  i=match($0,"Diplomatic Relations Report");
  name=truncwhite(substr($0,1,i-2));
  getline; getline;
  while (getline) {
    if (NF<4) break;
    relname=truncwhite(substr($0,6,20));
    number[relname]=substr($1,1,length($1)-1);
    country[number[relname]]=relname;
    relation[name,relname]=truncwhite(substr($0,28,10));
    relation[relname,name]=truncwhite(substr($0,39,10));
  }

  next;
}


/ *DUMP SECTOR/ { mode="dump"; stat=1; next; }
/^shp#     ship type       x,y   fl  eff civ mil  uw  fd pn he xl ln mob fuel tech/ { mode="ship"; stat=1; next; }
/^shp# ship type           x,y   flt  eff  sh gun pet irn dst bar oil lcm hcm rad/ { mode="cargo"; stat=1; next; }


/ *lcm hcm avail tech \$/ {mode="ssb"; stat=1; next;}
/ *cargos & capabilities/ {mode="ssc"; stat=1; next; }
/ *def  d  s  y  g  r  d  n  l  l/ {mode="sss"; stat=1; next; }

{
  if (mode=="dump") {
    if (stat==1) {
      for (i=1;i<=NF;i++) header[i]=$i;
      nheader=NF;
      stat=2;
      break;
    }
    
    if (NF != nheader) {
      stat=0;
    }
    
    if (stat==2) {
      dump[coun]++;
      for (i=1;i<=nheader;i++) temp[header[i]] = $i;
      sect = temp["x"] "," temp["y"];
      for (i=1;i<=nheader;i++) val[sect,header[i]] = $i;
      
      if (val[sect,"*"]=="*") oldown[sect]=0;
      else if ("own" in temp) oldown[sect]=val[sect,"own"];
      else oldown[sect]=coun;
      if ("own" in temp) own[sect]=val[sect,"own"];
      else own[sect]=coun;
    }
  } else if (mode=="ssb") {
    if (stat==1 && NF > 5) {
      name=truncwhite(substr($0,1,shipnamlen));
      shipcost[name]=substr($NF,2);
      shiptech[name]=$(NF-1);
      shipavail[name]=$(NF-2);
      shiplcm[name]=$(NF-3);
      shiphcm[name]=$(NF-4);
      next;
    } else {
      mode="";
      stat=0;
      next;
    }
  } else if (mode=="sss") {
    if (stat==1 && NF > 11) {
      name=truncwhite(substr($0,1,shipnamlen));
      nf=split(substr($0,21),a,"[ \t/]*");
      shipdef[name]=a[2];
      shipspd[name]=a[3];
      shipvis[name]=a[4];
      shipspy[name]=a[5];
      shiprng[name]=a[6];
      shipfir[name]=a[7];
      shiplnd[name]=a[8];
      shippln[name]=a[9];
      shiphel[name]=a[10];
      shipxpl[name]=a[11];
      shipfc[name]=a[12];

      shipfu[name]=a[13];
      next;
    } else {
      mode="";
      stat=0;
      next;
    }
  } else if (mode=="ssc") {
    if (stat==1 && NF > 3) {
      name=truncwhite(substr($0,1,shipnamlen));
      nf=split(substr($0,21),a,"[ \t/]*");
      for (i=2;i<=nf;i++) {
	if (a[i] ~ "[0-9]+[cmufsgpidbolhr]") {
	  shipcargo[name,commstr(a[i])] = num(a[i]);
	} else {
	  capability[name] = capability[name] " " a[i] " ";
	}
      }
      next;
    } else {
      mode="";
      stat=0;
      next;
    }
  } else if (mode=="ship") {
    if (stat==1) {
      ships=0;
      for (i in shiporder) delete shiporder[i];
      stat=2;
    }
    if (stat==2 && NF > 2) {
      name=truncwhite(substr($0,6,shipnamlen));
      shiporder[ships++]=$1;
      shipname[$1]=name;
      shipown[$1]=coun;
      shiptech[$1]=$NF;
      shipfuel[$1]=$(NF-1);
      shipmob[$1]=$(NF-2);
      shiplnd[$1]=$(NF-3);
      shipxlnd[$1]=$(NF-4);
      shiphel[$1]=$(NF-5);
      shippln[$1]=$(NF-6);
      shipcargo[$1,"food"]=$(NF-7);
      shipcargo[$1,"uw"]=$(NF-8);
      shipcargo[$1,"mil"]=$(NF-9);
      shipcargo[$1,"civ"]=$(NF-10);
      shipeff[$1]=num($(NF-11));
      shipfleet[$1]=substr($0,33,1);
      shipsect[$1]=truncwhite(substr($0,22,9));
      next;
    } else {
      mode="";
      stat=0;
      next;
    }
  } else if (mode=="cargo") {
    if (stat==1) {
      ships=0;
      for (i in shiporder) delete shiporder[i];
      stat=2;
    }
    if (stat==2 && NF > 10) {
      name=truncwhite(substr($0,6,shipnamlen));
      shiporder[ships++]=$1;
      shipname[$1]=name;
      shipown[$1]=coun;
      shipcargo[$1,"rad"]=$NF;
      shipcargo[$1,"hcm"]=$(NF-1);
      shipcargo[$1,"lcm"]=$(NF-2);
      shipcargo[$1,"oil"]=$(NF-3);
      shipcargo[$1,"bar"]=$(NF-4);
      shipcargo[$1,"dust"]=$(NF-5);
      shipcargo[$1,"iron"]=$(NF-6);
      shipcargo[$1,"pet"]=$(NF-7);
      shipcargo[$1,"gun"]=$(NF-8);
      shipcargo[$1,"shell"]=$(NF-9);
      shipeff[$1]=num($(NF-10));
      shipfleet[$1]=substr($0,31,1);
      shipsect[$1]=truncwhite(substr($0,22,9));
      next;
    }
  } else {
    mode="";
    stat=0;
    next;
  }
  
}



# calculate hexes between two sectors
function distance(from,to, a,b,deltax,deltay)
{
  split(from,a,",");
  split(to,b,",");

  deltax=b[1]-a[1];
  if (deltax<0) deltax = -deltax;
  if (deltax>width/2) deltax=width-deltax;
  deltay=b[2]-a[2];
  if (deltay<0) deltay = -deltay;
  if (deltay>height/2) deltay=height-deltay;

  if (deltax>deltay) return ((deltax-deltay)/2+deltay);
  return (deltay);
}

function navigable(sect)
{
  if (!(sect in bdes) || bdes[sect]=="") return 1;
  if (bdes[sect]=="=") {
    if (!((sect,"eff") in val) || val[sect,"eff"]>59) {
      if (own[sect]==coun) return 1;
      if (relation[country[own[sect]],country[coun]]=="Allied") return 1;
    }
    return 0;
  }
  if (bdes[sect]=="h") {
    if (!((sect,"eff") in val) || val[sect,"eff"]>1) {
      if (own[sect]==coun) return 1;
      if (relation[country[own[sect]],country[coun]]=="Allied") return 1;
    }
  }
  return 0;
}

function normsect(x,y)
{
  if (x>=width/2) x -= width;
  if (y>=height/2) y -= height;
  if (x<-width/2) x += width;
  if (y<-height/2) y += height;
  return x "," y ;
}

# build navigation paths
function navbuild(path,navlen, sect,added,x,y,tmp)
{
  if (navlen=="") {
    for (sect in path) if (path[sect]>navlen) navlen=path[sect];
  }

  added=0;
  for (sect in path) if (path[sect]==navlen) {
    split(sect,a,",");
    x=a[1];
    y=a[2];

    tmp= normsect(x+2,y);
    if (!(tmp in path) && navigable(tmp)) { path[tmp]=navlen+1; added++; }
    tmp=normsect(x-2,y);
    if (!(tmp in path) && navigable(tmp)) { path[tmp]=navlen+1; added++; }
    tmp= normsect(x+1,y+1);
    if (!(tmp in path) && navigable(tmp)) { path[tmp]=navlen+1; added++; }
    tmp= normsect(x+1,y-1);
    if (!(tmp in path) && navigable(tmp)) { path[tmp]=navlen+1; added++; }
    tmp= normsect(x-1,y+1);
    if (!(tmp in path) && navigable(tmp)) { path[tmp]=navlen+1; added++; }
    tmp= normsect(x-1,y-1);
    if (!(tmp in path) && navigable(tmp)) { path[tmp]=navlen+1; added++; }
  }

  return added;
}

# returns navigation path.  Optionally pass path array from buildcost.
function navpath(from,to, path,pathlen,x,y,a,b)
{
  pathlen=0;
  path[to]=0;
  for (sect in path) delete path[sect];
  path[to]=0;
  while ( navbuild(path,pathlen) && !(from in path)) pathlen++;
  if (to in path) {
    sect=from;
    nav="";
    for (i=pathlen;i>=0;i--) {
      split(sect,a,",");
      for (newsect in path) if (path[newsect]==i) {
	split(newsect,b,",");
	x=b[1]-a[1];
	y=b[2]-a[2];
	if (x==2 && y==0) { nav=nav "j"; break; }
	else if (x==1 && y==1) { nav=nav "n"; break; }
	else if (x==-1 && y==1) { nav=nav "b"; break; }
	else if (x==-2 && y==0) { nav=nav "g"; break; }
	else if (x==-1 && y==-1) { nav=nav "y"; break; }
	else if (x==1 && y==-1) { nav=nav "u"; break; }
      }
      if (path[newsect]==i) {
	sect=newsect;
      } else {
	printf("# error from=%s to=%s nav=%s sect=%s pathlen=%s i=%s\n",
	       from,to,nav,sect,pathlen,i);
	return "";
      }
    }
  }
  return nav;
}


END {
  for (n in shipname) {
    speed=shipspd[shipname[n]];
    shiprange[n]=int(0.9999 + shipmob[n]*((speed+speed*(50+shiptech[n])/(200+shiptech[n]))*shipeff[n]/100)/480);
  }

  for (sect in own) {
    if (val[sect,"des"]=="h" && relation[country[own[sect]],country[coun]]=="Allied") {
      allyharbor[sect]=own[sect];
    }
    if (own[sect]==coun) {
      harbor[sect]=own[sect];
    }
  }

  for (n in shipname) {
    if (index(capability[shipname[n]],"oiler")) {
      if (shipcargo[n,"oil"]>0 || shipcargo[n,"pet"]>10) {
	oiler[shipsect[n]]=n;
      }
    }
  }
  

  for (n in shiporig) {
    if (shipeta[n]==1 && shipeff[n]==100 && (n in shiporig)) {
      printf("nav %d %sh\n\n",navpath(shipsect[n],shipdest1[n]));
      scuttle[n]=1;
    }
  }

  printf("# scuttle s\n");
  printf("ship ");
  for (n in scuttle) {
    printf("%d/",n);
  }
  printf("\n");

}
