/*
 * Copyright 1996 by Michel D. Grimminck
 *
 * All Rights Reserved
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose and without fee is hereby granted,
 * provided that the above copyright notice appear in all copies and that
 * both that copyright notice and this permission notice appear in
 * supporting documentation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 */

#include <stdio.h>
#include "functions.h"
#include "var.h"

#define maxmoves 140  /* maximal number of moves */

int randomgame(int games,  /* number of games to play */
               int depth1, /* player 1 search depth */
               int eval1,  /* player 1 evaluation type */
               int depth2, /* player 2 search depth */
               int eval2,  /* player 2 evaluation type */
               int learn)  /* use games to learn */
{
    int g,r,i,color=white,n,movenr=0;
    int score,currentscore;
    char local[52];
    int test=white;
    int win=0,lose=0,draw=0;
    int gamelength=0,depth;
    FILE *corr;

    corr=fopen("corr","a");
    g=0; /* the number of accepted games played so far */
    while (g<games) {
        init_board();
        color=white;
        for(i=0;i<10;i++) {
            n=move_list(0,color);
            do_move(movelist[0][rand()%n]);
            color^=1;
            }
        for (movenr=10;movenr<maxmoves;movenr++) {
            if (games==1) display_board();
            score=0;
            n=move_list(0,color);
            if (n==1) {do_move(movelist[0][0]);}
            else if (n==0) break;
            else if (n!=100) {
	      if ((pieces[white|man]+pieces[black|man]+pieces[white|crown]+pieces[black|crown])==6) {
		init_stats();
		display_board();
		do_pn_search(color,2000,WINTHEO,2);
	      }
                init_stats();
                init_hash();
	      
                currentscore=alfabeta(-INF,INF,color,0,depth-200,0);
                if (color==test) {
                    depth=depth1;
                    eval_type=eval1;
                    }
                else {
                    depth=depth2;
                    eval_type=eval2;
                    }
                score=alfabeta(-INF,INF,color,0,depth,0);
                printf("%.3f  ",score/1000.0F); print_pv();
                if (quiet(color)==true && color==white) {
                    int p;
                    fprintf(corr,"%i %i ",score,currentscore);
                    
                    fprintf(corr,"\n");
                    }
                if (score<-1700 || score>1700) break;
                do_move(PV[0][0]);
                if (theoretic(color)==DRAW) {score=0; break;}
                }
            color^=1;
            }
        if ((score<-500 || score>500) && movenr>14) {
            /* score for white */
            if (color==black) score-=score;
            printf("game:%i color:%i score:%i\n",g,color,score);
            display_board();
            test^=1; g++;
            gamelength+=movenr;
            }
        if (movenr>=maxmoves) draw++;
        }
    printf("testee win:%i  lose:%i  draw:%i  av.gamelength:%.1f\n",win,lose,draw,(float) gamelength/games);
    eval_type=NORMAL;
    fclose(corr);
    return(0);
}

int predict_move(int color, int level,char *move)
{
    int score,nmoves;

    nmoves=move_list(0,color);
    if (nmoves==0) {printf("no moves\n"); return(false);}
    if (nmoves==1) return(true);
    init_stats();
    init_hash();
    set_eval();
    score=alfabeta(-INF,INF,color,0,level-400,0);
    score=alfabeta(-INF,INF,color,0,level-200,0);
    score=alfabeta(-INF,INF,color,0,level,0);
    if (movecmp(PV[0][0],move)==0) return(true);
    return(false);
}

void best_fit(void)
{
   int i,bestscore=-100000,best,score,j;
   char local[50];

   for(i=0;i<50;i++) local[i]=board[map[i]];

   for(i=0;i<ref_nr;i++) {
     score=0;
     for(j=0;j<50;j++) if (local[j]!=ref_board[i][j]) score--;
     if (score>bestscore) {bestscore=score; best=i;}
   }
   printf("best:%i  score:%i  move:",best,bestscore);
   print_move(ref_move[best]); printf("\n");
   for(j=0;j<50;j++) board[map[j]]=ref_board[best][j];
   display_board();
}

int read_comment(FILE *in,char *comment)
{
    int i,bracket;
    char u;

    do {
        u=fgetc(in);
    } while(u<=32);
    if (u!='{') {
        ungetc(u,in);
        return(0);
    }
    i=0;
    bracket=1;
    do {
        u=fgetc(in);
        if (u=='{') bracket++;
        if (u=='}') bracket--;
        if (bracket==0) break;
        if (i<128) comment[i++]=u;
    } while(true);
    comment[i]=0;
    return(i);
}

int check_database(char *file,int min,int max)
{
    FILE *in;
    char field[2048];
    int c,i,n,col,correct=0,try=0;
    char move[32],comment[128];
    int total,count=0,games=0,playmove;
    float q=0;

    in=my_fopen(file,"r");
    if (in==NULL) {printf("error opening database\n"); return(0);}

    do {

        playmove=0;
        col=2;
        /* read leader */
        if (feof(in)) break;
        do {
            n=fgetc(in);
            if (n<0) goto endread;
            if (n=='[') {
                ungetc(n,in);
                fgets(field,2048,in);
                /*printf("%s",field);*/
                }
            } while (n!='1');
        ungetc(n,in);
        init_board();
        init_stats();

        do {
            c=read_comment(in,comment);
            /*if (c!=0) printf("comment:'%s'\n",comment);*/
            n=fscanf(in,"%s",field);
            if (strcmp(field,"1-0")==0 || strcmp(field,"0-1")==0 || strcmp(field,"1/2-1/2")==0 || strcmp(field,"*")==0 ) {
	      if (parameters[0]==-5) {
		display_board();
		printf("tomove:%i %s\n",col,field);
		}
	      if (parameters[0]==-6) {
		int score1,score2,score3,score4,score5,score6;
		if (col==2) col=white;
		display_board();
		init_hash(); init_stats();
		set_eval();
		score1=alfabeta(-INF,INF,col,0,0,0);
		score2=alfabeta(-INF,INF,col,0,200,0);
		score3=alfabeta(-INF,INF,col,0,400,0);
		score4=alfabeta(-INF,INF,col,0,800,0);
		score5=alfabeta(-INF,INF,col,0,1000,0);
		score6=alfabeta(-INF,INF,col,0,1200,0);
		if (col==black) {
		  score1=-score1;
		  score2=-score2;
		  score3=-score3;
		  score4=-score4;
		  score5=-score5;
		  score6=-score6;
		}
		printf("tomove:%i result:%s score:%i %i %i %i %i %i\n",col,field,score1,score2,score3,score4,score5,score6);
		}
	      break;
	    }
            if (col!=2) {
                c=strlen(field);
                if (field[c-1]=='-' || field[c-1]=='x') {
                    n=fscanf(in,"%s",&field[c]);
                }

                n=text_to_move(field,col,move);
                if (n==false) {
                    printf("errornous move:'%s'\n",field);
                    return(-1);
                    }

                total=pieces[white|man]+pieces[white|crown]+
                      pieces[black|man]+pieces[black|crown];
                if (total>=min && total<=max) q-=perc;
                if (total>=min && total<=max && q<=0) {
                    count++;q+=1.0F;
                    if (parameters[0]>0) {
                        try++;
                        if (try%25==0) {printf(".");fflush(stdout);}
                        if (predict_move(col,parameters[0],move)==true) correct++;
                        }
                    if (parameters[0]==-2) {
                      for(i=0;i<50;i++) ref_board[count][i]=board[map[i]];
                      movecopy(ref_move[count],move);
                      }
                    if (parameters[0]==-3 && playmove<20) {
                      add_book_entry(col,0);
                    }
                    if (parameters[0]==-4) store_history(move,0,0);
		    if (parameters[0]==-7 && quiet(col)==true && pieces[white|man]>2 && pieces[white|crown]==0 && pieces[black|man]>2 && pieces[black|crown]==0) {
                      BTYPE temp[93];
		      int nr1,nr2,nmoves1,nmoves2;
		      nmoves1=move_list(MAXPLY-2,col);
		      for(nr1=0;nr1<nmoves1;nr1++) {
			do_move(movelist[MAXPLY-2][nr1]);
			nmoves2=move_list(MAXPLY-1,col^1);
			for(nr2=0;nr2<nmoves2;nr2++) {
			  do_move(movelist[MAXPLY-1][nr2]);
			  copy_board(temp,board);
			  plearn(col,800);
			  copy_board(board,temp);
			  undo_move(movelist[MAXPLY-1][nr2]);
			}
			undo_move(movelist[MAXPLY-2][nr1]);
		      }
		    }
		    if (parameters[0]==-1) {display_board();print_move(move); printf("\n");}
		    
		    playmove++;
		  }
		do_move(move);
	      }
            col=(col+1)%3;
            } while (n>0);
            if (parameters[0]==-1) printf("\n");
            games++;
        } while(!feof(in));
    endread:
    fclose(in);
    /*if (parameters[0]>0) {
        printf("\ncorrect predictions:%i out %i\n",correct,try);
        }*/
    if (parameters[0]==0) printf("total count in range:%i\n, %i games",count,games);
    ref_nr=count;
    if (parameters[0]==-3) book_info();
    if (parameters[0]==-4) return(count);
    return(correct);
}
