#if defined(SDLFUNCS) || defined(DOS)

int clippy_accept_resign(void);
int clippy_accept_draw(void);
void clippy_recommend_move(void);
void show_move_list(void);
void undo_openings(void);

void undo_move(void)
{
  if(turn_count <= 3) return;

  turn_count--;
  game_status->last_moves.index--;
  memcpy(&board, &game_status->last_moves.position[game_status->last_moves.index-1].board, sizeof(struct board));
  game_status->turn--;
  undo_openings();
}

void redo_move(void)
{
  if(max_turn == turn_count) return;

  turn_count++;
  memcpy(&board, &game_status->last_moves.position[game_status->last_moves.index].board, sizeof(struct board));
  game_status->last_moves.index++;
  game_status->turn++;
  undo_openings();
}

struct screen_coord tile_coords(signed char row, signed char col);
void reset_aimv(struct coord king_pos, struct aimvstruct *state);
unsigned calc_legal_moves(struct coord *king_pos, struct board *brd);

void rate_one_ai_move(struct aimvstruct *aimvstate)
{
  signed char s;
  struct move m;
  struct piece_all_moves *piece_moves;
  struct coord king_pos;

  if(aimvstate->moves_rated == aimvstate->total_moves)
  {
    if(aimvstate->phase)
    {
      if(aimvstate->onemv)
      {
#ifdef DEBUG
        printf("My best next move: %c%u-%c%u\n", 'a'+aimvstate->max.coords.src.col, 8-aimvstate->max.coords.src.row, 
             'a' + aimvstate->max.coords.dst.col, 8-aimvstate->max.coords.dst.row);
#endif
        aimvstate->onemv = 0;
      }
      return;
    }
    aimvstate->nextpos = board;
    aimvstate->board = &aimvstate->nextpos;
    aimvstate->phase++;
    move_piece(aimvstate->board, aimvstate->max.coords.src, aimvstate->max.coords.dst);
#ifdef DEBUG
    printf("Opponent's best move: %c%u-%c%u\n", 'a'+aimvstate->max.coords.src.col, 8-aimvstate->max.coords.src.row, 
           'a' + aimvstate->max.coords.dst.col, 8-aimvstate->max.coords.dst.row);
#endif
    king_pos = find_king(aimvstate->board, !game_status->turn);
    aimvstate->total_moves = calc_legal_moves(&king_pos, aimvstate->board);
    aimvstate->bestval_limit2 = aimvstate->moves_rated = aimvstate->pc_coords.col = aimvstate->pc_coords.row = 0;
    memset(&aimvstate->max, 0, sizeof(aimvstate->max));
    memset(&aimvstate->max_nostale, 0, sizeof(aimvstate->max_nostale));
    aimvstate->max.score = aimvstate->max_nostale.score = INT32_MIN;
//    return;
  }
  aimvstate->onemv = 1;

#ifdef DEBUG
//  printf("%u %u ", aimvstate->pc_coords.row, aimvstate->pc_coords.col);
#endif

  aimvstate->max.interrupted = 0;
  m = do_ai_move(aimvstate->board, find_king(aimvstate->board, (game_status->turn^aimvstate->phase)&1), &s, aimvstate);
  if(m.interrupted) return;

#ifdef DEBUG
  printf("%u %u ", (aimvstate->move-1)->coords.src.row, (aimvstate->move-1)->coords.src.col);
  printf("%li\n", (signed long)(aimvstate->move-1)->score);
#endif

  if(!aimvstate->move_count)
    if(++aimvstate->pc_coords.col == 8)
    {
      aimvstate->pc_coords.col = 0;
      aimvstate->pc_coords.row++;
    }
}

int select_tile(struct coord *legal_moves, unsigned char legal_move_count, struct coord *selcoords, struct coord *selpiece, struct aimvstruct *aimvstate)
{
#ifdef SDLFUNCS
  SDL_Scancode i;
#endif
#ifdef DOS
  int i;
#endif
  static char old_row = 7;
  static char old_col = 7;
  struct screen_coord tlcoords;
  struct screen_coord pccoords;
  struct screen_coord spccoords;
  unsigned char piece;
  int rc;

  selcoords->row = old_row;
  selcoords->col = old_col;

  redraw:draw_board(&board, legal_moves, legal_move_count, selcoords, selpiece);
  store_clippyspr();

  if(setup.deep_thinking && aimvstate && !aimvstate->phase)
  {
    reset_aimv(find_king(&board, game_status->turn), aimvstate);
  }

  while(1)
  {
    print_timectrl(0);

    tlcoords = tile_coords(selcoords->row, selcoords->col);
    get_scrarea(tlcoords.x, tlcoords.y, 24, 24, pc_background);
    draw_rectangle(tlcoords.x+2, tlcoords.y+2, 20, 20, 0x99);
    piece = piece_in_tile(&board, selcoords->row, selcoords->col);
    if(piece)
    {
      pccoords = piece_coords(selcoords->row, selcoords->col, piece);
      push_scrbitmap(pccoords.x, pccoords.y, piece_bitmap(piece), 1);
    }
    if(selpiece)
    {
      piece = piece_in_tile(&board, selpiece->row, selpiece->col);
      spccoords = piece_coords(selcoords->row, selcoords->col, piece);
      push_scrbitmap(spccoords.x, spccoords.y, piece_bitmap(piece), 0);
    }
    tlcoords = tile_coords(selcoords->row, selcoords->col);
    if(setup.enable_clippy)
      draw_clipeyes(230, 90, -3+(tlcoords.y/24), -2 + ((tlcoords.x/24) >> 2));
    draw_screen_sprites();

    update_screenr(tlcoords.x, tlcoords.y, 24, 24, 1);
    if(setup.enable_clippy)
      update_screenr(220, 113, 40, 17, 0);
    update_screenr(220, 36, 80, 10, 0);
    update_screenr(220, 76, 80, 10, 0);

    set_scrarea(tlcoords.x, tlcoords.y, 24, 24, pc_background);
    restore_clippyspr();

    i = poll_keypress();
    if(playeroutoftime())
      return 2;

    if(setup.deep_thinking && aimvstate)
    {
      rate_one_ai_move(aimvstate);
    }


    if(i == SCANCODE_UNKNOWN) continue;

    if(i == KEY_ENTER) break;

    update_screenr(tlcoords.x, tlcoords.y, 24, 24, 0);

    switch (i)
    {
      case KEY_UP:
        if(setup.board_rotation == 0) { up:if(selcoords->row) --selcoords->row; }
        else if(setup.board_rotation == 1) goto left;
        else if(setup.board_rotation == 2) goto down;
        else goto right;
        break;
      case KEY_DOWN:
        if(setup.board_rotation == 0) { down:if(selcoords->row < 7) ++selcoords->row; }
        else if(setup.board_rotation == 1) goto right;
        else if(setup.board_rotation == 2) goto up;
        else goto left;
        break;
      case KEY_LEFT:
        if(setup.board_rotation == 0) { left:if(selcoords->col) --selcoords->col; }
        else if(setup.board_rotation == 1) goto down;
        else if(setup.board_rotation == 2) goto right;
        else goto up;
        break;
      case KEY_RIGHT:
        if(setup.board_rotation == 0) { right:if(selcoords->col < 7) ++selcoords->col; }
        else if(setup.board_rotation == 1) goto up;
        else if(setup.board_rotation == 2) goto left;
        else goto down;
        break;
      case KEY_F7:
        clippy_recommend_move();
        goto redraw;
      case KEY_F8:
        if(clippy_accept_resign()) return 1;
        goto redraw;
      case KEY_F9:
        if(clippy_accept_draw()) return 1;
        goto redraw;
      case KEY_F5:
        show_move_list();
        goto redraw;
      case KEY_F11:
        if(!selpiece)
        {
          undo_move();
          resetaimv:reset_aimv(find_king(&board, game_status->turn), aimvstate);
        }
        goto redraw;
      case KEY_F12:
        if(!selpiece)
          redo_move();
        goto resetaimv;
      case KEY_ESC:
        if(!legal_moves) return 1;
        if(rc = show_menu(mainmenu))
          if(rc == 1) return 1;
          else if(rc == 2) goto resetaimv;
        if(prevgameloaded) return 1;
        goto redraw;
    }
  }

  old_col = selcoords->col;
  old_row = selcoords->row;

  return 0;
}
#endif

void init_board(struct board *brd)
{
  memset(brd, 0, sizeof(struct board));
  brd->tiles[0][0] = PC_ROOK | PC_BLACK;
  brd->tiles[0][1] = PC_KNIGHT | PC_BLACK;
  brd->tiles[0][2] = PC_BISHOP | PC_BLACK;
  brd->tiles[0][3] = PC_QUEEN | PC_BLACK;
  brd->tiles[0][4] = PC_KING | PC_BLACK;
  brd->tiles[0][5] = PC_BISHOP | PC_BLACK;
  brd->tiles[0][6] = PC_KNIGHT | PC_BLACK;
  brd->tiles[0][7] = PC_ROOK | PC_BLACK;
  memset(brd->tiles[1], PC_PAWN_UNMOVED | PC_BLACK, 8);

  memset(brd->tiles[6], PC_PAWN_UNMOVED | PC_WHITE, 8);
  brd->tiles[7][0] = PC_ROOK | PC_WHITE;
  brd->tiles[7][1] = PC_KNIGHT | PC_WHITE;
  brd->tiles[7][2] = PC_BISHOP | PC_WHITE;
  brd->tiles[7][3] = PC_QUEEN | PC_WHITE;
  brd->tiles[7][4] = PC_KING | PC_WHITE;
  brd->tiles[7][5] = PC_BISHOP | PC_WHITE;
  brd->tiles[7][6] = PC_KNIGHT | PC_WHITE;
  brd->tiles[7][7] = PC_ROOK | PC_WHITE;

}

struct screen_coord tile_coords(signed char row, signed char col)
{
  struct screen_coord retval;

  if(setup.board_rotation == 0)
  {
    retval.x = 8+col*24;
    retval.y = row*24;
  }
  else if(setup.board_rotation == 1)
  {
    retval.x = 8+(7-row)*24;
    retval.y = 8+col*24;
  }
  else if(setup.board_rotation == 2)
  {
    retval.x = (7-col)*24;
    retval.y = 8+(7-row)*24;
  }
  else
  {
    retval.x = row*24;
    retval.y = (7-col)*24;
  }

  return retval;
}

struct screen_coord piece_coords(unsigned char row, unsigned char col, unsigned char piece)
{
  struct screen_coord retval = tile_coords(row, col);

  retval.x += 2;
  retval.y += (((piece & 7) < PC_ROOK) ? 2 : 1);

  return retval;
}

void coord_to_str(struct coord coord, char *str);

struct movecoords str_to_move(char *str, unsigned char turn)
{
  struct movecoords retval;

  if(!strncmp(str, "0-0", 3))
  {
    if(!turn)
      retval.src.row = retval.dst.row = 7;
    else
      retval.src.row = retval.dst.row = 0;
    retval.src.col = 4;
    if(!strcmp(str, "0-0-0"))
    {
      retval.dst.col = 2;
    }
    else
    {
      retval.dst.col = 6;
    }
  }
  else
  {
    retval.src.col = str[0]-'a';
    retval.src.row = 7-(str[1]-'1');
    retval.dst.col = str[3]-'a';
    retval.dst.row = 7-(str[4]-'1');
  }

  return retval;
}

char *move_to_str(unsigned char move_id)
{
  struct lastmove *move;
  struct coord src;
  struct coord dst;
  unsigned char piece;
  unsigned char old_piece;
  unsigned char ascend;
  unsigned char n;
  static char str[16];

  if((signed)move_id < 0 || move_id > turn_count-1)
  {
    memset(str, 0, sizeof(str));
    return str;
  }

  move = &game_status->last_moves.lastmoves[move_id];
  src = move->coords.src;
  dst = move->coords.dst;
  piece = piece_in_tile(&game_status->last_moves.position[move_id].board,
                                      dst.row, dst.col) & 0x7;
  if(move_id)
  {
    old_piece = piece_in_tile(&game_status->last_moves.position[move_id-1].board,
                                      src.row, src.col) & 0x7;
    if(old_piece == PC_PAWN_MOVED && old_piece != piece)
      ascend = piece;
    else goto noascend;
  }
  else noascend:ascend = 0;

  sprintf(str, "%u.  ", (2+move_id)>>1);

  if(piece == PC_KING)
  {
    if(dst.col - src.col == 2)
    {
      strcpy(str+4, "0-0");
      n = 7;
    }
    else if(src.col - dst.col == 2)
    {
      strcpy(str+4, "0-0-0");
      n = 9;
    }
    else goto nospmove;
  }
  else
  {
    nospmove:
    coord_to_str(src, str+4);
    str[6] = '-';
    coord_to_str(dst, str+7);
    n = 9;
  }

  if(ascend)
  {
    if(ascend == PC_ROOK)
      str[n] = 'R';
    else if(ascend == PC_BISHOP)
      str[n] = 'B';
    else if(ascend == PC_KNIGHT)
      str[n] = 'N';
    else if(ascend == PC_QUEEN)
      str[n] = 'Q';
    n++;
  }

  if(move->chk & 1)
    str[n++] = '+';
  if(move->chk == 3)
    str[n++] = '+';
  else if(move->chk > 1)
    str[n++] = '=';

  str[n] = 0;

  return str;
}

#if defined(SDLFUNCS) || defined(DOS)

void show_move_list(void)
{
  unsigned char s = 0;
  unsigned r, n;
  int k;

  do
  {
    fill_screen(0x01);

    for(n=s,r=10;n<turn_count-1;n+=2,r+=10)
    {
      print_text(10, r, 0xFF, move_to_str(n));
      if(n+1 != turn_count-1)
        print_text(10+12*9, r, 0xFF, move_to_str(n+1)+4);
      if(r >= 190)
       break;
    }

    update_screen();
    k = poll_keypress();
    if(k == KEY_DOWN)
      s+=2;
    else if(k == KEY_UP)
      if(s >= 2) s-=2;
  }
  while(k != KEY_ESC);
}

#endif


void draw_board(struct board *brd, struct coord *legal_moves, unsigned char legal_move_count, struct coord *seltile,
                struct coord *selpiece)
{
//  unsigned char row, col;
  char chr;
  unsigned char piece;
  struct coord brd_coords;
#if defined(SDLFUNCS) || defined(DOS)
  struct screen_coord px_coords;
  struct screen_coord sel_coords;
  unsigned char n;
  struct coord *ptr;

  if(graphics)
  {
    fill_screen(0x01);
    for(brd_coords.col=0;brd_coords.col<8;brd_coords.col++)
    {
      px_coords = tile_coords(8, brd_coords.col);
      if(setup.board_rotation < 2) px_coords.x += 16;
      else px_coords.y += 16;
      draw_chr(px_coords.x, px_coords.y, 0x7F, 'A' + brd_coords.col);
    }
    for(brd_coords.row=0;brd_coords.row<8;brd_coords.row++)
    {
      px_coords = tile_coords(brd_coords.row, -1);
      if(setup.board_rotation < 2) px_coords.y += 16;
      else px_coords.x -= 16;
      draw_chr(px_coords.x+16, px_coords.y, 0x7F, '1' + (7-brd_coords.row));

      for(brd_coords.col=0;brd_coords.col<8;brd_coords.col++)
      {
        px_coords = tile_coords(brd_coords.row, brd_coords.col);
        draw_rectangle(px_coords.x, px_coords.y, 24, 24, (brd_coords.row & 1) ^ (brd_coords.col & 1) ? 0x67 : 0xFF);
        if(legal_move_count && setup.show_legal_moves
           && move_in_list(legal_moves, legal_move_count, &brd_coords))
          draw_rectangle(px_coords.x+3, px_coords.y+3, 18, 18, 0x22);
      }
    }
    for(ptr=threat_list,n=threat_count;n--;ptr++)
    {
      px_coords = tile_coords(ptr->row, ptr->col);
      draw_rectangle(px_coords.x+3, px_coords.y+2, 18, 20, 0x44);
    }

    draw_rectangle(202, 4, 115, 85, 0xFE);
    push_scrbitmap(205, 6, &clipupil, 0);
    push_scrbitmap(308, 6, &clipupil, 0);
    print_text(220, 6, 0x80, "- Black -");
    print_text(205, 16, 0x80, move_to_str((turn_count-5)|1));
    print_text(205, 26, 0x80, move_to_str((turn_count-3)|1));

    print_text(220, 46, 0x80, "- White -");
    print_text(205, 56, 0x80, move_to_str((turn_count-4)&((unsigned char)~1)));
    print_text(205, 66, 0x80, move_to_str((turn_count-2)&((unsigned char)~1)));

    print_timectrl(0);
  }
#endif

  if(!graphics)
  {
    for(brd_coords.col=0;brd_coords.col<8;brd_coords.col++)
      printf("  %c  ", 'a' + brd_coords.col);
    printf("\n");
  }
  for(brd_coords.row=0;brd_coords.row<8;brd_coords.row++)
  {
    if(!graphics) printf("%c ", '8' - brd_coords.row);
    for(brd_coords.col=0;brd_coords.col<8;brd_coords.col++)
    {
      if(selpiece && selpiece->row == brd_coords.row && selpiece->col == brd_coords.col)
        continue;
      piece = piece_in_tile(brd, brd_coords.row, brd_coords.col);
#if defined(SDLFUNCS) || defined(DOS)
      if(graphics)
      {
        if(piece)
        {
          px_coords = piece_coords(brd_coords.row, brd_coords.col, piece);
          push_scrbitmap(px_coords.x, px_coords.y, piece_bitmap(piece), 0);
        }
      }
#endif
      if(!graphics)
      {
        switch(piece & 0x7)
        {
          case 0:
            chr = ' ';
            break;
          case PC_PAWN_UNMOVED: case PC_PAWN_MOVED:
            chr = 'P';
            break;
          case PC_ROOK:
            chr = 'R';
            break;
          case PC_KNIGHT:
            chr = 'H';
            break;
          case PC_BISHOP:
            chr = 'B';
          break;
          case PC_QUEEN:
            chr = 'Q';
            break;
          case PC_KING:
            chr = 'K';
            break;
        }
        if(piece & PC_BLACK)
          chr += 0x20;

        if((seltile && (seltile->row == brd_coords.row && seltile->col == brd_coords.col))
           || (legal_move_count && move_in_list(legal_moves, legal_move_count, &brd_coords)))
        {
          printf("[[%c]]", chr);
        }
        else if((brd_coords.row & 1) ^ (brd_coords.col & 1))
          printf("[ %c ]", chr);
        else printf("] %c [", chr);
      }
    }
    if(!graphics)
      printf("\n");
  }
#if defined(SDLFUNCS) || defined(DOS)
  if(graphics)
  {
    if(selpiece)
    {
      sel_coords = tile_coords(selpiece->row, selpiece->col);
      draw_clippy(230, 90, -3+sel_coords.y/24, -2 + ((sel_coords.x/24) >> 2));
    }
    else
      draw_clippy(230, 90, 0, -1);
    draw_screen_sprites();
    update_screen();
  }
#endif

}
