# include "robots.h"

/*
 * user.c: user oriented things
 */

command()  /* whats the user trying to tell us */
{
retry:
  if (all_moves && wimpy) good_moves();
  move(my_y,my_x);
  refresh();
  if(last_stand) return;
  bad_move = FALSE;
  switch(cmd_ch=read_com()) {
  case '.':
  case 'h':
  case 'j':
  case 'k':
  case 'l':
  case 'y':
  case 'u':
  case 'b':
  case 'n':
  case 'w':
    do_move(cmd_ch);
    break;
  case 't':
  case 'r':
  case 'T':
  case 'R':
  teleport:
    new_x = rndx();
    new_y = rndy();
    move(new_y,new_x);
    switch(inch()) {
    case FROBOT:
    case ROBOT:
    case SCRAP:
    case ME:
      goto teleport;
    }
    if( (free_teleports > 0)
       && ((cmd_ch == 't')||(cmd_ch =='T')) ) {
      if( !isgood(new_y, new_x))
        goto teleport;
      free_teleports--;
    }
    break;
  case 's':
  case 'S':
  case 'W':
    last_stand = TRUE;
    leaveok(stdscr,TRUE);
    return;
  case 'M':
    all_moves = !all_moves;
    goto retry;
  case 'm':
  case '?':
    if (wimpy) good_moves();
    else mvprintw(LINES-1,MSGPOS,"Be a stud!");
    goto retry;
  case 'd':
  case 'D':
    if(dots < 2) {
      dots++;
      put_dots();
    } else {
      erase_dots();
      dots = 0;
    }
    goto retry;
  case 'q':
  case 'Q':
    quit(FALSE);
  case 'a':
  case 'A':  /* Antimatter - sonic screwdriver */
    if (free_teleports) { new_x = my_x;
          new_y = my_y;
          screwdriver();
        }
    else goto retry;
    break;
  case ctrl('R'):
    clearok(curscr,TRUE);
    wrefresh(curscr);
    goto retry;
  default:
    bad_move = TRUE;
  }
  if(bad_move) {
    putchar(BEL);
    refresh();
    count = 0;
    adjacent=FALSE;
    waiting=FALSE;
    first_move=FALSE;
    goto retry;
  }
  first_move = FALSE;
  if(dots) erase_dots();
  mvaddch(my_y,my_x,' ');
  my_x = new_x;
  my_y = new_y;
  move(my_y,my_x);
  if((inch() == ROBOT)||(inch() == FROBOT)) dead=TRUE;
  else {
    if(dots) put_dots();
    mvaddch(my_y,my_x,ME);
    refresh();
  }
}

read_com()
{
  static int     com;

  if(count == 0) {
    if(isdigit(com = readchar())) {
      count = com-'0';
      while(isdigit(com = readchar()))
        count = count*10+com-'0';
    }
    else { /* rfs -- eliminate possible infinite loop when running */
      switch (com) {
	case ctrl('W'):
	  /* com |= 0040; */
	  waiting=TRUE;
	case ctrl('H'):
	case ctrl('J'):
	case ctrl('K'):
	case ctrl('L'):
	case ctrl('Y'):
	case ctrl('U'):
	case ctrl('B'):
	case ctrl('N'):
	  com |= 0100;
	  adjacent = TRUE;
	  first_move=TRUE;
      }
      switch (com) {
	case 'H':
	case 'L':
	  count = WIDTH;
	  com |= 0040;
	  first_move=TRUE;
	  break;
	case 'J':
	case 'K':
	  count = HEIGHT;
	  com |= 0040;
	  first_move=TRUE;
	  break;
	case 'Y':
	case 'U':
	case 'N':
	case 'B':
        case 'W':
	  { /* set count to the least common multiple of WIDTH and HEIGHT */
	    int w=WIDTH, h=HEIGHT,t;
	    while (w>h) {
	      t=w-h;
	      if (t<h) { w=h; h=t; }
	      else w=t;
	      }
	    count=(WIDTH/w)*HEIGHT;
	  }
	  com |= 0040;
	  first_move=TRUE;
	  break;
	default:
	  count=0;
	  break;
	}
    }
  }
  if(count > 0) count--;
  return(com);
}

do_move(dir)  /* implement the users move */
  char dir;
{
  register int x, y;
  new_x = hbound(my_y+yinc(dir),my_x+xinc(dir));
  new_y = vbound(my_y+yinc(dir),my_x+xinc(dir));
  if(adjacent && !first_move) {
    for(x = -2; x <= 2; x++) {
      for(y = -2; y <= 2; y++) {
        tmove(new_y+y ,new_x+x);
        switch(inch()) {
        case SCRAP:
          if( waiting )
            break;
        case ROBOT:
          if(abs(x) < 2 && abs(y) < 2) {
            bad_move = TRUE;
            return;
          }
          else break;
        case FROBOT:
          if (waiting &&
            blocked(new_y, new_x, y, x) )
            break;
          bad_move = TRUE;
          return;
        }
      }
    }
  }
  move(new_y,new_x); /* already bounded */
  switch(inch()) {
  case SCRAP:
    if(moveable_heaps && move_heap(dir)) break;
    else {
      bad_move = TRUE;
      return;
    }
  case VERT:
    if (hsew||hrev) break; 
    else {
      bad_move = TRUE;
      return;
    }
  case HORIZ:
    if (vsew||vrev) break;
    else {
      bad_move = TRUE;
      return;
    }
  }
}

move_heap(dir)  /* push a scrap heap */
char  dir;
{
  register int  x, y;

  x = hbound(new_y + yinc(dir),new_x + xinc(dir));
  y = vbound(new_y + yinc(dir),new_x + xinc(dir));
  move(y, x);
  switch(inch()) {
    case VERT:
    case HORIZ:
    case SCRAP:
    case ROBOT:
    case FROBOT:
      return FALSE;
  }
  addch(SCRAP);
  mvaddch(new_y,new_x,' ');
  return TRUE;
}
