
/* https://home.hccnet.nl/h.g.muller/NEG.c */

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

#ifdef _WIN32
#include <windows.h>
#else
#include <sys/time.h>
#include <sys/times.h>
#include <unistd.h>
int GetTickCount()
{
  struct timeval t;
  gettimeofday(&t, NULL);
  return t.tv_sec * 1000 + t.tv_usec / 1000;
}
#endif

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

#define WHITE 8
#define BLACK 16
#define COLOR (WHITE|BLACK)

#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 ENGINE_NAME "Aquilon 0.0.3.1"

#ifdef CREATE_LOG
FILE* log_file;
#endif

struct t_position position1;

int Setup(char* fen)
{
  load_position_from_fen(&position1, fen);
  return (position1.active == 'w' ? WHITE : BLACK);
}

int main(void)
{
  int stm = WHITE, engineSide = 0;
  char line[256], command[20];
  int post, randomize;
  char fen[256];
  char move_str[6];
  struct t_move move;
  enum chess_variant cv = cv_undefined;
  
  strcpy(fen, STARTPOS_CLASSICAL);
  
#ifdef CREATE_LOG
  log_file = fopen("aquilon.log", "a");
#endif
  
  erase_position(&position1);
  
  srand(GetTickCount());
  
  while (1)
  {
    int i, c;
    
    if (stm == engineSide)
    {
      struct t_position_info info1;
      struct t_move moves1[256];
      int movecount1;
      info1 = get_position_info(&position1, 0);
      movecount1 = generate_legal_moves(position1, info1, moves1, sizeof(moves1) / sizeof(struct t_move), 0);
      
      LOG_LINE("DEBUG Found %d legal moves\n", movecount1)
      
      if (movecount1 > 0)
      {
        i = rand() % movecount1;
        move = moves1[i];
        do_move(move, &position1);
        if ((move.capture & CASTLING) == CASTLING && (cv == cv_normal || cv == cv_capablanca || cv == cv_undefined))
        {
          castling2str(move, move_str, sizeof(move_str), cv);
        }
        else
        {
          move2str(move, move_str, sizeof(move_str));
        }
        printf("move %s\n", move_str);
        stm ^= COLOR;
      }
    }
    
    fflush(stdout);
    
    i = 0;
    while ((line[i++] = c = getchar()) != '\n') if (c == EOF) printf("# EOF\n"), exit(1);
    line[i] = '\0';
    if (*line == '\n') continue;
    
    sscanf(line, "%s", command);
    
    LOG_LINE("DEBUG Received command [%s]\n", command)
    
    if (!strcmp(command, "usermove"))
    {
      sscanf(line, "usermove %s", move_str);
      
      if (ischessmove(move_str))
      {
        LOG_LINE("DEBUG User move [%s]\n", move_str)
        move = str2move(move_str);
        do_move(move, &position1);
        stm ^= COLOR;
      }
      else
      {
        LOG_LINE("WARN Invalid user move [%s]\n", move_str)
      }
    }
    else if (!strcmp(command, "protover")) {
      printf("feature done=0\n");
      printf("feature myname=\"" ENGINE_NAME "\"\n");
      printf("feature setboard=1 usermove=1 analyze=0 colors=0 sigint=0 sigterm=0\n");
      printf("feature variants=\"capablanca,caparandom,fischerandom,normal\"\n");
      printf("feature done=1\n");
    }
    else if (!strcmp(command, "new"))      stm = Setup(fen), randomize = 0, engineSide = BLACK;
    else if (!strcmp(command, "go"))       engineSide = stm;
    else if (!strcmp(command, "result"))   engineSide = 0;
    else if (!strcmp(command, "force"))    engineSide = 0;
    else if (!strcmp(command, "setboard")) stm = Setup(line + 9);
    else if (!strcmp(command, "random"))   randomize = !randomize;
    else if (!strcmp(command, "post"))     post = 1;
    else if (!strcmp(command, "nopost"))   post = 0;
    else if (!strcmp(command, "quit"))     break;
    else if (!strcmp(command, "variant"))
    {
      char variant_str[16];
      sscanf(line, "variant %s", variant_str);
      
      if      (!strcmp(variant_str, "capablanca"))   { cv = cv_capablanca; strcpy(fen, STARTPOS_CAPABLANCA); stm = Setup(fen); }
      else if (!strcmp(variant_str, "caparandom"))   { cv = cv_caparandom; }
      else if (!strcmp(variant_str, "fischerandom")) { cv = cv_fischerandom; }
      else if (!strcmp(variant_str, "normal"))       { cv = cv_normal; strcpy(fen, STARTPOS_CLASSICAL);  stm = Setup(fen); }
      else
      {
        LOG_LINE("WARN Unknown variant [%s]\n", variant_str)
        cv = cv_undefined;
      }
    }
    else if (
      !strcmp(command, "accepted") ||
      !strcmp(command, "rejected") ||
      !strcmp(command, "xboard")
    ) {}
    else
    {
      LOG_LINE("WARN Unknown command [%s]\n", command)
    }
  }
  
#ifdef CREATE_LOG
  fclose(log_file);
#endif
  return 0;
}
