#include "stdafx.h"
#include 
#include 
#include 
#include 
#include 

#include 
//using namespace std;
#include 

#include "globals.h"
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>

#include <iostream>
//using namespace std;

#include <sys timeb.h>

#include "globals.h"

bool ftime_ok = false;  /* does ftime return milliseconds? */
//
void xboard();

//diagram stuff
int LoadDiagrams(char* file);
int LoadDiagram(char* file,int);
int GetSquare(char file,char rank);
int GetPiece(char b);

int pos[100][3][16][3];
int startpos[100];
int diag_number;

int ponder;

FILE *diagram_file;
char fen_name[256];
//

int uci_mode = 0;

int flip = 0;

int number=0;

int games = 0;
int white_wins = 0;
int black_wins = 0;
int draws = 0;
int game_total = 0;
int autoplay = 0;

int computer_side;
int player[2];

int fixed_time;
int fixed_depth;
int max_time;
int start_time;
int stop_time;
int max_depth;
int deep;
int turn = 0;

void print_result();
void NewGame();

void SetMaterial();

int get_ms()
{
	struct timeb timebuffer;
	ftime(&timebuffer);
	if (timebuffer.millitm != 0)
		ftime_ok = true;
	return (timebuffer.time * 1000) + timebuffer.millitm;
}

char *move_str(int start,int dest,int bits,int promote)
{
	static char str[6];

	char c;

	if (bits & 32) {
		switch (promote) {
			case N:
				c = 'n';
				break;
			case B:
				c = 'b';
				break;
			case R:
				c = 'r';
				break;
			default:
				c = 'q';
				break;
		}
		sprintf_s(str, "%c%d%c%d%c",
				col[start] + 'a',
				row[start] + 1,
				col[dest] + 'a',
				row[dest] + 1,
				c);
	}
	else
		sprintf_s(str, "%c%d%c%d",
				col[start] + 'a',
				row[start] + 1,
				col[dest] + 'a',
				row[dest] + 1);
	return str;
}

int main2()
{
	char s[256];
    char sFen[256];//
	char sText[256];//
	int m;
    int total=0;
    float turns=0;
    int editmode=0;
    int analyze=0;
    int np=0;
int edit_color=0;
int sq=0;
double nps;
fixed_time = 0;
int t;

	printf("\n");
	printf("Bills bare bones chess engine\n");
	printf("version 1.0, 23/7/15\n");
	printf("Copyright 2015 Bill Jordan \n");
	printf("\n");
	printf("\"help\" displays a list of commands.\n");
	printf("\n");

    RandomizeHash();
    FreeAllHash();
	SetTables();
	SetMoves();
	init_board();
    //SetBook(1);
	//??open_book();
	
	Gen();
	computer_side = EMPTY;
	player[0] =0;
	player[1] = 0;
	max_time = 1 << 25;
	max_depth = 4;

	for (;;)
    {
    diag_number=0;
		if (side == computer_side) 
		{  /* computer's turn */
		player[side] = 1;
        {
//			if(6000 - (get_ms() - start_time) <100)
 // max_depth = 1;//
			if(autoplay==0)
			think(1);
			else
			think(0);
			printf("Think finished!\n");
   int deep = 1;//
   total += deep;
   //if(deep>0)
     turns++;
   //
   currentkey = GetKey();
   currentlock = GetLock();
int a=0;
int zero=0;
int lookup = LookUp(side);
if(lookup != 0)
{
   printf("\n lookup %d ",lookup);
   Alg(hash_start,hash_dest);printf("\n");
   autoplay = 0;//
}
 else
	 printf("n o look\n");
 //Alg(hash_start,hash_dest);
            //
if(autoplay==1 && max_depth>4)
{
	print_board();
}
if(autoplay==0)
{
printf("\n hash %d ",hashpositions[0]);
printf(" hash %d ",hashpositions[1]);
printf(" collisions %d ",collisions);
}
printf("\n");
collisions = 0;

//if(turns>0)
//  printf("\n average depth is %d ",total/turns);
}

			if (root_start==0 && root_dest==0) {
				printf("(no legal moves)\n");
				computer_side = EMPTY;
				print_board();
				ShowAll(ply);
				Gen();
				continue;
			}
		    printf("Computer's move: %s\n", move_str(root_start,root_dest,0,0));printf("\n");

			SetMaterial();
			Gen();
			
	 for(int x=0;x0)
      nps = (double)nodes / (double)t;
    else
      nps=0;
	nps *= 1000.0;

	printf("\nNodes per second: %d (Score: %.3f)\n", (int)nps, (float)nps/243169.0);
			}
	//*/
            //if(analyze==0)
            //makemove(pv[0][0]);
			ply = 0;

			first_move[0] = 0;//11/12/12
			Gen();
			print_result();
			if(games>=game_total && game_total>0)
			{
				printf("%d",games); printf(" games \\ %d ",game_total); 
				printf(" 1-0 "); printf("%d \n",white_wins);
				printf(" 0-1 "); printf("%d \n",black_wins);
				printf(" 1/2 "); printf("%d \n",draws);
				games = 0;
				game_total = 0;
				white_wins = 0;
				black_wins = 0;
				draws = 0;
				autoplay = 0;
			}
            printf(" turn "); printf("%d",turn++);
			if(autoplay==0)
              print_board();
            if(analyze==1)
				goto out;
			continue;
		}
	out:
		/* get user input */
		if (autoplay==0)
		  printf("Cheese> ");
		if (autoplay==1)
		{
		  computer_side = side;
		  continue;
		}
		if (autoplay==0 && scanf("%s", s) == EOF)
			//if (autoplay==0 && scanf_s("%s", s) == EOF)
			return 0;
	if (!strcmp(s, "quit"))
    {
			printf("Bye Bye\n");
			break;
	}
	if (!strcmp(s, "go"))
       {
		computer_side = side;
		continue;
	   }
		//
       if (!strcmp(s, "a") || !strcmp(s, "analyze"))
        {
          analyze=1;
          printf("starting analysis mode\n");
		  continue;
		}
		if (!strcmp(s, "exit"))
        {
          analyze=0;
          printf("ending analysis mode\n");
          continue;
        }
        if (!strcmp(s, "edit"))
        {
          editmode=1;
          printf("edit");
          continue;
        }
   if (!strcmp(s, "#"))
        {
          editmode=1;
for(int x=0;x<64;x++)
{
board[x]=EMPTY;
color[x]=EMPTY;
}
//SetBook(0);
          printf("#\n");
          continue;
        }
//if(editmode==1)
if (!strcmp(s, "Nc5"))
{
 switch(s[0])
  {
  case 'P': np=0;break;
  case 'N': np=1;break;
  case 'B': np=2;break;
  case 'R': np=3;break;
  case 'Q': np=4;break;
  case 'K': np=5;break;
  case 'c':edit_color=1;break;
  default:break;
  }
  sq= s[1]-96-1 + (s[2]-48-1)*8;
if(sq>-1 && sq<64 && np>-1 && np<6)
{
  if(np==5) kingloc[edit_color]=sq;
  board[sq]=np;
  color[sq]=edit_color;
}
continue;
}
        if (!strcmp(s, "."))
        {
          editmode=0;
          continue;
        }
   if (!strcmp(s, "sb")) 
   {
            //SetBook(0);
			sFen[0] = 0;
			strcat_s(sFen,"c:\\bscp\\");//
            scanf("%s", sText);
			strcat_s(sFen,sText);//
            strcat_s(sFen,".fen");
			LoadDiagram(sFen,1);
			continue;
		}
  if (!strcmp(s, "zz")) 
  {
         autoplay = 1;
		 player[0] = 1;
		 player[1] = 1;
			continue;
		}
   if (!strcmp(s, "gg")) 
   {
            scanf("%d", &game_total);
			games = 0;
			white_wins = 0;
			black_wins = 0;
			draws = 0;
			continue;
		}
		if (!strcmp(s, "on") || !strcmp(s, "p")) {
			computer_side = side;
			continue;
		}
		if (!strcmp(s, "off")) {
			computer_side = EMPTY;
			continue;
		}
        if (!strcmp(s, "random")) {
			continue;
		}
		if (!strcmp(s, "st")) {
			scanf("%d", &max_time);
			max_time *= 1000;
			max_depth = MAX_PLY;
			fixed_time = 1;
			continue;
		}
		if (!strcmp(s, "sd")) {
			scanf("%d", &max_depth);
			max_time = 1 << 25;
			fixed_depth = 1;//
			continue;
		}
		if (!strcmp(s, "undo")) {
			if (!hply)
				continue;
			computer_side = EMPTY;
			TakeBack();
			ply = 0;
	if(first_move[0] != 0)
      first_move[0] = 0;
			Gen();
			continue;
		}
		if (!strcmp(s, "new")) 
		{
			NewGame();
			computer_side = EMPTY;
			continue;
		}
		if (!strcmp(s, "d")) {
			print_board();
			printf("\n key %d ",currentkey);
			printf("\n lock %d ",currentlock);
			continue;
		}
        if (!strcmp(s, "f")) {
			flip = 1 - flip;
            print_board();
			continue;
		}
        if (!strcmp(s, "book") || !strcmp(s, "bk")) {
	        //SetBook(0);
			continue;
		}
        if (!strcmp(s, "nb")) {
	        //SetBook(0);
			continue;
		}
        if (!strcmp(s, "sw")) {
	        side = 1-side;
            xside = 1-xside;
			continue;
		}
        if (!strcmp(s, "moves")) {     //wj
			printf("Moves ??\n");
            move *g;
            for (int i = 0; i < first_move[1]; ++i)
            {
            g = &move_list[i];
            printf("%s",move_str(move_list[i].start,move_list[i].dest,0,move_list[i].promote));
            printf("\n");
            }
			continue;
		}
		 if (!strcmp(s, "sb")) {
            //SetBook(0);
			sFen[0] = 0;
			strcat_s(sFen,"c:\\bscp\\");//
            scanf("%s", sText);
			strcat_s(sFen,sText);//
            strcat_s(sFen,".fen");
			LoadDiagram(sFen,1);
			continue;
		}
		if (!strcmp(s, "bye")) {
			printf("Share and enjoy!\n");
			break;
		}
		if (!strcmp(s, "xboard")) {
			xboard();
			break;
		}
		if (!strcmp(s, "help")) {
			printf("a - toggle analysis mode\n");
			printf("on - computer plays for the side dest move\n");
			printf("off - computer stops playing\n");
			printf("st n - search for n seconds per move\n");
			printf("sd n - search n ply per move\n");
			printf("undo - takes back a move\n");
			printf("new - starts a new game\n");
			printf("d - display the board\n");
            printf("f - flip board\n");
            printf("book - turns on openong book\n");
            printf("nb - turns off opening book\n");
			printf("nd - next diagram\n");
			printf("np - load diagram\n eg. np 101 (For fen files which contain multiple diagrams)");
			printf("v - test eval\n");
            printf("sb - set board fen diagram\n eg. sb lasker (for lasker.fen)");
            printf("sw - switch sides\n");
			printf("bye - exit the program\n");
			printf("Enter moves in coordinate notation, e.g., e2e4, e7e8Q\n");
			continue;
		}

		/* maybe the user entered a move? */
		ply = 0;
  	if(first_move[0] != 0)
      first_move[0] = 0;
		Gen();
 		m = parse_move(s);
		if (m == -1 || !MakeMove(move_list[m].start,move_list[m].dest))
		{
			printf("Illegal move. \n");
			printf(s);printf(" \n");
			move_str(move_list[m].start,move_list[m].dest,0,move_list[m].promote);
			if (m == -1)printf(" m = -1 \n");
		}
		//
		if(game_list[hply-1].start_piece == P && (row[move_list[m].dest]==0 || row[move_list[m].dest]==7))
		{
			RemovePiece(xside,Q,move_list[m].dest);
			if(s[4]=='n' || s[4]=='N')
				AddPiece(xside,N,move_list[m].dest);
			else if(s[4]=='b' || s[4]=='B')
				AddPiece(xside,B,move_list[m].dest);
			else if(s[4]=='r' || s[4]=='r')
				AddPiece(xside,R,move_list[m].dest); 
			else AddPiece(xside,Q,move_list[m].dest);
		}
		//
	}
    Free();
	return 0;
}


/* parse the move s (in coordinate notation) and return the move's
   indx in move_list, or -1 if the move is illegal */

int parse_move(char *s)
{
	int start, dest, i;

	/* make sure the string looks like a move */
	if (s[0] < 'a' || s[0] > 'h' ||
			s[1] < '0' || s[1] > '9' ||
			s[2] < 'a' || s[2] > 'h' ||
			s[3] < '0' || s[3] > '9')
		return -1;

    start = s[0] - 'a';
    start += ((s[1] - '0') - 1)*8;
    dest = s[2] - 'a';
    dest += ((s[3] - '0') - 1)*8;

	for (i = 0; i < first_move[1]; ++i)
		if (move_list[i].start == start && move_list[i].dest == dest)
        {
			return i;
	    }
	/* didn't find the move */
	return -1;
}
/* print_board() prints the board */

void print_board()
{
	int flip = 0;
	int i, x=0;

	printf("\n8 ");
    if(flip==0)
    {
	for (int j = 0; j < 64; ++j)
    {
        i = Flip[j];
        //for(int y=0;y<2;y++)
        {
    	switch (color[i])
        {
			case EMPTY:
                if(x==0)
				printf(" .");
                else
                printf(". ");
				break;
			case 0:
            if(x==0)
				printf(" %c", piece_char[board[i]]);
                else
                printf("%c ", piece_char[board[i]]);
				break;
			case 1:
            if(x==0)
				printf(" %c", piece_char[board[i]] + ('a' - 'A'));
                else
                printf("%c ", piece_char[board[i]] + ('a' - 'A'));
				break;
			default:
				if(x==0)
				printf(" %d.",color[i]);
                else
                printf(".%d ",color[i]);
				break;
		}
		if((color[i]==0 || color[i]==1) && board[i]==6)
	if(x==0)
				printf(" %d",color[i]);
                else
                printf("%d ",color[i]);
		if(board[i]<0 || board[i]>6)
	if(x==0)
				printf(" %d.",board[i]);
                else
                printf("%d ",board[i]);
        }
		if ((j + 1) % 8 == 0 && j != 63)
			printf("\n%d ", row[i]);
	}
	printf("\n\n   a b c d e f g h\n\n");
    }
 
     if(flip==1)
    {
 	for (int j = 0; j < 64; ++j) {
        i = 63-Flip[j];
		switch (color[i]) {
			case EMPTY:
				printf(" .");
				break;
			case 0:
				printf(" %c", piece_char[board[i]]);
				break;
			case 1:
				printf(" %c", piece_char[board[i]] + ('a' - 'A'));
				break;
		}
		if ((j + 1) % 8 == 0 && row[i] != 7)
			printf("\n%d ",  row[j]+2);//7-
	}
	printf("\n\n   h g f e d c b a\n\n");
    }
}

/* xboard() is a substitute for main() that is XBoard
   and WinBoard compatible. See the following page for details:
   http://www.research.digital.com/SRC/personal/mann/xboard/engine-intf.html */

void xboard()
{
	int computer_side;
	char line[256], command[256];
	int m;
	int post = 0;
	int analyze = 0;

	signal(SIGINT, SIG_IGN);
	printf("\n");
	NewGame();
	fixed_time = 0;
	computer_side = EMPTY;
    
	for (;;) {
		fflush(stdout);
		if (side == computer_side) {

			think(post);
			SetMaterial();
			Gen();
			currentkey = GetKey();
			currentlock = GetLock();
			
	 		move_list[0].start = root_start;
            move_list[0].dest = root_dest;
      
			printf("move %s\n", move_str(root_start,root_dest,0,0));
			//
			if(analyze==0)//
				MakeMove(root_start,root_dest);
			else goto out;
  
			ply = 0;
			Gen();
			print_result();
			continue;
		}
		out:
		if (!fgets(line, 256, stdin))
			return;
		if (line[0] == '\n')
			continue;
		sscanf(line, "%s", command);
		if (!strcmp(command, "xboard"))
			continue;
		if (!strcmp(command, "new")) {
			NewGame();
			computer_side = 1;
			continue;
		}
		if (!strcmp(command, "quit"))
			return;
		if (!strcmp(command, "force")) {
			computer_side = EMPTY;
			continue;
		}
		//
		if (!strcmp(command, "analyze"))
        {
          analyze=1;
          printf("starting analysis mode\n");
		  continue;
		}
		if (!strcmp(command, "exit"))
        {
          analyze=0;
          printf("ending analysis mode\n");
          continue;
        }
	//
		if (!strcmp(command, "white")) {
			side = 0;
			xside = 1;
			Gen();
			computer_side = 1;
			continue;
		}
		if (!strcmp(command, "black")) {
			side = 1;
			xside = 0;
			Gen();
			computer_side = 0;
			continue;
		}
		if (!strcmp(command, "st")) {
			sscanf(line, "st %d", &max_time);
			max_time *= 1000;
			max_depth = MAX_PLY;
			fixed_time = 1;
			continue;
		}
		if (!strcmp(command, "sd")) {
			sscanf(line, "sd %d", &max_depth);
			max_time = 1 << 25;
			continue;
		}
		if (!strcmp(command, "time")) {
			sscanf(line, "time %d", &max_time);
			if(max_time < 200)
			  max_depth = 1;
			else
			{
			max_time *= 10;
			max_time /= 20;//30 28/4/13
			max_depth = MAX_PLY;
			}
            //printf(" max time %d \n",max_time);//
			continue;
		}
		if (!strcmp(command, "otim")) {
			continue;
		}
		if (!strcmp(command, "go")) {
			computer_side = side;
			continue;
		}
		if (!strcmp(command, "random")) {
			continue;
		}
		if (!strcmp(command, "level")) {
			continue;
		}
		if (!strcmp(command, "hard")) {
			continue;
		}
		if (!strcmp(command, "easy")) {
			continue;
		}
		if (!strcmp(command, "hint")) {
			think(0);
			if(root_start==0 && root_dest==0)
				continue;
			printf("Hint: %s\n", move_str(root_start,root_dest,0,0));
			continue;
		}
		if (!strcmp(command, "undo")) {
			if (!hply)
				continue;
			TakeBack();
			ply = 0;
			Gen();
			continue;
		}
		if (!strcmp(command, "remove")) {
			if (hply < 2)
				continue;
			TakeBack();
			TakeBack();
			ply = 0;
			Gen();
			continue;
		}
		if (!strcmp(command, "post")) {
			post = 2;
			continue;
		}
		if (!strcmp(command, "nopost")) {
			post = 0;
			continue;
		}
		first_move[0] = 0;
		Gen();

		m = parse_move(line);
		if (m == -1 || !MakeMove(move_list[m].start,move_list[m].dest))
			printf("Error (unknown command): %s\n", command);
		else 
		{
			ply = 0;
 			Gen();
			print_result();
		}
	}
}

void NewGame()
{
	init_board();
    first_move[0] = 0;
	turn = 0;
	fifty = 0;
	ply = 0;
	hply = 0;
	Gen();
}

int GetComputerSide(int& s)
{
	return player[s];
}

void print_result()
{
	int i;
    int flag=0;//
	/* is there a legal move? */
	SetMaterial();
	Gen();//
	for (i = 0; i < first_move[1]; ++i)
		if (MakeMove(move_list[i].start,move_list[i].dest))
        {
			TakeBack();
            flag=1;
			break;
		}

    if(pawn_mat[0]==0 && pawn_mat[1]==0 && piece_mat[0]<=300 && piece_mat[1]<=300)
    {
if(autoplay==1 && game_total==0)
{
	print_board();
	autoplay = 0;
}
	  games++;
	  draws++;
      printf("1/2-1/2 {Stalemate1}\n");
	  NewGame();
	  computer_side = EMPTY;
	  return;
    }
	if (i == first_move[1] && flag==0)
    {
		if(autoplay==1 && game_total==0)
		{
		print_board();
		autoplay = 0;
		}
    //
		Gen();
       printf(" end of game ");
	 
    //
		if (Attack(xside,kingloc[side]))
        {
			if (side == 0)
			{
				printf("0-1 {Black mates}\n");
				games++;
	            black_wins++;
			}
			else
			{
				printf("1-0 {White mates}\n");
				games++;
	            white_wins++;
			}
		}
		else
		{
			printf("1/2-1/2 {Stalemate}\n");
			games++;
	        draws++;
		}
		NewGame();
		computer_side = EMPTY;
	}
	else if (reps() >= 3)
	{
		if(autoplay==1 && game_total==0)
		{
			print_board();
	    autoplay = 0;
		}
		printf("1/2-1/2 {Draw by repetition}\n");
		games++;
	    draws++;
		NewGame();
		computer_side = EMPTY;
	}
	else if (fifty >= 100)
	{
if(autoplay==1 && game_total==0)
{
	print_board();
	autoplay = 0;
}
		printf("1/2-1/2 {Draw by fifty move rule}\n");
		fifty = 0;
		games++;
	    draws++;
		NewGame();
		computer_side = EMPTY;
	}
	if(turn>300)
	{
if(autoplay==1 && game_total==0)
{
	print_board();
	autoplay = 0;
}
		printf("1/2-1/2 {>300 moves}\n");
		games++;
	    draws++;
		NewGame();
		computer_side = EMPTY;
		return;
	}
}

void SetMaterial()
{
pawn_mat[0]=0;
pawn_mat[1]=0;
piece_mat[0]=0;
piece_mat[1]=0;
for(int x=0;x<64;x++)
{
	if(board[x]<6)
	{
		if(board[x]==5)
			kingloc[color[x]] = x;
		if(board[x]==0)
			pawn_mat[color[x]] += 100;
		else
			piece_mat[color[x]] += piece_value[board[x]];
	}
}
}

int reps()
{
	int r = 0;

	for (int i = hply - 1; i >= hply-fifty; i-=2)
		if (game_list[i].hash == currentkey && game_list[i].lock == currentlock)
			++r;
	return r;
}

void CloseDiagram()
{
if (diagram_file)
    fclose(diagram_file);
diagram_file = NULL;
}

int LoadDiagrams(char* file)
{
memset(pos,0,sizeof(pos));
	diagram_file = fopen(file, "r");
	if (!diagram_file)
    {
		printf("Diagram missing.\n");
        return -1;
    }
return 0;
}

int LoadDiagram(char* file,int num)
{
int x,n=0;
static int count=1;
char ts[200];

diagram_file = fopen(file, "r");
if (!diagram_file)
{
  printf("Diagram missing.\n");
  return -1;
}

strcpy_s(fen_name,file);

for(x=0;x='0' && ts[c]<='8')
    i += ts[c]-48;
if(ts[c]=='\\')
    continue;
j = Flip[i];

switch(ts[c])
{
case 'K': board[j]=K; color[j]=0;i++;
kingloc[0]=j;break;
case 'Q': board[j]=Q;color[j]=0;i++;break;
case 'R': board[j]=R; color[j]=0;i++;break;
case 'B': board[j]=B; color[j]=0;i++;break;
case 'N': board[j]=N; color[j]=0;i++;break;
case 'P': board[j]=P; color[j]=0;i++;break;
case 'k': board[j]=K; color[j]=1;i++;

		  kingloc[1]=j;break;
case 'q': board[j]=Q;color[j]=1;i++;break;
case 'r': board[j]=R; color[j]=1;i++;break;
case 'b': board[j]=B; color[j]=1;i++;break;
case 'n': board[j]=N; color[j]=1;i++;break;
case 'p': board[j]=P; color[j]=1;i++;break;
}
c++;
if(ts[c]==' ')
  break;
if(i>63)
  break;
}
if(ts[c]==' ' && ts[c+2]==' ')
{
if(ts[c+1]=='w')
{
side=0;xside=1;
}
if(ts[c+1]=='b')
{
side=1;xside=0;
}
}

game_list[0].castle_q[0] = 0;
game_list[0].castle_q[1] = 0;
game_list[0].castle_k[0] = 0;
game_list[0].castle_k[1] = 0;

while(ts[c])
{
switch(ts[c])
{
case '-': break;
case 'K':if(board[E1]==5 && color[E1]==0) game_list[0].castle_q[0] = 1;break;
case 'Q':if(board[E1]==5 && color[E1]==0) game_list[0].castle_q[1] = 1;break;
case 'k':if(board[E8]==5 && color[E8]==1) game_list[0].castle_k[0] = 1;break;
case 'q':if(board[E8]==5 && color[E8]==1) game_list[0].castle_k[1] = 1;break;
default:break;
}
c++;
}

CloseDiagram();
print_board();
NewPosition();
Gen();
printf(" diagram # %d \n",num+count);
count++;
if(side==0)
  printf("White to move\n");
else
  printf("Black to move\n");
printf(" %s \n",ts);
return 0;
}