/* Program:	Zappa					*/
/* David Roe						*/
/* Email:	roe@research.att.com			*/
/* Compile:	cc -O Zappa.c				*/
/* Run:		a.out FILENAME 
#include 
#include 

/*******************/
/*      MACROS     */
/*******************/
#define MAXROW 9        /* number of rows			*/
#define MAXCOL 26       /* number of columns			*/
#define MAXMOVE 100     /* max number of moves in the game	*/
#define LINEL 80        /* maximum line length in input		*/
#define INST_SIZE 9     /* maximum characters in an instruction */
#define FFACTOR 1.0     /* Fudge-factor for leaky average	*/
#define min(x,y) ((x)<(y) ? (x) : (y))
#define max(x,y) ((x)>(y) ? (x) : (y))
#define abs(x) (((x)>0) ? (x) : (-(x)))
#define round(x) (((x)>0) ? (int)((x)+.5) : (int)((x)-.5))
#define out4(f,ss,inst) if(inst.comm[0]!='\0') fprintf(f,"%s   \t%s\n",ss,inst2str(buf,&inst))
#define out3(f,str,row,col) fprintf(f,"%s\t%c %d\n",str,'A'-1+row,col)
#define out2(f,str,value) fprintf(f,"%s %d\n",str,value)
#define outfloat(f,str,value) fprintf(f,"%s %.2f\n",str,value)
#define SOK(x) strtok(x," \t\n")
#define SOK2 strtok(NULL," \t\n")

/********************/
/*  STRUCTURE DEFN  */
/********************/
struct Inst {
  char comm[INST_SIZE+1];
  int row;
  int col;
};

/*******************/
/* EXTERNAL MEMORY */
/*******************/
int wall_r[2*MAXMOVE], wall_c[2*MAXMOVE], nwalls=0;

/*******************/
/*   SUBROUTINES   */
/*******************/
int normc(int col) {			/* Truncate to a column value	*/
  if(col<=1) return 1;			/* between 1 and MAXCOL		*/
  if(col>=MAXCOL) return MAXCOL;
  return(col);
}

int normr(int row) {			/* Truncate to a row value	*/
  if(row<1) return 1;			/* between 1 and MAXROW		*/
  if(row>MAXROW) return MAXROW;
  return(row);
}

char *inst2str(char *buf,struct Inst *pinstr) {
  if(pinstr->row>0)
    sprintf(buf,"%s %c %d",pinstr->comm,'A'-1+pinstr->row,pinstr->col);
  else
    sprintf(buf,"%s",pinstr->comm);
  return buf;
}

int is_wallat(int row, int col) {	/* Check if a wall is at (row,col) */
  int i;
  for(i=0;iMAXROW||mcol>MAXCOL)
    return(5);					/* move off the board	*/
  if(mrow==frow) {
    if(mcol==fcol) return(3);			/* same space		*/
    if(abs(mcol-fcol)==1) {
      if(is_wallat(mrow,mcol)) return(1);	/* there's a wall there */
      return(0);				/* a legal move		*/
    }
    else return(2);				/* OK for zap, not for move */
  }
  else if(mcol==fcol) {
    if(abs(mrow-frow)==1) {
      if(is_wallat(mrow,mcol)) return(1);	/* there's a wall there */
      return(0);				/* a legal move		*/
    }
    else return(2);				/* OK for zap, not for move */
  }
  else return(4);				/* too far to move	*/
}

void dumpout(FILE *fp, int me_first, int my_row, int my_col, int my_turns,
int op_row,int op_col,int op_turns,
int max_row, int max_col, float rv_dist, float cv_dist, float v_time,
int my_hello,int my_ouchs,
int nwalls, int *wall_r, int *wall_c,
struct Inst c_move, struct Inst p_feedback, struct Inst p_move) {
  int i;
  char buf[LINEL+1];
  out2(fp,"me_first", me_first);
  out3(fp,"my_pos",my_row,my_col);
  out2(fp,"my_turns", my_turns);
  out3(fp,"op_pos",op_row,op_col);
  out2(fp,"op_turns", op_turns);
  out3(fp,"max_pos",max_row,max_col);
  outfloat(fp,"rv_dist",rv_dist);
  outfloat(fp,"cv_dist",cv_dist);
  outfloat(fp,"v_time",v_time);
  if(my_hello>0) out2(fp,"my_hello",my_hello);
  if(my_ouchs>0) out2(fp,"my_ouchs",my_ouchs);
  for(i=0;i1.0        */
  *prv_dist=min(*pv_time,*prv_dist);	/* distances may be + or -           */
  *prv_dist=max(-*pv_time,*prv_dist);
  *pcv_dist=min(*pv_time,*pcv_dist);
  *pcv_dist=max(-*pv_time,*pcv_dist);
  *pop_row=*pmax_row=*pest_row=newrow;	/* update the positions		     */
  *pop_col=*pmax_col=*pest_col=newcol;
  *pop_turns=newturns;			/* update the number of turns	     */
}

int zap_wall(int row, int col) {	/* Zap a wall at position (row,col)  */
  int i;
  for(i=0;i0? 1 : -1);
  }
  else if(ccol==dcol) {
    dc=0;
    dr=(drow-crow>0? 1 : -1);
  }
  else {
    printf("bad direction in rm_wall: crow=%d, ccol=%d,   drow=%d, dcol=%d\n",
        crow,ccol, drow,dcol);
    return(-1);
  }
  while(crow>=1 && ccol<=MAXCOL && ccol>=1 && crow<=MAXROW) {
    crow+=dr;
    ccol+=dc;
    if(zap_wall(crow,ccol)>0) {			/* zapped it		*/
      return(0);
    }
  }
  return(-1);					/* found no wall to zap	*/
}

void setinst(struct Inst *pinstr, char *command, int row, int col)
{
  strncpy(pinstr->comm,command,INST_SIZE);
  pinstr->row=row;
  pinstr->col=col;
}

void printinst(struct Inst *pinstr)
{
  char buf[LINEL+1];
  printf("%s\n",inst2str(buf,pinstr));
}

static int rrc(int *prow, int *pcol) {
  char *cptr,stri[INST_SIZE+1];

  if((cptr=SOK2)==NULL) {
    printf("rrc(): illegal command\n");
    return(-1);
  }
  strcpy(stri,cptr);
  if(stri[0]=='\0') printf("bad stdin\n");
  if((int)strlen(stri)>1 || stri[0]<'A' || stri[0]>'I') {
    printf("illegal row %s in a move\n", stri);
    return(-1);
  }
  *prow=*stri-'A'+1;
  if((cptr=SOK2)==NULL) {
    printf("illegal command\n");
    return(-1);
  }
  *pcol= atoi(cptr);
  if(*pcol<=0 || *pcol>MAXCOL) {
    printf("illegal col %d in a move\n", *pcol);
    return(-1);
  }
  return(2);
}

int readinst(char *buf, struct Inst *pinstr)
{
  strncpy(pinstr->comm,SOK(buf),INST_SIZE);
  if(
    strcmp(pinstr->comm,"ZAP")==0 ||
      strcmp(pinstr->comm,"MOVE")==0 ||
      strcmp(pinstr->comm,"WALL")==0 ||
      strcmp(pinstr->comm,"INIT")==0 ||
      strcmp(pinstr->comm,"LOC")==0 ||
      strcmp(pinstr->comm,"AT")==0) {
    if(rrc(&pinstr->row,&pinstr->col)<0) {
      printf("bad move %s\n",buf);
      return(-1);
    }
  }
  else if(
      strcmp(pinstr->comm,"RADAR")==0 ||
      strcmp(pinstr->comm,"HELP")==0 ||
      strcmp(pinstr->comm,"OK")==0 ||
      strcmp(pinstr->comm,"ERROR")==0 ||
      strcmp(pinstr->comm,"OUCH")==0 ||
      strcmp(pinstr->comm,"HELLO")==0 ||
      strcmp(pinstr->comm,"OOPS")==0 ||
      strcmp(pinstr->comm,"MISS")==0 ||
      strcmp(pinstr->comm,"BOOM")==0 ||
      strcmp(pinstr->comm,"HIT")==0
      ) {
    pinstr->row=0;
    pinstr->col=0;
  }
  else {
    printf("illegal instruction, %s\n",pinstr->comm);
    return(-1);
  }
  return(0);
}

/********************/
/*   MAIN PROGRAM   */
/********************/
main(int argc, char **argv) {
  struct Inst feedback,c_move,p_move,p_feedback,n_move;
  int i,row,col,me_first;
  char *s,buf[LINEL+1],quantity[LINEL+1];
  int op_turns=0, my_turns=0, my_ouchs=0, my_hello=0;
  FILE *fp;
  int nturns;			/* opponent turns since latest radar	*/
  int delta;			/* the direction I'm going		*/
  int closecol;			/* =1 if opponent is closer to my colum	*/
				/*   than my row			*/
  int my_row, my_col;		/* my known position			*/
  int my_rowt, my_colt;		/* my target in the corner		*/
  int op_row, op_col;		/* opponent's latest known position	*/
  int op_rowt, op_colt;		/* opponent's target in the corner	*/
  float est_row, est_col;	/* estimated op's row&col position	*/
  float est_vrow, est_vcol;	/* estimated op's row&col position,	*/
				/*   based on current velocity		*/
  float est_speed;		/* estimated op's probability of moving */
  int max_row, max_col;		/* opponent's furthest possible position */
  int del_op_row, del_op_col;	/* difference between op's latest position */
				/* 	and mine			*/
  float del_est_row,del_est_col;/* estimated difference between op's position */
				/* 	and mine			*/
  int del_max_row, del_max_col;	/* max difference between op's position */
				/* 	and mine			*/
  int md;			/* minimum distance, based on op's	*/
				/*	latest known position		*/
  int nmd;			/* new minimum distance, based on op's	*/
				/*	futhest position		*/
  int my_dist;			/* distance I need to travel		*/
  int op_dist;			/* distance op needs to travel		*/
  int est_dist;			/* distance op might still need to travel */
				/*	based on estimated position	*/
  int im_confused=0;		/* indicates total confusion if ==1	*/
  int im_past_col, im_past_row;	/* 1 if I have passed op's row or col	*/
  int im_quad2;			/* quadrant you are in			*/
  int im_hunting;		/* 1 if Im_quad2,			*/
				/*   and farther from goal than op	*/
				/* 0 if opponent has farther to go than me */
  int im_desperate;		/* opponent is about to win		*/
  float rv_dist, cv_dist;	/* av. distance op moved in v_time turns */
  float v_time;			/* turns over which op's velocity is computed*/
				/* STRATEGY FACTORS			*/
  float pmovm;			/* prob. to move in "minimum" direction */
  float pmovo;			/* prob. to move in "other" direction	*/
  float prad;			/* prob. to use radar			*/
  float pzap;			/* prob. to zap in "minimum" direction	*/
  float ranprob;		/* random value, compare to prob's	*/

  /********************/
  /*   GET OPTIONS    */
  /********************/
  while(--argc>0 && (*++argv)[0] =='-') {
    for(s=argv[0]+1;*s!='\0';s++) {
      switch (*s) {
      default:
	printf("Zappa: illegal option %s\n",s);
	printf("usage: Zappa memory_file\n");
	exit(1);
      }
    }
  }
  if(argc!=1) {
    printf("incorrect argument count %d\n",argc);
    exit(-1);
  }

  /*************************/
  /*  GET STDIN FEEDBACK   */
  /*************************/
  fgets(buf, LINEL, stdin);
  if(readinst(buf,&feedback)<0)
    printf("bad input ""%s..."" in stdin\n",buf);
  c_move.comm[0]=p_move.comm[0]=p_feedback.comm[0]='\0';

  /*************************/
  /* EITHER INITIALIZE...  */
  /*************************/
  if(strcmp(feedback.comm,"INIT")==0) {
    my_hello=my_ouchs=0;
    if(feedback.row==1 && feedback.col==1) {
      me_first=1;
      my_turns=0;
      op_row=max_row=est_row=MAXROW;
      op_col=max_col=est_col=MAXCOL;
    }
    else if(feedback.row==MAXROW && feedback.col==MAXCOL) {
      my_turns=1;			/* pretend you took a null turn */
      me_first=0;
      op_row=max_row=est_row=1;
      op_col=max_col=est_col=1;
    }
    else {
      printf("bad initial row-col value %d %d\n",feedback.row,feedback.col);
      exit(1);
    }
    my_row=feedback.row;
    my_col=feedback.col;
  }
  /*************************/
  /* ...OR READ INPUT FILE */
  /*************************/
  else {
    if((fp=fopen(argv[0],"r"))==NULL) {
      printf("cannot open memory_file named %s\n",argv[0]);
      exit(-1);
    }
    while ( fgets(buf, LINEL, fp) != NULL) {
      strcpy(quantity,buf);
      SOK(quantity);
      if(strcmp(quantity,"my_pos")==0) {
	rrc(&my_row,&my_col);
      }
      else if(strcmp(quantity,"op_pos")==0) {
	rrc(&op_row,&op_col);
      }
      else if(strcmp(quantity,"max_pos")==0) {
	rrc(&max_row,&max_col);
      }
      else if(strcmp(quantity,"my_turns")==0)
	my_turns=atoi(SOK2);
      else if(strcmp(quantity,"op_turns")==0)
	op_turns=atoi(SOK2);
      else if(strcmp(quantity,"my_ouchs")==0)
	my_ouchs=atoi(SOK2);
      else if(strcmp(quantity,"my_hello")==0)
	my_hello=atoi(SOK2);
      else if(strcmp(quantity,"me_first")==0)
	me_first=atoi(SOK2);
      else if(strcmp(quantity,"rv_dist")==0)
	rv_dist=atof(SOK2);
      else if(strcmp(quantity,"cv_dist")==0)
	cv_dist=atof(SOK2);
      else if(strcmp(quantity,"v_time")==0)
	v_time=atof(SOK2);
      else if(strcmp(quantity,"wall_at")==0) {
	rrc(&row,&col);
	buildwall(row,col);
      }
      else if(strcmp(quantity,"c_move")==0) {
	readinst((char *)(buf+7),&c_move);
      }
      else if(strcmp(quantity,"p_move")==0) {
	readinst(buf+7,&p_move);
      }
      else if(strcmp(quantity,"p_feedback")==0) {
	readinst(buf+11,&p_feedback);
      }
    }
    fclose(fp);
  }
  /*******************/
  /* INITIAL SET-UP  */
  /*******************/
  if(me_first>0) {		/* I am first player			*/
    op_rowt=op_colt=1;
    delta=1;			/* my direction is 1, lower to higher,	*/
    my_rowt=MAXROW;
    my_colt=MAXCOL;
  }
  else {			/* I am second player			*/
    my_rowt=my_colt=1;
    delta=(-1);			/* my direction is -1, higher to lower	*/
    op_rowt=MAXROW;
    op_colt=MAXCOL;
  }
  /**********************/
  /*  PROCESS FEEDBACK  */
  /**********************/
  if(strcmp(feedback.comm,"INIT")==0) {			/* INIT: do nothing */
    rv_dist= -delta*(MAXROW/(float)(MAXROW+MAXCOL+1));
    cv_dist= -delta*(MAXCOL/(float)(MAXROW+MAXCOL+1));
    v_time=1.;
  }
  else if(strcmp(c_move.comm,"RADAR")==0) {
    if(strcmp(feedback.comm,"AT")==0) {
      updop(feedback.row, feedback.col, my_turns-1, &op_row, &op_col,
          &max_row, &max_col, &est_row, &est_col, &op_turns,
          &rv_dist, &cv_dist, &v_time);
    }
    else {
      printf("bad feedback for RADAR: %s\n",inst2str(buf,&feedback));
      exit(1);
    }
  }
  else if(strcmp(c_move.comm,"WALL")==0) {
    if(strcmp(feedback.comm,"OK")==0) {			/* I built a wall! */
      buildwall(c_move.row,c_move.col);
    }
    else if(strcmp(feedback.comm,"OOPS")==0) {		/* Opponent was there*/
      updop(c_move.row, c_move.col, my_turns-1, &op_row, &op_col,
          &max_row, &max_col, &est_row, &est_col, &op_turns,
          &rv_dist, &cv_dist, &v_time);
    }
    else if(strcmp(feedback.comm,"ERROR")==0) {		/* Wall not built */
      if(c_move.row<1 ||c_move.col<1 ||c_move.row>MAXROW||c_move.col>MAXCOL) {
	;
      }
      else {
	my_row=c_move.row;
	my_col=c_move.col;
      }
    }
    else {
      printf("Illegal feedback to WALL command: %s\n",feedback.comm);
      dumpout(stdout,me_first,my_row,my_col,my_turns,op_row,op_col,op_turns,
          max_row,max_col,rv_dist,cv_dist,v_time,
          my_hello, my_ouchs,nwalls,wall_r,wall_c,
          c_move,p_feedback,p_move);
      exit(1);
    }
  }
  else if(strcmp(c_move.comm,"MOVE")==0) {
    if(strcmp(feedback.comm,"OK")==0) {			/* I moved! */
      my_row=c_move.row;
      my_col=c_move.col;
    }
    else if(strcmp(feedback.comm,"OUCH")==0) {		/* I hit a wall */
      buildwall(c_move.row,c_move.col);
      my_ouchs++;
    }
    else if(strcmp(feedback.comm,"HELLO")==0) {		/* Opponent is here! */
      updop(c_move.row, c_move.col, my_turns-1, &op_row, &op_col,
          &max_row, &max_col, &est_row, &est_col, &op_turns,
          &rv_dist, &cv_dist, &v_time);
      my_hello++;
    }
    else if(strcmp(feedback.comm,"ERROR")==0) {
      i=checkmove(c_move.row,c_move.col,my_row,my_col);
      if(i==0)					/* I'm not in right place */
	im_confused=1;
    }
    else {
      printf("Illegal feedback to MOVE command: %s\n",feedback.comm);
      dumpout(stdout,me_first,my_row,my_col,my_turns,op_row,op_col,op_turns,
          max_row,max_col,rv_dist,cv_dist,v_time,
          my_hello, my_ouchs,nwalls,wall_r,wall_c,
          c_move,p_feedback,p_move);
      exit(1);
    }
  }
  else if(strcmp(c_move.comm,"ZAP")==0) {
    if(strcmp(feedback.comm,"MISS")==0) {         		/* No walls! */
      			/* remove all "stray" walls along the path */
      while(rm_wall(my_row,my_col,c_move.row,c_move.col)>=0);
      /* check if max row or column is forbidden 'cause there was no HIT*/
      			/* zap along row  */
      if(max_row==my_row && (c_move.col-my_col)*(max_col-my_col)>=0
          && (c_move.col-my_col)*(op_col-my_col)>0 ) {
	max_row+=delta;
      }
      			/* zap along column */
      if(max_col==my_col && (c_move.row-my_row)*(max_row-my_row)>=0
          && (c_move.row-my_row)*(op_row-my_row)>0 ) {
	max_col+=delta;
      }
      /* check if op_row or op_col is forbidden 'cause there was no HIT */
      			/* zap along row */
      if(op_row==my_row && (c_move.col-my_col)*(max_col-my_col)>=0
          && (c_move.col-my_col)*(op_col-my_col)>0 ) {
	op_row-=delta;
      }
      			/* zap along column */
      if(op_col==my_col && (c_move.row-my_row)*(max_row-my_row)>=0
          && (c_move.row-my_row)*(op_row-my_row)>0 ) {
	op_col-=delta;
      }
    }
    else if(strcmp(feedback.comm,"BOOM")==0) { 		/* I hit a wall */
      			/* remove the first wall along the path */
      rm_wall(my_row,my_col,c_move.row,c_move.col);
    }
    else if(strcmp(feedback.comm,"HIT")==0) {	/* Opp. is somewhere here! */
      if(c_move.row==my_row)
	op_row=est_row=max_row=c_move.row;
      else
	op_col=est_col=max_col=c_move.col;
      op_turns=my_turns;				/* set ZAP flag */
    }
    else if(strcmp(feedback.comm,"ERROR")==0) {
      i=checkmove(c_move.row,c_move.col,my_row,my_col);
      if(i==0 || i==2) 				/* I'm in the wrong place */
	im_confused=1;
    }
    else {
      printf("Illegal feedback to ZAP command: %s\n",feedback.comm);
      dumpout(stdout,me_first,my_row,my_col,my_turns,op_row,op_col,op_turns,
          max_row,max_col,rv_dist,cv_dist,v_time,
          my_hello, my_ouchs,nwalls,wall_r,wall_c,
          c_move,p_feedback,p_move);
      exit(1);
    }
  }
  else if(strcmp(c_move.comm,"HELP")==0) {
    if(strcmp(feedback.comm,"LOC")==0) {         /* Get my position */
      my_row=feedback.row;
      my_col=feedback.col;
    }
  }
  else {
    printf("illegal c_move: %s\n",c_move.comm);
    dumpout(stdout,me_first,my_row,my_col,my_turns,op_row,op_col,op_turns,
        max_row,max_col,rv_dist,cv_dist,v_time,
        my_hello, my_ouchs,nwalls,wall_r,wall_c,
        c_move,p_feedback,p_move);
    exit(1);
  }
  /*************************/
  /*  ANALYZE POSITION     */
  /*************************/
  nturns=my_turns-op_turns;
				/* estimate op's position	*/
  my_dist=abs((my_col-my_colt)+(my_row-my_rowt));
  if(my_dist==0) im_confused=1;
  op_dist=abs((op_col-op_colt)+(op_row-op_rowt));
				/* increment max_row and max_col */
  max_row=normr(max_row-(op_turnsabs(max_row-op_row))
    est_row=max_row;
  est_col=op_col-nturns*est_speed*(op_col-op_colt)/(float)op_dist;
  if(abs(est_col-op_col)>abs(max_col-op_col))
    est_col=max_col;
				/* estimate position based on cur. velocity */
  est_vrow=op_row+nturns*rv_dist/v_time;
  if(abs(est_vrow-op_row)>abs(max_row-op_row))
    est_vrow=max_row;
  est_vcol=op_col+nturns*cv_dist/v_time;
  if(abs(est_vcol-op_col)>abs(max_col-op_col))
    est_vcol=max_col;
				/* average est_pos and est_vpos		*/
  est_row=(est_row+est_vrow)/2;
  est_col=(est_col+est_vcol)/2;
				/* check for symtoms of zapping to	*/
				/* limit min_col			*/
  if((op_col-max_col)*delta==1) {
    est_col=op_col+(1./nturns)*(est_col-op_col);
  }
  if((op_row-max_row)*delta==1) {
    est_row=op_row+(1./max(1,nturns))*(est_row-op_row);
  }
  del_op_row=delta*(op_row-my_row);	/* if del_op_row>0, opponent is */
  del_op_col=delta*(op_col-my_col);	/*   positioned "ahead" of me	*/
  del_est_row=delta*(est_row-my_row);
  del_est_col=delta*(est_col-my_col);
  del_max_row=delta*(max_row-my_row);
  del_max_col=delta*(max_col-my_col);
			/* closecol=1 if op is closer to col than row */
			/* closecol depends on del_max_pos first... */
  if(del_max_col!=del_max_row && (del_max_col>0||del_max_row>0))
    closecol=(del_max_colabs(est_col-my_col) ? 1 : 0);
  md=(closecol ? max(del_est_col,del_op_col) : max(del_est_row,del_op_row));
  nmd=(closecol ? del_max_col : del_max_row);
  est_dist=max(1,round(abs((est_col-op_colt)+(est_row-op_rowt))));
  im_past_row = ((abs(est_row-my_rowt)>abs(my_row-my_rowt)) ? 1 : 0);
  im_past_col = ((abs(est_col-my_colt)>abs(my_col-my_colt)) ? 1 : 0);
  im_quad2 = ((im_past_row+im_past_col)==2 ? 1 : 0 );
  im_hunting = ((im_quad2 && my_dist>est_dist ) ? 1 : 0 );
  if (nturns>0 && (nmd<(-1) || (nmd<0 && op_dist<=2) || est_dist<=1.2))
    im_desperate =(((im_hunting && (est_dist<=2) || op_dist<=3)) ? 1 : 0);
  else im_desperate=0;
  /*********************/
  /* TABLE OF STRATEGY */
  /*********************/
  if(md>=3 && nmd>=2)  { pmovm=.2; pmovo=.8; prad=.0; pzap=.0; } /*pwall =.0*/ /* at beginning, know exact op position */
  if(md>=3 && nmd==md)   { pmovm=.0; pmovo=.1; prad=.0; pzap=.0; } /*pwall =.9*/
  if(md>=3 && nmd==md-1) { pmovm=.1; pmovo=.8; prad=.0; pzap=.0; } /*pwall =.1*/
  /* the order is important here */
  if(md>=3 && nmd==1)    { pmovm=.0; pmovo=.1; prad=.9; pzap=.0; }
  if(md>=3 && nmd==0)    { pmovm=.0; pmovo=.0; prad=.5; pzap=.5; }
  if(md>=3 && nmd <0)    { pmovm=.0; pmovo=.0; prad=1.; pzap=.0; }
  if(md==2 && nmd>=1)    { pmovm=.2; pmovo=.8; prad=.0; pzap=.0; }
  if(md==2 && nmd==0)    { pmovm=.0; pmovo=.1; prad=.1; pzap=.8; }
  if(md==2 && nmd==(-1)) { pmovm=.0; pmovo=.0; prad=.5; pzap=.5; }
  if(md==2 && nmd<=(-2)) { pmovm=.0; pmovo=.0; prad=1.; pzap=.0; }
  if(md==1 && nmd>=1)    { pmovm=.1; pmovo=.1; prad=.2; pzap=.6; }
  if(md==1 && nmd==0)    { pmovm=.0; pmovo=.3; prad=.0; pzap=.7; }
  if(md==1 && nmd==(-1)) { pmovm=.0; pmovo=.1; prad=.2; pzap=.7; }
  if(md==1 && nmd==(-2)) { pmovm=.0; pmovo=.1; prad=.7; pzap=.2; }
  if(md==1 && nmd<=(-3)) { pmovm=.0; pmovo=.0; prad=1.; pzap=.0; }
  if(md==0 && nmd==0)    { pmovm=.0; pmovo=.0; prad=.0; pzap=1.; }
  if(md==0 && nmd==(-1)) { pmovm=.3; pmovo=.0; prad=.0; pzap=.7; }
  if(md==0 && nmd==(-2)) { pmovm=.6; pmovo=.1; prad=.0; pzap=.3; }
  if(md==0 && nmd<=(-3)) { pmovm=.0; pmovo=.0; prad=.7; pzap=.3; }
  if(md==(-1) && nmd>=(-1)) { pmovm=.1; pmovo=.75; prad=.0; pzap=.15; }
  if(md==(-1) && nmd==(-2)) { pmovm=.5; pmovo=.3; prad=.0; pzap=.1; }
  if(md==(-1) && nmd<=(-3)) { pmovm=.6; pmovo=.0; prad=.4; pzap=.0; }
  if(md<=(-2) && nmd==md-1) { pmovm=.6; pmovo=.1; prad=.0; pzap=.0; } /*pwall=.3*/
  if(md<=(-2) && nmd!=md-1 && my_dist=est_dist)
    { pmovm=.6; pmovo=.0; prad=.3; pzap=.0; }
  /*************************/
  /*  FIGURE OUT STRATEGY  */
  /*************************/
  srand(11*my_turns+7*me_first+3*(int)time(NULL));
  rand();
newrand:
  ranprob=rand()/32768.;
  /*****************/
  /* HELP COMMAND  */
  /*****************/
  if(im_confused>0)
    setinst(&n_move,"HELP",0,0);
  /***********************/
  /* DESPERATE COMMANDS  */
  /***********************/
  else if(im_desperate>0) {
    if(ranprob<0.4 || op_dist<=2)
      setinst(&n_move,"WALL",op_rowt,op_colt);
    else
      setinst(&n_move,"RADAR",0,0);
  }
  /******************/
  /*  MOVE COMMAND  */
  /******************/
  else if(ranprob0)
	  				/* o dir. is illegal	*/
	  setinst(&n_move,"ZAP",m_row,m_col);	/* zap in m_direction	*/
	else setinst(&n_move,"MOVE",o_row,o_col); /* else substitue movo */
      }
      else setinst(&n_move,"MOVE",m_row,m_col);
    }
    else {				/* move along other direction */
					/* check whether movo is legal, smart */
      if(checkmove(o_row,o_col,my_row,my_col)==5) {
					/* o dir. is off board */
	if(pmovo<1.0) goto newrand;
	else setinst(&n_move,"RADAR",0,0);	/* this is a cop-out */
      }
      else if(checkmove(o_row,o_col,my_row,my_col)==1) {
					/* There's a wall	*/
					/* check whether to substitute movm */
	if(pmovm==0. || checkmove(m_row,m_col,my_row,my_col)>0)
	  				/* m dir. is illegal	*/
	  setinst(&n_move,"ZAP",o_row,o_col);	/* zap in o_direction	*/
	else setinst(&n_move,"MOVE",m_row,m_col); /* else substitiue movm */
      }
      else setinst(&n_move,"MOVE",o_row,o_col); /* normal movo		*/
    }
  }
  /*******************/
  /*  RADAR COMMAND  */
  /*******************/
  else if(ranprobnturns)
      zr=(op_row>my_row? 1 : -1);	      /* row won't reach; zap column */
    else if(abs(my_col-op_col)>nturns)
      zc=(op_col>my_col ? 1 : -1);	/* column won't reach; zap row */
    else {				/* else zap toward the opponent */
      if(closecol)
	zr=(est_row>my_row ? 1 : -1);
      else
	zc=(est_col>my_col ? 1 : -1);
    }
    setinst(&n_move,"ZAP",my_row+zr,my_col+zc);
  }
  /*******************/
  /*  WALL  COMMAND  */
  /*******************/
  else {				/* P(wall) is left over		*/
    					/* put a wall in front of the opp */
    int nr,nc,ec,er;
    er=normr(round(est_row));
    ec=normc(round(est_col));
    for(i=1;i<20;i++) {
      nr=normr(round(est_row+i*rv_dist));
      nc=normc(round(est_col+i*cv_dist));
      if(nr==er && nc==ec) continue;
      if(is_wallat(nr,nc)) continue;
      setinst(&n_move,"WALL",nr,nc);
      goto ewall;
    }
    nr=normr(round(est_row-delta));
    nc=normc(round(est_col-delta));
    setinst(&n_move,"WALL",nr,nc);
ewall:
    ;
  }

  /******************/
  /*  FINAL OUTPUT  */
  /******************/
  my_turns++;
  printinst(&n_move);
  if((fp=fopen(argv[0],"w"))==NULL) {
    printf("cannot open memory_file named %s for writing\n",argv[0]);
    exit(-1);
  }				/* save all information in a temp file	*/
  dumpout(fp,me_first,my_row,my_col,my_turns,op_row,op_col,op_turns,
      max_row,max_col,rv_dist,cv_dist,v_time,
      my_hello, my_ouchs,nwalls,wall_r,wall_c,
      n_move,feedback,c_move);	/* substitute n_move for c_move,	*/
  				/* substitute c_move for p_move		*/
  fclose(fp);
  return(0);
}