#include "phalanx.h" int WIN=5; /* highest value for every win of this move */ int DRA=2; /* much smaller value for drawing moves */ int LOO=1; /* lowest value for losing moves */ int UNK=1; /* the result is unknown. there is often [Result "*"] in lots of PGN files */ int Asize=500000; /* default buffer size. one cell is 12 bytes. qsort() temporarily needs about twice as much memory to sort the array. */ int MaxBookPly=70; /* we want only opening to be in the book ... stop the game parsing at this ply. */ int MaxComment=4096; /* maximum size of comment in bytes. if a comment exceeds this limit, we search for another game. */ int MinValue=15; /* move bonus must be >= MinValue, otherwise the move is not added into the opening book. */ int MinPercentage=80; /* alternate moves must be at least at MinPercentage % of the value of the most valuable move */ FILE * tb1; FILE * tb2; typedef struct { unsigned hashboard; unsigned n; unsigned short move; } tb; /* 10 bytes */ tb *A; int I=0; int bsortkey( const void *a, const void *b ) { if( ((tb*)a)->hashboard > ((tb*)b)->hashboard ) return 1; else if( ((tb*)a)->hashboard < ((tb*)b)->hashboard ) return -1; else if( ((tb*)a)->move > ((tb*)b)->move ) return 1; else if( ((tb*)a)->move < ((tb*)b)->move ) return -1; else return 0; } int usortkey( const void *a, const void *b ) { if( ((tb*)a)->n < ((tb*)b)->n ) return 1; else return -1; } int games=0; int positions=0; void printit(int x) { printf("%8i%10i%7i%%", games,positions,I*100/Asize); fflush(stdout); signal(SIGALRM,printit); alarm(5); } void compress(void) { int i1, i2; printit(0); alarm(0); printf("\nsorting buffer ............ "); qsort( A, I, sizeof(tb), bsortkey ); puts("done"); printf("compressing buffer ........ "); i1=0; i2=1; while( i2 != I ) { while( i2 != I && A[i1].hashboard == A[i2].hashboard && A[i1].move == A[i2].move ) { A[i1].n += A[i2].n; i2++; } if( i2 != I ) { i1++; A[i1]=A[i2]; i2++; } } I=i1+1; A[I].n = 0; printf("done, buffer usage=%i (%i%%)\n",I,100*I/Asize); /** Now, take tb1 file and the memory buffer and join them to *** the tb2 (rbook.phalanx.tmp). Rename tb2 to tb1. **/ { int i=0; int done_m, done_f; tb mtb, ftb; printf("adding to file ............ "); tb1=fopen("rbook.phalanx","rb"); tb2=fopen("rbook.phalanx.tmp","wb"); rewind(tb1); mtb=A[0]; i=1; done_m=(i==I); myfread( &ftb, sizeof(tb), tb1 ); done_f=feof(tb1); while( !done_f || !done_m ) { if( !done_m && !done_f && bsortkey(&mtb,&ftb)==0 ) { mtb.n += ftb.n; myfwrite(&mtb,sizeof(tb),tb2); mtb=A[i]; i++; done_m=(i==I); myfread(&ftb,sizeof(tb),tb1); done_f=feof(tb1); } else if( !done_m && ( done_f || bsortkey(&mtb,&ftb)==-1 ) ) { myfwrite(&mtb,sizeof(tb),tb2); mtb=A[i]; i++; done_m=(i==I); } else if( !done_f && ( done_m || bsortkey(&mtb,&ftb)==1 ) ) { myfwrite(&ftb,sizeof(tb),tb2); myfread(&ftb,sizeof(tb),tb1); done_f=feof(tb1); } } /* good, it's there, close the two files, move newly * joined to the first one and reopen */ fclose(tb1); fclose(tb2); rename("rbook.phalanx.tmp","rbook.phalanx"); printf("done\n"); } I=0; alarm(5); } int bpoints, wpoints; int findgame(void) { register int c; register int found=0; char s[64]; bpoints=0; wpoints=0; while( ! found ) { while( (c=getchar()) != EOF && c!='R' ) {} if( c==EOF ) return 0; if( fgets(s,6,stdin)==NULL ) return 0; if( strncmp(s,"esult",5) == 0 ) { int nlns=0; while( (c=getchar()) == ' ' ) {} if( fgets(s,4,stdin)==NULL ) return 0; if( strncmp(s,"1-0",3) == 0 ) { bpoints=LOO; wpoints=WIN; } else if( strncmp(s,"0-1",3) == 0 ) { bpoints=WIN; wpoints=LOO; } else if( strncmp(s,"1/2",3) == 0 ) { bpoints=DRA; wpoints=DRA; } else { bpoints=UNK; wpoints=UNK; } /*** find two newlines in a row -> end of the header ***/ while( (c=getchar()) != EOF && nlns < 2 ) { if(c=='\n') nlns++; else nlns=0; } if(c!=EOF) return 1; } } return 0; } extern char piece[7]; extern char file[10]; extern char row[12]; int addmove(char *move) { static tmove m[256]; tmove * mf; static int n; int i; int p=PAWN+Color; for(i=2;i!=7;i++) if(piece[i]==move[0]) p=16*i+Color; if( move[0]=='O' ) { p=KING+Color; if(move[3]=='-') { if(Color==WHITE){} } } generate_legal_moves( m, &n, checktest(Color) ); if( (mf=sandex(move,m,n)) != NULL ) { if( Color==WHITE ) { if(wpoints) { A[I].hashboard=G[Counter].hashboard; A[I].move = smove(mf); A[I].n = wpoints; positions++; I++; if( I>=Asize ) compress(); } } else { if(bpoints) { A[I].hashboard=G[Counter].hashboard; A[I].move = smove(mf); A[I].n = bpoints; positions++; I++; if( I>=Asize ) compress(); } } do_move(mf); return 1; } else { return 0; } } void parsegame(void) { register int c='*'; unsigned char m[128]; int i; setfen("rnbqkbnr/pppppppp/////PPPPPPPP/RNBQKBNR/w"); while( c!='[' && c!=EOF && Counter < MaxBookPly ) { while( (c=getchar()) != '.' && c!=EOF ) if(c=='{') { int csize=0; while( (c=getchar())!='}' && c!=EOF && csize\n"); printf("Options: -b one cell is %lu bytes\n", (unsigned long) sizeof(tb) ); printf(" -p \n"); printf(" -c \n"); printf(" -v \n"); printf(" -g \n"); printf(" -w \n"); printf(" -d \n"); printf(" -l \n"); printf(" -u \n"); exit(0); } int bcreate( int argc, char ** argv ) { FILE * f; int c; while( (c=getopt(argc,argv,"b:p:c:v:g:w:d:l:u:")) != -1 ) switch(c) { case 'b': if( sscanf( optarg, "%i", &Asize ) == 0 ) wusage(); if( Asize < 1000 ) wusage(); break; case 'p': if( sscanf( optarg, "%i", &MaxBookPly ) == 0 ) wusage(); if( MaxBookPly < 2 ) wusage(); break; case 'c': if( sscanf( optarg, "%i", &MaxComment ) == 0 ) wusage(); if( MaxComment < 2 ) wusage(); break; case 'v': if( sscanf( optarg, "%i", &MinValue ) == 0 ) wusage(); if( MinValue < 0 ) wusage(); break; case 'g': if( sscanf( optarg, "%i", &MinPercentage ) == 0 ) wusage(); if( MinPercentage < 50 || MinPercentage > 100 ) wusage(); break; case 'w': if( sscanf( optarg, "%i", &WIN ) == 0 ) wusage(); if( WIN < 1 || WIN > 10 ) wusage(); break; case 'd': if( sscanf( optarg, "%i", &DRA ) == 0 ) wusage(); if( DRA < 0 || DRA > 10 ) wusage(); break; case 'l': if( sscanf( optarg, "%i", &LOO ) == 0 ) wusage(); if( LOO < 0 || LOO > 10 ) wusage(); break; case 'u': if( sscanf( optarg, "%i", &UNK ) == 0 ) wusage(); if( UNK < 0 || UNK > 10 ) wusage(); break; default: wusage(); } A=malloc(Asize*sizeof(tb)); if( A == NULL ) { printf("cannot alloc %lu bytes of memory\n", (unsigned long)(Asize*sizeof(tb))); exit(0); } { struct stat fs; if( ! stat("rbook.phalanx",&fs) ) { puts("rbook.phalanx exists, skipping stage 1"); goto stage_2; } else { tb1 = fopen("rbook.phalanx", "w+"); } } setvbuf(stdout, (char*)NULL, _IONBF, 0); puts( "creating opening book"); puts( "-----------------------------"); puts( " games positions buffer%"); puts( "-----------------------------"); signal(SIGALRM,printit); alarm(5); while( findgame() ) { parsegame(); games++; } printf("end of file, parsed %i positions in %i games\n",positions,games); if( games == 0 ) { puts("opening book not created"); return 0; } compress(); alarm(0); stage_2:; if( ( f = fopen( SBOOK_FILE, "wb" ) ) == NULL ) { printf("cannot create book file %s\n", SBOOK_FILE); return 1; } { int dots=0; struct stat fs; int fsize; tb M; tb1=fopen("rbook.phalanx","rb"); myfread( &M, sizeof(tb), tb1 ); stat("rbook.phalanx",&fs); fsize = fs.st_size/sizeof(tb); printf("writing book "); while(!feof(tb1)) { int i; int minn; A[0]=M; I=0; do { int fpos=ftell(tb1)/sizeof(tb); if( fpos % (fsize/30) == 1 ) { if( dots==3 ) { printf("%i%%", (int)(((float)fpos)*100/fsize + 1) ); dots=0; } else printf("."); dots++; } I++; myfread( A+I, sizeof(tb), tb1 ); } while( !feof(tb1) && M.hashboard==A[I].hashboard ); M=A[I]; /* sort them, better first */ qsort( A, I, sizeof(tb), usortkey ); /* more variability in frequently played lines of early openings */ { unsigned i=100, j=10, p=MinPercentage; while( A[0].n > i && p>10 ) { p-=j; j--; i*=10; } minn=A[0].n*p/100; } if( minn > A[0].n ) minn = A[0].n; if( minn < MinValue ) minn=MinValue; for( i=0; i!=I && A[i].n>=minn; i++ ) {} /* printf("got %i of %i moves at hasboard of %08X, next HB %08X\n", i, I, A[0].hashboard, M.hashboard ); */ I=i; for(i=0;i!=I;i++) { unsigned short m = A[i].move; myfwrite( A+i, sizeof(unsigned), f ); myfwrite( &m, sizeof(unsigned short), f ); } } printf(" done\n"); } return 0; }