
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <time.h>

#include "chess.h"
#include "utils.h"

#define STARTPOS_CLASSICAL "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"
#define STARTPOS_CAPABLANCA "rnabqkbcnr/pppppppppp/10/10/10/10/PPPPPPPPPP/RNABQKBCNR w KQkq - 0 1"
#define CHECK "rnb1kbnr/pppppppp/8/8/7q/8/PPPPP1PP/RNBQKBNR w KQkq - 0 1"
#define CASTLING_PATH_ATTACKED "rnbqkbnr/pppppp1p/8/8/8/8/PPPPPPpP/RNBQK2R w KQkq - 0 1"
#define CASTLING_PATH_OCCUPIED "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/R2QK1NR w KQkq - 0 1"
#define CASTLING_PATH_ATTACKED_CAPABLANCA "rnabqkbcnr/pppppppppp/10/10/5b4/10/PPP1PPP1PP/R4K3R w KQkq - 0 1"
#define PAWN_CANNOT_MOVE "4k3/8/8/8/7b/8/5P2/4K3 w - - 0 1"

/* http://www.talkchess.com/forum3/viewtopic.php?t=47318#p508880 */
#define ILLEGAL_EN_PASSANT_CAPTURE "8/5bk1/8/2Pp4/8/1K6/8/8 w - d6 0 1"
#define ILLEGAL_EN_PASSANT_CAPTURE_BLACK "8/8/1k6/8/2pP4/8/5BK1/8 b - d3 0 1"
#define EN_PASSANT_CAPTURE_CHECKS_OPPONENT "8/8/1k6/2b5/2pP4/8/5K2/8 b - d3 0 1"
#define EN_PASSANT_CAPTURE_CHECKS_OPPONENT_BLACK "8/5k2/8/2Pp4/2B5/1K6/8/8 w - d6 0 1"
#define SHORT_CASTLING_GIVES_CHECK "5k2/8/8/8/8/8/8/4K2R w K - 0 1"
#define SHORT_CASTLING_GIVES_CHECK_BLACK "4k2r/8/8/8/8/8/8/5K2 b k - 0 1"
#define LONG_CASTLING_GIVES_CHECK "3k4/8/8/8/8/8/8/R3K3 w Q - 0 1"
#define LONG_CASTLING_GIVES_CHECK_BLACK "r3k3/8/8/8/8/8/8/3K4 b q - 0 1"
#define PROMOTE_TO_GIVE_CHECK "4k3/1P6/8/8/8/8/K7/8 w - - 0 1"
#define PROMOTE_TO_GIVE_CHECK_BLACK "8/k7/8/8/8/8/1p6/4K3 b - - 0 1"
#define UNDERPROMOTE_TO_CHECK "8/P1k5/K7/8/8/8/8/8 w - - 0 1"

#define CAPABLANCA_CASTLING "rnabqkbcnr/pppppppppp/10/10/10/10/PPPPPPPPPP/R4K3R w KQkq - 0 1"

int main(int argc, char *argv[])
{
  struct t_position position;
  char fen_i[256];
  const char sample[] = STARTPOS_CLASSICAL;
  struct t_move moves[256];
  int movecount, i;
  char move_str[6];
  struct t_position_info info;
  char str[256], cmd[256];
  struct t_move move;
  
  erase_position(&position);
  
  if (argc > 1) { strcpy(fen_i, argv[1]); } else { strcpy(fen_i, sample); }
  
  load_position_from_fen(&position, fen_i);
  
  prettyprint_position(position);
  printf("\n");
  
  info = get_position_info(&position, 0);
  
  movecount = generate_legal_moves(position, info, moves, sizeof(moves) / sizeof(struct t_move), 0);
  
  for (i = 0; i < movecount; i ++)
  {
    move2str(moves[i], move_str, sizeof(move_str));
    printf("%-6s", move_str);
    if ((i + 1) % 12 == 0 || i == movecount - 1)
    {
      printf("\n");
    }
  }
  
  printf("Move %d %s > ", position.fullmove, (position.active == 'w') ? "white" : "black");
  
  while (fgets(str, 256, stdin) != NULL)
  {
    if (sscanf(str, "%s", cmd) != 1)
    {
      break;
    }
    if (ischessmove(cmd))
    {
      move = str2move(cmd);
      do_move(move, &position);
      prettyprint_position(position);
      printf("\n");
      
      info = get_position_info(&position, 0);
      print_info(info);
      printf("\n");

      movecount = generate_legal_moves(position, info, moves, sizeof(moves) / sizeof(struct t_move), 0);
      
      for (i = 0; i < movecount; i ++)
      {
        move2str(moves[i], move_str, sizeof(move_str));
        printf("%-6s", move_str);
        if ((i + 1) % 12 == 0 || i == movecount - 1)
        {
          printf("\n");
        }
      }
    }
    else
    {
      printf("invalid input\n");
    }
    
    printf("Move %d %s > ", position.fullmove, (position.active == 'w') ? "white" : "black");
  }
  
  return 0;
}
