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

#include "chess.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"

int main(int argc, char *argv[])
{
  char fen[256];
#ifdef CAPABLANCA
  const char sample[] = STARTPOS_CAPABLANCA;
#else
  const char sample[] = STARTPOS_CLASSICAL;
#endif
  struct t_position position1;
  struct t_position_info info1;
  struct t_move moves1[256];
  int movecount1;
  
  struct t_position position2;
  struct t_position_info info2;
  struct t_move moves2[256];
  int movecount2;
  
  struct t_position position3;
  struct t_position_info info3;
  struct t_move moves3[256];
  int movecount3;
  
  struct t_position position4;
  struct t_position_info info4;
  struct t_move moves4[256];
  int movecount4;
  
  struct t_position position5;
  struct t_position_info info5;
  struct t_move moves5[256];
  int movecount5;
  
  int perft1, perft2, perft3, perft4, perft5;
  int i1, i2, i3, i4;
  
  /*
  char move_str[6];
  */
  
  erase_position(&position1);
  
  if (argc > 1) { strcpy(fen, argv[1]); } else { strcpy(fen, sample); }
  
  load_position_from_fen(&position1, fen);

  prettyprint_position(position1);
  printf("\n");
  
  clock_t begin = clock();
  
  info1 = get_position_info(&position1, 0);
  
  print_info(info1);
  printf("\n");
  
  movecount1 = generate_legal_moves(position1, info1, moves1, sizeof(moves1) / sizeof(struct t_move), 0);
  
  perft1 = movecount1;
  perft2 = 0;
  perft3 = 0;
  perft4 = 0;
  perft5 = 0;
  
  for (i1 = 0; i1 < movecount1; i1 ++)
  {
    /*
    move2str(moves1[i1], move_str, sizeof(move_str));
    printf("%s\n", move_str);
    */
    
    position2 = position1;
    do_move(moves1[i1], &position2);
    info2 = get_position_info(&position2, 0);
    movecount2 = generate_legal_moves(position2, info2, moves2, sizeof(moves2) / sizeof(struct t_move), 0);
    perft2 += movecount2;
    
    for (i2 = 0; i2 < movecount2; i2 ++)
    {
      position3 = position2;
      do_move(moves2[i2], &position3);
      info3 = get_position_info(&position3, 0);
      movecount3 = generate_legal_moves(position3, info3, moves3, sizeof(moves3) / sizeof(struct t_move), 0);
      perft3 += movecount3;
      
      for (i3 = 0; i3 < movecount3; i3 ++)
      {
        position4 = position3;
        do_move(moves3[i3], &position4);
        info4 = get_position_info(&position4, 0);
        movecount4 = generate_legal_moves(position4, info4, moves4, sizeof(moves4) / sizeof(struct t_move), 0);
        perft4 += movecount4;
        
        for (i4 = 0; i4 < movecount4; i4 ++)
        {
          position5 = position4;
          do_move(moves4[i4], &position5);
          info5 = get_position_info(&position5, 0);
          movecount5 = generate_legal_moves(position5, info5, moves5, sizeof(moves5) / sizeof(struct t_move), 0);
          perft5 += movecount5;
        }
      }
    }
  }
  
  clock_t end = clock();
  double time_spent = (double)(end - begin);
  
#ifdef CAPABLANCA
  printf("perft(1) = %8d (%d)\n", perft1, perft1 ==       28);
  printf("perft(2) = %8d (%d)\n", perft2, perft2 ==      784);
  printf("perft(3) = %8d (%d)\n", perft3, perft3 ==    25228);
  printf("perft(4) = %8d (%d)\n", perft4, perft4 ==   805128);
  printf("perft(5) = %8d (%d)\n", perft5, perft5 == 28741319);
  /* http://www.eglebbk.dds.nl/program/chess-perft.html */
#else
  printf("perft(1) = %7d (%d)\n", perft1, perft1 ==      20);
  printf("perft(2) = %7d (%d)\n", perft2, perft2 ==     400);
  printf("perft(3) = %7d (%d)\n", perft3, perft3 ==    8902);
  printf("perft(4) = %7d (%d)\n", perft4, perft4 ==  197281);
  printf("perft(5) = %7d (%d)\n", perft5, perft5 == 4865609);
#endif
  printf("\n");
  printf("%.3f s\n", time_spent / CLOCKS_PER_SEC);
  
  return 0;
}
