From ad2265d4fc54fc9ba99fc606e6174df34bfb4a0f Mon Sep 17 00:00:00 2001 From: H.G. Muller Date: Thu, 9 Jun 2011 09:46:39 +0200 Subject: [PATCH] version 1.4w10UCIb18 --- ChangeLog | 2 + README | 64 ++++++- book_make.cpp | 590 +++++++++++++++++++++++++++++++++++++++++++++++++++++--- book_make.h | 2 + config.h | 6 +- configure | 20 +- configure.ac | 2 +- engine.cpp | 2 +- main.cpp | 36 +++-- option.cpp | 2 +- parse.cpp | 2 +- polyglot.man | 64 ++++++- polyglot.pod | 77 +++++++- polyglot.spec | 2 +- uci2uci.cpp | 4 +- util.h | 4 + xboard2uci.cpp | 4 +- 17 files changed, 813 insertions(+), 70 deletions(-) diff --git a/ChangeLog b/ChangeLog index ab9261c..ca28e59 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,5 @@ +=========1.4w10UCIb18=========== +- Two new utilities: info-book and dump-book. =========1.4w10UCIb17=========== - More refactoring. main.cpp is now #ifdef _WIN32 free. - The main loop (previously in adapter.cpp) is now in its own file mainloop.cpp. diff --git a/README b/README index fa7080c..6322277 100644 --- a/README +++ b/README @@ -5,7 +5,8 @@ POLYGLOT(6) POLYGLOT(6) NAME PolyGlot - Winboard protocol to UCI protocol adapter - book engine for Polyglot books - - a collection of utilities for creating opening books + - a collection of utilities for creating and analyzing open- + ing books - a utility for analyzing epd files - a perft counter @@ -20,6 +21,10 @@ SYNOPSIS polyglot merge-book -in1 inputfile1 -in2 inputfile2 [-out outputfile] + polyglot info-book [-bin inputfile] [-exact] + + polyglot dumb-book [-bin inputfile] -color color [-out outputfile] + polyglot [configfile] epd-test [-epd inputfile] [-min-depth depth] [-max-depth depth] [-max-time time] [-depth-delta delta] @@ -78,6 +83,33 @@ DESCRIPTION PolyGlot can compile a pgn file into a binary PolyGlot book and fur- thermore it can merge two such binary books into a third one. + PolyGlot can also extract some useful information from PolyGlot books. + The utility "dump-book" dumps the "lines" in a book for a given color. + By definition a line is a sequence of moves (from the starting posi- + tion) in which the given color makes only book moves and the other + color makes arbitrary moves (i.e. not necessarily book moves). + + Since a PolyGlot book is built up from positions and not lines there + may be (and there usually are) many positions in the book that are not + on a "line" as defined in the previous paragraph. It is convenient to + call such positions "isolated" positions. The utility "info-book" + counts such isolated positions. + + Some of the isolated positions are provably unreachable and they could + in principle be deleted from the book. For example if a book contains + only the move "e4" in the starting position but also the position after + "d4 d5" then this last position is provably unreachable since it + requires white to make a non-book move when a book move is available. + Such situations arise frequently from the priority rules in merging + books. + + Unfortunately not all isolated positions are provably unreachable and + it is difficult to identify the latter. If invoked with "-exact" the + utility info-book will attempt to count the isolated positions which + require a player to make a non-book move when a book move is available. + Due to the possibility of transpositions this is not a fool proof + method. + Epd test mode In epd test mode, PolyGlot will search positions in an epd file and @@ -158,6 +190,34 @@ OPTIONS When invoked as + polyglot dump-book + + PolyGlot supports the following options + + -bin (default: book.bin) + Input file in PolyGlot book format. + + -color + The color for whom to generate the lines. + + -out (default: book_.txt) + The name of the output file. + + When invoked as + + polyglot info-book + + PolyGlot supports the following options + + -bin (default: book.bin) + Input file in PolyGlot book format. + + -exact + Attempt to count the provably unreachable positions among the iso- + lated ones. Note that this takes a very long time. + + When invoked as + polyglot epd-test (possibly with a config file as first argument) PolyGlot supports the @@ -434,4 +494,4 @@ SEE ALSO - 2009-01-14 POLYGLOT(6) + 2009-01-15 POLYGLOT(6) diff --git a/book_make.cpp b/book_make.cpp index ffffc9b..ba02f51 100644 --- a/book_make.cpp +++ b/book_make.cpp @@ -1,4 +1,3 @@ - // book_make.cpp // includes @@ -13,6 +12,7 @@ #include "book_make.h" #include "move.h" #include "move_do.h" +#include "move_gen.h" #include "move_legal.h" #include "pgn.h" #include "san.h" @@ -21,17 +21,31 @@ // constants static const int COUNT_MAX = 16384; +static const int StringSize = 4096; static const int NIL = -1; +// defines + +#define opp_search(s) ((s)==BOOK?ALL:BOOK) + // types struct entry_t { - uint64 key; - uint16 move; - uint16 n; - uint16 sum; - uint16 colour; + uint64 key; + uint16 move; + uint16 count; + union{ // unfortunately minggw32 seems to have a bug with anon unions. + struct { + uint16 n; + uint16 sum; + }; + struct{ + uint8 height; + int line; + }; + }; + uint8 colour; }; struct book_t { @@ -42,6 +56,24 @@ struct book_t { sint32 * hash; }; +enum search_t { + BOOK, + ALL +}; + +struct info_t { + int height; + int line; + int initial_color; + bool book_trans_only; + bool extended_search; + uint16 moves[1024]; + double probs[1024]; + uint64 keys[1024]; + FILE *output; +}; + + // variables static int MaxPly; @@ -49,6 +81,7 @@ static int MinGame; static double MinScore; static bool RemoveWhite, RemoveBlack; static bool Uniform; +static bool Quiet=false; static book_t Book[1]; @@ -71,6 +104,10 @@ static int entry_score (const entry_t * entry); static int key_compare (const void * p1, const void * p2); static void write_integer (FILE * file, int size, uint64 n); +static uint64 read_integer(FILE * file, int size); + +static void read_entry_file(FILE *f, entry_t *entry); +static void write_entry_file(FILE * f, const entry_t * entry); // functions @@ -332,9 +369,9 @@ static int find_entry(const board_t * board, int move) { int pos; ASSERT(board!=NULL); - ASSERT(move_is_ok(move)); + ASSERT(move==MoveNone || move_is_ok(move)); - ASSERT(move_is_legal(move,board)); + ASSERT(move==MoveNone || move_is_legal(move,board)); // init @@ -342,7 +379,7 @@ static int find_entry(const board_t * board, int move) { // search - for (index = key & Book->mask; (pos=Book->hash[index]) != NIL; index = (index+1) & Book->mask) { + for (index = key & (uint64) Book->mask; (pos=Book->hash[index]) != NIL; index = (index+1) & Book->mask) { ASSERT(pos>=0&&possize); @@ -361,7 +398,7 @@ static int find_entry(const board_t * board, int move) { resize(); - for (index = key & Book->mask; Book->hash[index] != NIL; index = (index+1) & Book->mask) + for (index = key & (uint64) Book->mask; Book->hash[index] != NIL; index = (index+1) & Book->mask) ; } @@ -387,13 +424,24 @@ static int find_entry(const board_t * board, int move) { return pos; } -// resize() +// rebuild_hash_table + +static void rebuild_hash_table(){ + int index,pos; + for (index = 0; index < Book->alloc*2; index++) { + Book->hash[index] = NIL; + } + for (pos = 0; pos < Book->size; pos++) { + for (index = Book->entry[pos].key & (uint64) Book->mask; Book->hash[index] != NIL; index = (index+1) & Book->mask) + ; + ASSERT(index>=0&&indexalloc*2); + Book->hash[index] = pos; + } +} static void resize() { int size; - int pos; - int index; ASSERT(Book->size==Book->alloc); @@ -403,7 +451,9 @@ static void resize() { size = 0; size += Book->alloc * sizeof(entry_t); size += (Book->alloc*2) * sizeof(sint32); - if (size >= 1048576) printf("allocating %gMB ...\n",double(size)/1048576.0); + + if (size >= 1048576) if(!Quiet){printf("allocating %gMB ...\n",double(size)/1048576.0);} + // resize arrays Book->entry = (entry_t *) my_realloc(Book->entry,Book->alloc*sizeof(entry_t)); @@ -411,20 +461,10 @@ static void resize() { // rebuild hash table - for (index = 0; index < Book->alloc*2; index++) { - Book->hash[index] = NIL; - } - - for (pos = 0; pos < Book->size; pos++) { - - for (index = Book->entry[pos].key & Book->mask; Book->hash[index] != NIL; index = (index+1) & Book->mask) - ; - - ASSERT(index>=0&&indexalloc*2); - Book->hash[index] = pos; - } + rebuild_hash_table(); } + // halve_stats() static void halve_stats(uint64 key) { @@ -434,7 +474,7 @@ static void halve_stats(uint64 key) { // search - for (index = key & Book->mask; (pos=Book->hash[index]) != NIL; index = (index+1) & Book->mask) { + for (index = key & (uint64) Book->mask; (pos=Book->hash[index]) != NIL; index = (index+1) & Book->mask) { ASSERT(pos>=0&&possize); @@ -536,5 +576,501 @@ static void write_integer(FILE * file, int size, uint64 n) { } } +// read_integer() + +static uint64 read_integer(FILE * file, int size) { + uint64 n; + int i; + int b; + ASSERT(file!=NULL); + ASSERT(size>0&&size<=8); + n = 0; + for (i = 0; i < size; i++) { + b = fgetc(file); + if (b == EOF) { + if (feof(file)) { + my_fatal("read_integer(): fgetc(): EOF reached\n"); + } else { // error + my_fatal("read_integer(): fgetc(): %s\n",strerror(errno)); + } + } + ASSERT(b>=0&&b<256); + n = (n << 8) | b; + } + return n; +} + +// read_entry_file + +static void read_entry_file(FILE *f, entry_t *entry){ + uint64 n; + ASSERT(entry!=NULL); + n = entry->key = read_integer(f,8); + entry->move = read_integer(f,2); + entry->count = read_integer(f,2); + entry->n = read_integer(f,2); + entry->sum = read_integer(f,2); + ASSERT(n==entry->key); // test for mingw compiler bug with anon structs +} + +// write_entry_file + +static void write_entry_file(FILE * f, const entry_t * entry) { + ASSERT(entry!=NULL); + write_integer(f,8,entry->key); + write_integer(f,2,entry->move); + write_integer(f,2,entry->count); + write_integer(f,2,entry->n); + write_integer(f,2,entry->sum); +} + +static void print_list(const board_t *board, list_t *list){ + int i; + uint16 move; + char move_string[256]; + for (i = 0; i < list_size(list); i++) { + move = list_move(list,i); + move_to_san(move,board,move_string,256); + printf("%s",move_string); + } + printf("\n"); +} + +// book_load() +// loads a polyglot book + +static void book_load(const char filename[]){ + FILE* f; + entry_t entry[1]; + int size; + int i; + int pos; + int index; + ASSERT(filename!=NULL); + if(!(f=fopen(filename,"rb"))){ + my_fatal("book_load() : can't open file \"%s\" for reading: %s\n",filename,strerror(errno)); + } + fseek(f,0L,SEEK_END); // superportable way to get size of book! + size=ftell(f)/16; + fseek(f,0,SEEK_SET); + for(i=0L;isize<=Book->alloc); + if (Book->size == Book->alloc) { + // allocate more memoryx + resize(); + } + // insert into the book + pos = Book->size++; + Book->entry[pos].key = entry->key; + ASSERT(entry->move!=MoveNone); + Book->entry[pos].move = entry->move; + Book->entry[pos].count = entry->count; + Book->entry[pos].n = entry->n; + Book->entry[pos].sum = entry->sum; + Book->entry[pos].colour = ColourNone; + // find free hash table spot + for (index = entry->key & (uint64) Book->mask; + Book->hash[index] != NIL; + index = (index+1) & Book->mask); + // insert into the hash table + ASSERT(index>=0&&indexalloc*2); + ASSERT(Book->hash[index]==NIL); + Book->hash[index] = pos; + ASSERT(pos>=0&&possize); + } + fclose(f); +} + +// gen_book_moves() +// similar signature as gen_legal_moves +static int gen_book_moves(list_t * list, const board_t * board){ + int first_pos, pos, index; + entry_t entry[1]; + list_clear(list); + bool found; + found=FALSE; + for (index = board->key & (uint64) Book->mask; (first_pos=Book->hash[index]) != NIL; index = (index+1) & Book->mask) { + ASSERT(first_pos>=0&&first_possize); + if (Book->entry[first_pos].key == board->key) { + found=TRUE; + break; // found + } + } + if(!found) return -1; + if(Book->entry[first_pos].move==MoveNone) return -1; + for (pos = first_pos; pos < Book->size; pos++) { + *entry=Book->entry[pos]; + if (entry->key != board->key) break; + if (entry->count > 0 && + entry->move != MoveNone && + move_is_legal(entry->move,board)) { + list_add(list,entry->move,entry->count); + } + } + return first_pos; +} + +// gen_opp_book_moves() +// moves to which opponent has a reply in book +// similar signature as gen_legal_moves +static void gen_opp_book_moves(list_t * list, const board_t * board){ + int move; + list_t new_list[1], legal_moves[1]; + board_t new_board[1]; + int i; + list_clear(list); + gen_legal_moves(legal_moves,board); + for (i = 0; i < list_size(legal_moves); i++) { + move = list_move(legal_moves,i); + // scratch_board + memcpy(new_board, board, sizeof(board_t)); + move_do(new_board,move); + gen_book_moves(new_list,new_board); // wasteful in time but tested! + if(list_size(new_list)!=0){ + list_add(list,move); + } + } +} + +static void print_moves(info_t *info){ + board_t board[1]; + char move_string[256]; + int i; + int color=White; + if(!info->output){ + return; + } + board_start(board); + for(i=0;iheight;i++){ + if(color==White){ + fprintf(info->output,"%d. ",i/2+1); + color=Black; + }else{ + color=White; + } + move_to_san(info->moves[i],board,move_string,256); + fprintf(info->output,"%s", move_string); + if(color==colour_opp(info->initial_color)){ + fprintf(info->output,"{%.0f%%} ",100*info->probs[i]); + }else{ + fprintf(info->output," "); + } + move_do(board,info->moves[i]); + } +} + +static int search_book(board_t *board, info_t *info, search_t search){ + list_t list[1]; + board_t new_board[1]; + uint16 move; + int count; + int ret; + int i; + int offset; + int pos; + int size; + int prob_sum; + double probs[256]; + for(i=0;i<256;i++){ + probs[i]=0.0; // kill compiler warnings + } + for(i=0;iheight;i++){ + if(board->key==info->keys[i]){ + if(info->output){ + fprintf(info->output,"%d: ",info->line); + print_moves(info); + fprintf(info->output,"{cycle: ply=%d}\n",i); + } + info->line++; + return 1; // end of line because of cycle + } + } + if(!info->book_trans_only || (info->book_trans_only && search==BOOK)){ + info->keys[info->height]=board->key; + size=Book->size; // hack + pos=find_entry(board,MoveNone); + if(size==Book->size){ + if(info->output){ + fprintf(info->output,"%d: ",info->line); + print_moves(info); + fprintf(info->output,"{trans: line=%d, ply=%d}\n", + Book->entry[pos].line, + Book->entry[pos].height); + } + info->line++; + return 1; // end of line because of transposition + }else{ + Book->entry[pos].height=info->height; + Book->entry[pos].line=info->line; + } + } + count=0; + if(search==BOOK){ + offset=gen_book_moves(list,board); + if(info->extended_search){ + gen_legal_moves(list,board); + } +// ASSERT(offset!=-1); + if(offset!=-1){ // only false in starting position for black book + Book->entry[offset].colour=board->turn; + prob_sum=0; + if(!info->extended_search){ + for(i=0;imoves[info->height++]=move; + if(search==BOOK){ + info->probs[info->height-1]=probs[i]; + } + ret=search_book(new_board, info, opp_search(search)); + if(ret==0 && search==BOOK){ + if(info->output){ + fprintf(info->output,"%d: ",info->line); + print_moves(info); + fprintf(info->output,"\n"); + } + info->line++; + ret=1; // end of line book move counts for 1 + } + info->height--; + ASSERT(info->height>=0); + count+=ret; + } + return count; +} + +void init_info(info_t *info){ + info->line=1; + info->height=0; + info->output=NULL; + info->initial_color=White; + info->book_trans_only=FALSE; +} + +// book_clean() +// remove MoveNone entries from book and rebuild hash table +void book_clean(){ + int read_ptr,write_ptr; + write_ptr=0; + for(read_ptr=0;read_ptrsize;read_ptr++){ + if(Book->entry[read_ptr].move!=MoveNone){ + Book->entry[write_ptr++]=Book->entry[read_ptr]; + } + } + Book->size=write_ptr; + rebuild_hash_table(); +} + +// book_dump() + +void book_dump(int argc, char * argv[]) { + const char * bin_file=NULL; + const char * txt_file=NULL; + char string[StringSize]; + int color=ColourNone; + board_t board[1]; + info_t info[1]; + int i; + FILE *f; + my_string_set(&bin_file,"book.bin"); + for (i = 1; i < argc; i++) { + if (false) { + } else if (my_string_equal(argv[i],"dump-book")) { + // skip + } else if (my_string_equal(argv[i],"-bin")) { + i++; + if (i==argc) my_fatal("book_dump(): missing argument\n"); + my_string_set(&bin_file,argv[i]); + } else if (my_string_equal(argv[i],"-out")) { + i++; + if (i==argc) my_fatal("book_dump(): missing argument\n"); + my_string_set(&txt_file,argv[i]); + } else if (my_string_equal(argv[i],"-color") || my_string_equal(argv[i],"-colour")) { + i++; + if (i == argc) my_fatal("book_dump(): missing argument\n"); + if(my_string_equal(argv[i],"white")){ + color=White; + }else if (my_string_equal(argv[i],"black")){ + color=Black; + }else{ + my_fatal("book_dump(): unknown color \"%s\"\n",argv[i]); + } + } else { + my_fatal("book_dump(): unknown option \"%s\"\n",argv[i]); + } + } + if(color==ColourNone){ + my_fatal("book_dump(): you must specify a color\n"); + } + if(txt_file==NULL){ + snprintf(string,StringSize,"book_%s.txt",color?"white":"black"); + my_string_set(&txt_file,string); + } + + book_clear(); + if(!Quiet){printf("loading book ...\n");} + book_load(bin_file); + board_start(board); + init_info(info); + info->initial_color=color; + if(!(f=fopen(txt_file,"w"))){ + my_fatal("book_dump(): can't open file \"%s\" for writing: %s", + txt_file,strerror(errno)); + } + info->output=f; + fprintf(info->output,"Dump of \"%s\" for %s.\n", + bin_file,color==White?"white":"black"); + if(color==White){ + if(!Quiet){printf("generating lines for white...\n");} + search_book(board,info, BOOK); + }else{ + if(!Quiet){printf("generating lines for black...\n");} + search_book(board,info, ALL); + } +} + +// book_info() + +void book_info(int argc,char* argv[]){ + const char *bin_file=NULL; + board_t board[1]; + info_t info[1]; + uint64 last_key; + int pos; + int white_pos,black_pos,total_pos,white_pos_extended, + black_pos_extended,white_pos_extended_diff,black_pos_extended_diff; + int s; + bool extended_search=FALSE; + int i; + Quiet=TRUE; + my_string_set(&bin_file,"book.bin"); + + for (i = 1; i < argc; i++) { + if (false) { + } else if (my_string_equal(argv[i],"info-book")) { + // skip + } else if (my_string_equal(argv[i],"-bin")) { + i++; + if (i==argc) my_fatal("book_info(): missing argument\n"); + my_string_set(&bin_file,argv[i]); + } else if (my_string_equal(argv[i],"-exact")) { + extended_search=TRUE; + } else { + my_fatal("book_info(): unknown option \"%s\"\n",argv[i]); + } + } + book_clear(); + if(!Quiet){printf("loading book ...\n");} + book_load(bin_file); + s=Book->size; + + board_start(board); + init_info(info); + info->book_trans_only=FALSE; + info->initial_color=White; + info->extended_search=FALSE; + search_book(board,info, BOOK); + printf("Lines for white : %8d\n",info->line-1); + + + info->line=1; + info->height=0; + info->initial_color=Black; + book_clean(); + ASSERT(Book->size==s); + board_start(board); + search_book(board,info, ALL); + printf("Lines for black : %8d\n",info->line-1); + + book_clean(); + ASSERT(Book->size==s); + white_pos=0; + black_pos=0; + total_pos=0; + last_key=0; + for(pos=0;possize;pos++){ + if(Book->entry[pos].key==last_key){ + ASSERT(Book->entry[pos].colour==ColourNone); + continue; + } + last_key=Book->entry[pos].key; + total_pos++; + if(Book->entry[pos].colour==White){ + white_pos++; + }else if(Book->entry[pos].colour==Black){ + black_pos++; + } + } + printf("Positions on lines for white : %8d\n",white_pos); + printf("Positions on lines for black : %8d\n",black_pos); + + + if(extended_search){ + init_info(info); + info->book_trans_only=TRUE; + info->initial_color=White; + info->extended_search=TRUE; + book_clean(); + board_start(board); + search_book(board,info, BOOK); + + init_info(info); + info->book_trans_only=TRUE; + info->initial_color=Black; + info->extended_search=TRUE; + book_clean(); + board_start(board); + search_book(board,info, ALL); + book_clean(); + ASSERT(Book->size==s); + white_pos_extended=0; + black_pos_extended=0; + last_key=0; + for(pos=0;possize;pos++){ + if(Book->entry[pos].key==last_key){ + ASSERT(Book->entry[pos].colour==ColourNone); + continue; + } + last_key=Book->entry[pos].key; + if(Book->entry[pos].colour==White){ + white_pos_extended++; + }else if(Book->entry[pos].colour==Black){ + black_pos_extended++; + } + } + white_pos_extended_diff=white_pos_extended-white_pos; + black_pos_extended_diff=black_pos_extended-black_pos; + printf("Unreachable white positions(?) : %8d\n", + white_pos_extended_diff); + printf("Unreachable black positions(?) : %8d\n", + black_pos_extended_diff); + + } + if(extended_search){ + printf("Isolated positions : %8d\n", + total_pos-white_pos_extended-black_pos_extended); + }else{ + printf("Isolated positions : %8d\n", + total_pos-white_pos-black_pos); + } +} + + + // end of book_make.cpp diff --git a/book_make.h b/book_make.h index 3302db4..f4054c0 100644 --- a/book_make.h +++ b/book_make.h @@ -11,6 +11,8 @@ // functions extern void book_make (int argc, char * argv[]); +extern void book_dump (int argc, char * argv[]); +extern void book_info (int argc, char * argv[]); #endif // !defined BOOK_MAKE_H diff --git a/config.h b/config.h index 2de88c9..f9a4be7 100644 --- a/config.h +++ b/config.h @@ -115,13 +115,13 @@ #define PACKAGE_NAME "polyglot" /* Define to the full name and version of this package. */ -#define PACKAGE_STRING "polyglot 1.4w10UCIb17" +#define PACKAGE_STRING "polyglot 1.4w10UCIb18" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "polyglot" /* Define to the version of this package. */ -#define PACKAGE_VERSION "1.4w10UCIb17" +#define PACKAGE_VERSION "1.4w10UCIb18" /* Define to 1 if the C compiler supports function prototypes. */ #define PROTOTYPES 1 @@ -150,7 +150,7 @@ #define TIME_WITH_SYS_TIME 1 /* Version number of package */ -#define VERSION "1.4w10UCIb17" +#define VERSION "1.4w10UCIb18" /* Define like PROTOTYPES; this can be used by system headers. */ #define __PROTOTYPES 1 diff --git a/configure b/configure index 77ab853..1dfe736 100755 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.61 for polyglot 1.4w10UCIb17. +# Generated by GNU Autoconf 2.61 for polyglot 1.4w10UCIb18. # # Report bugs to . # @@ -574,8 +574,8 @@ SHELL=${CONFIG_SHELL-/bin/sh} # Identity of this package. PACKAGE_NAME='polyglot' PACKAGE_TARNAME='polyglot' -PACKAGE_VERSION='1.4w10UCIb17' -PACKAGE_STRING='polyglot 1.4w10UCIb17' +PACKAGE_VERSION='1.4w10UCIb18' +PACKAGE_STRING='polyglot 1.4w10UCIb18' PACKAGE_BUGREPORT='michel.vandenbergh@uhasselt.be' ac_unique_file="mainloop.cpp" @@ -1216,7 +1216,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures polyglot 1.4w10UCIb17 to adapt to many kinds of systems. +\`configure' configures polyglot 1.4w10UCIb18 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1282,7 +1282,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of polyglot 1.4w10UCIb17:";; + short | recursive ) echo "Configuration of polyglot 1.4w10UCIb18:";; esac cat <<\_ACEOF @@ -1368,7 +1368,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -polyglot configure 1.4w10UCIb17 +polyglot configure 1.4w10UCIb18 generated by GNU Autoconf 2.61 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, @@ -1382,7 +1382,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by polyglot $as_me 1.4w10UCIb17, which was +It was created by polyglot $as_me 1.4w10UCIb18, which was generated by GNU Autoconf 2.61. Invocation command line was $ $0 $@ @@ -2072,7 +2072,7 @@ fi # Define the identity of the package. PACKAGE='polyglot' - VERSION='1.4w10UCIb17' + VERSION='1.4w10UCIb18' cat >>confdefs.h <<_ACEOF @@ -7344,7 +7344,7 @@ exec 6>&1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by polyglot $as_me 1.4w10UCIb17, which was +This file was extended by polyglot $as_me 1.4w10UCIb18, which was generated by GNU Autoconf 2.61. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -7397,7 +7397,7 @@ Report bugs to ." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF ac_cs_version="\\ -polyglot config.status 1.4w10UCIb17 +polyglot config.status 1.4w10UCIb18 configured by $0, generated by GNU Autoconf 2.61, with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\" diff --git a/configure.ac b/configure.ac index 1973b38..987344d 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ # Process this file with autoconf to produce a configure script. AC_PREREQ(2.61) -AC_INIT([polyglot], [1.4w10UCIb17], [michel.vandenbergh@uhasselt.be]) +AC_INIT([polyglot], [1.4w10UCIb18], [michel.vandenbergh@uhasselt.be]) AM_INIT_AUTOMAKE AC_CONFIG_SRCDIR([mainloop.cpp]) AC_CONFIG_HEADER([config.h]) diff --git a/engine.cpp b/engine.cpp index a898049..b674272 100644 --- a/engine.cpp +++ b/engine.cpp @@ -22,7 +22,7 @@ // constants -static const int StringSize = 4096; +static const unsigned int StringSize = 4096; // variables diff --git a/main.cpp b/main.cpp index b46be4a..83f1019 100644 --- a/main.cpp +++ b/main.cpp @@ -35,14 +35,17 @@ // constants -static const char * const Version = "1.4W10UCIb17"; +static const char * const Version = "1.4W10UCIb18"; static const char * const HelpMessage = "\ SYNTAX\n\ -polyglot [configfile]\n\ -polyglot make-book [-pgn inputfile] [-bin outputfile] [-max-ply ply] [-min-game games] [-min-score score] [-only-white] [-only-black] [-uniform]\n\ -polyglot merge-book -in1 inputfile1 -in2 inputfile2 [-out outputfile]\n\ -polyglot [configfile] epd-test [-epd inputfile] [-min-depth depth] [-max-depth depth] [-max-time time] [-depth-delta delta]\n\ -polyglot perft [-fen fen] [-max-depth depth]\ +* polyglot [configfile]\n\ +* polyglot -ec enginecommand\n\ +* polyglot make-book [-pgn inputfile] [-bin outputfile] [-max-ply ply] [-min-game games] [-min-score score] [-only-white] [-only-black] [-uniform]\n\ +* polyglot merge-book -in1 inputfile1 -in2 inputfile2 [-out outputfile]\n\ +* polyglot info-book [-bin inputfile] [-exact]\n\ +* polyglot dumb-book [-bin inputfile] -color color [-out outputfile]\n\ +* polyglot [configfile] epd-test [-epd inputfile] [-min-depth depth] [-max-depth depth] [-max-time time] [-depth-delta delta]\n\ +* polyglot perft [-fen fen] [-max-depth depth]\ "; static const int SearchDepth = 63; @@ -59,7 +62,6 @@ static void parse_option (); static void init_book (); static bool parse_line (char line[], char * * name_ptr, char * * value_ptr); static void stop_search (); -static void sig_quit(int); // functions @@ -101,6 +103,21 @@ int main(int argc, char * argv[]) { book_merge(argc,argv); return EXIT_SUCCESS; } + + if (argc >= 2 && my_string_equal(argv[1],"merge-book")) { + book_merge(argc,argv); + return EXIT_SUCCESS; + } + + if (argc >= 2 && my_string_equal(argv[1],"dump-book")) { + book_dump(argc,argv); + return EXIT_SUCCESS; + } + + if (argc >= 2 && my_string_equal(argv[1],"info-book")) { + book_info(argc,argv); + return EXIT_SUCCESS; + } if (argc >= 2 && my_string_equal(argv[1],"perft")) { do_perft(argc,argv); @@ -185,7 +202,6 @@ void polyglot_set_option(char *name, char *value){ // this must be cleaned up! // init_book() static void init_book(){ - const char *empty_var[]={}; book_clear(); if (option_get_bool("Book")){ my_log("POLYGLOT *** SETTING BOOK ***\n"); @@ -221,8 +237,6 @@ static void parse_option() { my_fatal("parse_option(): missing [Engine] section\n"); } - if(line[0]=='#') continue; - if (my_string_case_equal(line,"[engine]")) break; if (parse_line(line,&name,&value)) { @@ -249,8 +263,6 @@ static void parse_option() { Init = true; while (my_file_read_line(file,line,256)) { if (line[0] == '[') my_fatal("parse_option(): unknown section %s\n",line); - if (line[0]=='#') continue; - if (parse_line(line,&name,&value)) { uci_send_option(Uci,name,"%s",value); //to get a decent display in winboard_x we need to now if an engine really is doing multipv analysis diff --git a/option.cpp b/option.cpp index 0462000..5cb5024 100644 --- a/option.cpp +++ b/option.cpp @@ -81,7 +81,7 @@ void option_init() { option_t *p=Option; const char * name; - while(name=(p++)->name){ + while((name=(p++)->name)){ option_set(name,option_get_default(name)); } } diff --git a/parse.cpp b/parse.cpp index 9b12c38..f2340f4 100644 --- a/parse.cpp +++ b/parse.cpp @@ -83,7 +83,7 @@ bool parse_is_ok(const parse_t * parse) { if (parse == NULL) return false; if (parse->string == NULL) return false; - if (parse->pos < 0 || parse->pos > strlen(parse->string)) return false; + if (parse->pos < 0 || parse->pos > (int) strlen(parse->string)) return false; if (parse->keyword_nb < 0 || parse->keyword_nb >= KEYWORD_NUMBER) return false; return true; diff --git a/polyglot.man b/polyglot.man index e6d0ca8..e0dcef7 100644 --- a/polyglot.man +++ b/polyglot.man @@ -129,11 +129,11 @@ .\" ======================================================================== .\" .IX Title "POLYGLOT 6" -.TH POLYGLOT 6 "2009-01-14" "" "" +.TH POLYGLOT 6 "2009-01-15" "" "" .SH "NAME" PolyGlot \- Winboard protocol to UCI protocol adapter \- book engine for Polyglot books - \- a collection of utilities for creating opening books + \- a collection of utilities for creating and analyzing opening books \- a utility for analyzing epd files \- a perft counter .SH "SYNOPSIS" @@ -146,6 +146,10 @@ polyglot make-book [\-pgn inputfile] [\-bin outputfile] [\-max\-ply ply] [\-min\ .PP polyglot merge-book \-in1 inputfile1 \-in2 inputfile2 [\-out outputfile] .PP +polyglot info-book [\-bin inputfile] [\-exact] +.PP +polyglot dumb-book [\-bin inputfile] \-color color [\-out outputfile] +.PP polyglot [configfile] epd-test [\-epd inputfile] [\-min\-depth depth] [\-max\-depth depth] [\-max\-time time] [\-depth\-delta delta] .PP polyglot perft [\-fen fen] [\-max\-depth depth] @@ -200,7 +204,33 @@ Other opening book formats such as ChessBase's .ctg format and Arena's by their own GUIs. .PP PolyGlot can compile a pgn file into a binary PolyGlot book and furthermore -it can merge two such binary books into a third one. +it can merge two such binary books into a third one. +.PP +PolyGlot can also extract some useful information from PolyGlot books. The utility +\&\*(L"dump\-book\*(R" dumps the \*(L"lines\*(R" in a book for a given color. By definition +a line is a sequence of moves (from the starting position) in which +the given color makes only book moves and the other color makes +arbitrary moves (i.e. not necessarily book moves). +.PP +Since a PolyGlot book is built up from positions and not lines there +may be (and there usually are) many positions in the book that are not +on a \*(L"line\*(R" as defined in the previous paragraph. It is convenient +to call such positions \*(L"isolated\*(R" positions. The utility \*(L"info\-book\*(R" +counts such isolated positions. +.PP +Some of the isolated positions are provably unreachable and they +could in principle be deleted from the book. For example if a book +contains only the move \*(L"e4\*(R" in the starting position but also the +position after \*(L"d4 d5\*(R" then this last position is provably unreachable +since it requires white to make a non-book move when a book move is +available. Such situations arise frequently from the priority rules +in merging books. +.PP +Unfortunately not all isolated positions are provably unreachable and +it is difficult to identify the latter. If invoked with \*(L"\-exact\*(R" the +utility info-book will attempt to count the isolated positions which +require a player to make a non-book move when a book move is available. +Due to the possibility of transpositions this is not a fool proof method. .Sh "Epd test mode" .IX Subsection "Epd test mode" In epd test mode, PolyGlot will search positions in an epd file and @@ -277,6 +307,34 @@ Input files are not symmetrical, \*(L"in1\*(R" has priority over \*(L"in2\*(R". words when a position occurs both in \*(L"in1\*(R" and \*(L"in2\*(R" only the moves and weights from \*(L"in1\*(R" will be retained in \*(L"out\*(R". .PP +When invoked +as +.Sh "polyglot dump-book" +.IX Subsection "polyglot dump-book" +PolyGlot supports the following options +.IP "\fB\-bin\fR (default: book.bin)" 4 +.IX Item "-bin (default: book.bin)" +Input file in PolyGlot book format. +.IP "\fB\-color\fR" 4 +.IX Item "-color" +The color for whom to generate the lines. +.IP "\fB\-out\fR (default: book_.txt)" 4 +.IX Item "-out (default: book_.txt)" +The name of the output file. +.PP +When invoked +as +.Sh "polyglot info-book" +.IX Subsection "polyglot info-book" +PolyGlot supports the following options +.IP "\fB\-bin\fR (default: book.bin)" 4 +.IX Item "-bin (default: book.bin)" +Input file in PolyGlot book format. +.IP "\fB\-exact\fR" 4 +.IX Item "-exact" +Attempt to count the provably unreachable positions among the isolated ones. +Note that this takes a very long time. +.PP When invoked as .Sh "polyglot epd-test" .IX Subsection "polyglot epd-test" diff --git a/polyglot.pod b/polyglot.pod index db61280..0024cd1 100644 --- a/polyglot.pod +++ b/polyglot.pod @@ -2,7 +2,7 @@ PolyGlot - Winboard protocol to UCI protocol adapter - book engine for Polyglot books - - a collection of utilities for creating opening books + - a collection of utilities for creating and analyzing opening books - a utility for analyzing epd files - a perft counter @@ -16,6 +16,10 @@ polyglot make-book [-pgn inputfile] [-bin outputfile] [-max-ply ply] [-min-game polyglot merge-book -in1 inputfile1 -in2 inputfile2 [-out outputfile] +polyglot info-book [-bin inputfile] [-exact] + +polyglot dumb-book [-bin inputfile] -color color [-out outputfile] + polyglot [configfile] epd-test [-epd inputfile] [-min-depth depth] [-max-depth depth] [-max-time time] [-depth-delta delta] polyglot perft [-fen fen] [-max-depth depth] @@ -72,7 +76,33 @@ Other opening book formats such as ChessBase's .ctg format and Arena's by their own GUIs. PolyGlot can compile a pgn file into a binary PolyGlot book and furthermore -it can merge two such binary books into a third one. +it can merge two such binary books into a third one. + +PolyGlot can also extract some useful information from PolyGlot books. The utility +"dump-book" dumps the "lines" in a book for a given color. By definition +a line is a sequence of moves (from the starting position) in which +the given color makes only book moves and the other color makes +arbitrary moves (i.e. not necessarily book moves). + +Since a PolyGlot book is built up from positions and not lines there +may be (and there usually are) many positions in the book that are not +on a "line" as defined in the previous paragraph. It is convenient +to call such positions "isolated" positions. The utility "info-book" +counts such isolated positions. + +Some of the isolated positions are provably unreachable and they +could in principle be deleted from the book. For example if a book +contains only the move "e4" in the starting position but also the +position after "d4 d5" then this last position is provably unreachable +since it requires white to make a non-book move when a book move is +available. Such situations arise frequently from the priority rules +in merging books. + +Unfortunately not all isolated positions are provably unreachable and +it is difficult to identify the latter. If invoked with "-exact" the +utility info-book will attempt to count the isolated positions which +require a player to make a non-book move when a book move is available. +Due to the possibility of transpositions this is not a fool proof method. =head2 Epd test mode @@ -172,6 +202,49 @@ Input files are not symmetrical, "in1" has priority over "in2". In other words when a position occurs both in "in1" and "in2" only the moves and weights from "in1" will be retained in "out". +When invoked +as + +=head2 polyglot dump-book + +PolyGlot supports the following options + +=over 4 + +=item B<-bin> (default: book.bin) + +Input file in PolyGlot book format. + +=item B<-color> + +The color for whom to generate the lines. + +=item B<-out> (default: book_.txt) + +The name of the output file. + +=back + +When invoked +as + +=head2 polyglot info-book + +PolyGlot supports the following options + +=over 4 + +=item B<-bin> (default: book.bin) + +Input file in PolyGlot book format. + +=item B<-exact> + +Attempt to count the provably unreachable positions among the isolated ones. +Note that this takes a very long time. + +=back + When invoked as =head2 polyglot epd-test diff --git a/polyglot.spec b/polyglot.spec index 67a4465..959b69d 100644 --- a/polyglot.spec +++ b/polyglot.spec @@ -1,6 +1,6 @@ Summary: A Winboard protocol to UCI protocol adapter Name: polyglot -Version: 1.4w10UCIb17 +Version: 1.4w10UCIb18 Release: 1 License: GPL Group: Amusement/Games diff --git a/uci2uci.cpp b/uci2uci.cpp index 5dab703..a19b4da 100644 --- a/uci2uci.cpp +++ b/uci2uci.cpp @@ -146,9 +146,8 @@ static void format_uci_option_line(char * option_line,option_t *opt){ // send_uci_options() void send_uci_options() { - int i,j; + int i; option_t *p=Option; - const char * name; char option_line[StringSize]=""; gui_send(GUI,"id name %s", Uci->name); gui_send(GUI,"id author %s", Uci->author); @@ -171,7 +170,6 @@ void send_uci_options() { static void parse_setoption(const char string[]) { - parse_t parse[1]; char *name; char *pg_name; char *value; diff --git a/util.h b/util.h index 9449f12..759cd16 100644 --- a/util.h +++ b/util.h @@ -48,6 +48,10 @@ # define ASSERT(a) #endif +#ifdef _WIN32 +#define snprintf _snprintf +#endif + // types typedef signed char sint8; diff --git a/xboard2uci.cpp b/xboard2uci.cpp index ed241a0..1ffda48 100644 --- a/xboard2uci.cpp +++ b/xboard2uci.cpp @@ -479,7 +479,7 @@ void xboard_step(char string[]) { } else if (XB->has_feature_egt && match(string,"egtpath * *")){ char *type=Star[0]; char *path=Star[1]; - if(!my_string_case_equal(Star[0],"nalimov")){ + if(!my_string_case_equal(type,"nalimov")){ // refuse gui_send(GUI,"Error (unsupported table base format): %s",string); }else if(my_string_empty(path)){ @@ -1132,8 +1132,6 @@ static void search_update() { int move; int move_nb; board_t board[1]; - int nalimov_cache; - int real_memory; ASSERT(!Uci->searching); -- 1.7.0.4